Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion db/comdb2.h
Original file line number Diff line number Diff line change
Expand Up @@ -1419,8 +1419,9 @@ struct ireq {

/* List of indices that we've written to detect uncommittable upsert txns */
hash_t *vfy_idx_hash;

int dup_key_insert;
/* Whether this txn has ignored upsert conflicts */
int upsert_ignored;

/* List of genids that we've written to detect uncommittable txn's */
hash_t *vfy_genid_hash;
Expand Down
4 changes: 2 additions & 2 deletions db/constraints.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,10 +1162,10 @@ int upsert_collision_should_force_verify_error(int flags, int ixnum)
- If the client did 'insert ... on conflict ...', then upsert_idx will
specify the index passed in the on conflict clause
- If the client did 'replace into ...', then upsert_idx will be
MAXINDEX + 1
MAXINDEX + 1 (UPSERT_CONFLICT_ALL_INDEXES)
*/
const int upsert_idx = flags >> 8;
return upsert_idx == ixnum || upsert_idx == MAXINDEX + 1;
return upsert_idx == ixnum || upsert_idx == UPSERT_CONFLICT_ALL_INDEXES;
}

int delayed_key_adds(struct ireq *iq, void *trans, int *blkpos, int *ixout,
Expand Down
1 change: 1 addition & 0 deletions db/handle_buf.c
Original file line number Diff line number Diff line change
Expand Up @@ -639,6 +639,7 @@ void *thd_req(void *vthd)
}
thd->iq->vfy_idx_track = 0;
thd->iq->dup_key_insert = 0;
thd->iq->upsert_ignored = 0;
#if 0
fprintf(stderr, "%s:%d: THD=%p relablk iq=%p\n", __func__, __LINE__, pthread_self(), thd->iq);
#endif
Expand Down
52 changes: 23 additions & 29 deletions db/indices.c
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,21 @@ int track_record_index(struct ireq *iq, int ixnum, void *key, int ixkeylen)
return is_dup;
}

static int check_upsert_index(struct ireq *iq, void *trans, int idx, blob_buffer_t *blobs, size_t maxblobs,
int *opfailcode, int *ixfailnum, int *retrc, void *od_dta, size_t od_len,
unsigned long long ins_keys)
{
/* Ignore dup keys */
if (iq->usedb->ix_dupes[idx]) {
return 0;
}
/* Check for partial keys only when needed. */
if (gbl_partial_indexes && iq->usedb->ix_partial && !(ins_keys & (1ULL << idx))) {
return 0;
}
return check_index(iq, trans, idx, blobs, maxblobs, opfailcode, ixfailnum, retrc, od_dta, od_len, ins_keys);
}

/* If a specific index has been used in the ON CONFLICT (idx) DO NOTHING
* clause (aka upsert target/index), then we must first perform check for
* that particular index and bail out (ignore) if there's a similar entry
Expand All @@ -277,42 +292,21 @@ int check_for_upsert(struct ireq *iq, void *trans, blob_buffer_t *blobs, size_t
int upsert_idx = rec_flags >> 8;

/* Perform the check for upsert index first. */
if (upsert_idx != MAXINDEX + 1) {

/* It must be a unique key. */
assert(iq->usedb->ix_dupes[upsert_idx] == 0);

/* Check for partial keys only when needed. */
if (gbl_partial_indexes && iq->usedb->ix_partial &&
!(ins_keys & (1ULL << upsert_idx))) {
/* NOOP */
} else {
rc = check_index(iq, trans, upsert_idx, blobs, maxblobs, opfailcode, ixfailnum, retrc, od_dta, od_len,
ins_keys);
if (rc) {
return rc;
}
if (upsert_idx != UPSERT_CONFLICT_ALL_INDEXES) {
rc = check_upsert_index(iq, trans, upsert_idx, blobs, maxblobs, opfailcode, ixfailnum, retrc, od_dta, od_len,
ins_keys);
if (rc) {
return rc;
}
}

for (int ixnum = 0; ixnum < iq->usedb->nix; ixnum++) {
/* Skip check for upsert index, was already checked above. */
if ((upsert_idx != MAXINDEX + 1) && (ixnum == upsert_idx)) {
continue;
}

/* Ignore dup keys */
if (iq->usedb->ix_dupes[ixnum] != 0) {
if ((upsert_idx != UPSERT_CONFLICT_ALL_INDEXES) && (ixnum == upsert_idx)) {
continue;
}

/* Check for partial keys only when needed. */
if (gbl_partial_indexes && iq->usedb->ix_partial &&
!(ins_keys & (1ULL << ixnum))) {
continue;
}

rc = check_index(iq, trans, ixnum, blobs, maxblobs, opfailcode, ixfailnum, retrc, od_dta, od_len, ins_keys);
rc = check_upsert_index(iq, trans, ixnum, blobs, maxblobs, opfailcode, ixfailnum, retrc, od_dta, od_len,
ins_keys);
if (rc) {
return rc;
}
Expand Down
3 changes: 3 additions & 0 deletions db/indices.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
#ifndef INCLUDED_INDICES_H
#define INCLUDED_INDICES_H

#include <cdb2_constants.h>
#define UPSERT_CONFLICT_ALL_INDEXES (MAXINDEX + 1)

int track_record_index(struct ireq *iq, int ixnum, void *key, int ixkeylen);

int check_for_upsert(struct ireq *iq, void *trans, blob_buffer_t *blobs, size_t maxblobs, int *opfailcode,
Expand Down
2 changes: 2 additions & 0 deletions db/osqlblockproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,6 +1183,8 @@ static int apply_changes(struct ireq *iq, blocksql_tran_t *tran, void *iq_tran,
hash_clear(iq->vfy_idx_hash);
}

iq->upsert_ignored = 0;

/* create a cursor */
dbc = bdb_temp_table_cursor(thedb->bdb_env, tran->db, NULL, &bdberr);
if (!dbc || bdberr) {
Expand Down
16 changes: 10 additions & 6 deletions db/osqlcomm.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
#include "logical_cron.h"
#include "sc_logic.h"
#include "eventlog.h"
#include "indices.h"
#include <disttxn.h>

#define MAX_CLUSTER REPMAX
Expand Down Expand Up @@ -7331,7 +7332,7 @@ int osql_process_packet(struct ireq *iq, uuid_t uuid, void *trans, char **pmsg,
get_keynm_from_db_idx(iq->usedb, err->ixnum),
iq->usedb->tablename, err->ixnum);
err->errcode = ERR_UNCOMMITTABLE_TXN;
goto done_delete;
goto done_insert;
}

if (upsert_collision_should_force_verify_error(dt.upsert_flags, err->ixnum)) {
Expand All @@ -7341,20 +7342,23 @@ int osql_process_packet(struct ireq *iq, uuid_t uuid, void *trans, char **pmsg,

if ((dt.upsert_flags & OSQL_IGNORE_FAILURE) != 0) {
const int upsert_idx = dt.upsert_flags >> 8;
if (upsert_idx == MAXINDEX + 1) {
if (upsert_idx == UPSERT_CONFLICT_ALL_INDEXES) {
/* We're asked to ignore DUPs for all unique indices, no insert took place.*/
iq->upsert_ignored = 1;
err->errcode = 0;
rc = 0;
goto done_delete;
goto done_insert;
} else if ((dt.upsert_flags & OSQL_FORCE_VERIFY) == 1) {
iq->upsert_ignored = 0;
err->errcode = 0;
rc = 0;
goto done_delete;
goto done_insert;
} else if (upsert_idx == err->ixnum) {
/* We're asked to ignore DUPs for this particular * index, no insert took place.*/
iq->upsert_ignored = 1;
err->errcode = 0;
rc = 0;
goto done_delete;
goto done_insert;
}
}

Expand All @@ -7377,7 +7381,7 @@ int osql_process_packet(struct ireq *iq, uuid_t uuid, void *trans, char **pmsg,
rrn, bdb_genid_to_host_order(newgenid));

if (0) {
done_delete:
done_insert:
EVENTLOG_DEBUG(
uuidstr_t ustr;
comdb2uuidstr(uuid, ustr);
Expand Down
5 changes: 5 additions & 0 deletions db/toblock.c
Original file line number Diff line number Diff line change
Expand Up @@ -5079,6 +5079,10 @@ static int toblock_main_int(struct javasp_trans_state *javasp_trans_handle, stru
} else {
nops += tmpnops;
iq->sorese->nops = nops;
if (tmpnops == 0 && iq->upsert_ignored) {
logmsg(LOGMSG_DEBUG, "upsert did not insert, skipping constraints\n");
goto serializable_check;
}
}
}

Expand Down Expand Up @@ -5230,6 +5234,7 @@ static int toblock_main_int(struct javasp_trans_state *javasp_trans_handle, stru
GOTOBACKOUT;
}

serializable_check:
Pthread_rwlock_rdlock(&commit_lock);
hascommitlock = 1;
if (iq->arr || iq->selectv_arr) {
Expand Down
Loading