re-add threadsafe, tests for drop column support

This commit is contained in:
Alex Garcia 2024-06-24 23:34:40 -07:00
parent dada170dc5
commit d5363ccde7
2 changed files with 56 additions and 30 deletions

View file

@ -3054,9 +3054,12 @@ int vec0_new_chunk(vec0_vtab *p, i64 *chunk_rowid) {
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return rc; return rc;
} }
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_enter) { if (sqlite3_mutex_enter) {
sqlite3_mutex_enter(sqlite3_db_mutex(p->db)); sqlite3_mutex_enter(sqlite3_db_mutex(p->db));
} }
#endif
sqlite3_bind_int64(stmt, 1, p->chunk_size); // size sqlite3_bind_int64(stmt, 1, p->chunk_size); // size
sqlite3_bind_zeroblob(stmt, 2, p->chunk_size / CHAR_BIT); // validity bitmap sqlite3_bind_zeroblob(stmt, 2, p->chunk_size / CHAR_BIT); // validity bitmap
@ -3065,9 +3068,11 @@ int vec0_new_chunk(vec0_vtab *p, i64 *chunk_rowid) {
rc = sqlite3_step(stmt); rc = sqlite3_step(stmt);
int failed = rc != SQLITE_DONE; int failed = rc != SQLITE_DONE;
rowid = sqlite3_last_insert_rowid(p->db); rowid = sqlite3_last_insert_rowid(p->db);
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_leave) { if (sqlite3_mutex_leave) {
sqlite3_mutex_leave(sqlite3_db_mutex(p->db)); sqlite3_mutex_leave(sqlite3_db_mutex(p->db));
} }
#endif
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
if (failed) { if (failed) {
return SQLITE_ERROR; return SQLITE_ERROR;
@ -3263,8 +3268,9 @@ static int vec0_init(sqlite3 *db, void *pAux, int argc, const char *const *argv,
int keyLength, valueLength; int keyLength, valueLength;
rc = vec0_parse_table_option(argv[i], strlen(argv[i]), &key, &keyLength, rc = vec0_parse_table_option(argv[i], strlen(argv[i]), &key, &keyLength,
&value, &valueLength); &value, &valueLength);
if(rc == SQLITE_ERROR) { if (rc == SQLITE_ERROR) {
*pzErr = sqlite3_mprintf( VEC_CONSTRUCTOR_ERROR "could not parse table option '%s'", argv[i]); *pzErr = sqlite3_mprintf(
VEC_CONSTRUCTOR_ERROR "could not parse table option '%s'", argv[i]);
goto error; goto error;
} }
if (rc == SQLITE_OK) { if (rc == SQLITE_OK) {
@ -3272,23 +3278,28 @@ static int vec0_init(sqlite3 *db, void *pAux, int argc, const char *const *argv,
chunk_size = atoi(value); chunk_size = atoi(value);
if (chunk_size <= 0) { if (chunk_size <= 0) {
// IMP: V01931_18769 // IMP: V01931_18769
*pzErr = sqlite3_mprintf( VEC_CONSTRUCTOR_ERROR "chunk_size must be a non-zero positive integer"); *pzErr =
sqlite3_mprintf(VEC_CONSTRUCTOR_ERROR
"chunk_size must be a non-zero positive integer");
goto error; goto error;
} }
if ((chunk_size % 8) != 0) { if ((chunk_size % 8) != 0) {
// IMP: V14110_30948 // IMP: V14110_30948
*pzErr = sqlite3_mprintf( VEC_CONSTRUCTOR_ERROR "chunk_size must be divisible by 8"); *pzErr = sqlite3_mprintf(VEC_CONSTRUCTOR_ERROR
"chunk_size must be divisible by 8");
goto error; goto error;
} }
} else { } else {
// IMP: V27642_11712 // IMP: V27642_11712
*pzErr = sqlite3_mprintf(VEC_CONSTRUCTOR_ERROR "Unknown table option: %.*s", keyLength, key); *pzErr = sqlite3_mprintf(
VEC_CONSTRUCTOR_ERROR "Unknown table option: %.*s", keyLength, key);
goto error; goto error;
} }
continue; continue;
} }
*pzErr = sqlite3_mprintf(VEC_CONSTRUCTOR_ERROR "Could not parse '%s'", argv[i]); *pzErr =
goto error; sqlite3_mprintf(VEC_CONSTRUCTOR_ERROR "Could not parse '%s'", argv[i]);
goto error;
} }
if (chunk_size < 0) { if (chunk_size < 0) {
@ -4355,9 +4366,11 @@ int vec0Update_InsertRowidStep(vec0_vtab *p, sqlite3_value *idValue,
return SQLITE_ERROR; return SQLITE_ERROR;
} }
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_enter) { if (sqlite3_mutex_enter) {
sqlite3_mutex_enter(sqlite3_db_mutex(p->db)); sqlite3_mutex_enter(sqlite3_db_mutex(p->db));
} }
#endif
sqlite3_bind_value(p->stmtRowidsInsertId, 1, idValue); sqlite3_bind_value(p->stmtRowidsInsertId, 1, idValue);
rc = sqlite3_step(p->stmtRowidsInsertId); rc = sqlite3_step(p->stmtRowidsInsertId);
@ -4383,9 +4396,11 @@ int vec0Update_InsertRowidStep(vec0_vtab *p, sqlite3_value *idValue,
complete: complete:
sqlite3_reset(p->stmtRowidsInsertId); sqlite3_reset(p->stmtRowidsInsertId);
sqlite3_clear_bindings(p->stmtRowidsInsertId); sqlite3_clear_bindings(p->stmtRowidsInsertId);
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_leave) { if (sqlite3_mutex_leave) {
sqlite3_mutex_leave(sqlite3_db_mutex(p->db)); sqlite3_mutex_leave(sqlite3_db_mutex(p->db));
} }
#endif
return rc; return rc;
} }
@ -4393,9 +4408,11 @@ int vec0Update_InsertRowidStep(vec0_vtab *p, sqlite3_value *idValue,
if (sqlite3_value_type(idValue) == SQLITE_INTEGER) { if (sqlite3_value_type(idValue) == SQLITE_INTEGER) {
i64 suppliedRowid = sqlite3_value_int64(idValue); i64 suppliedRowid = sqlite3_value_int64(idValue);
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_enter) { if (sqlite3_mutex_enter) {
sqlite3_mutex_enter(sqlite3_db_mutex(p->db)); sqlite3_mutex_enter(sqlite3_db_mutex(p->db));
} }
#endif
sqlite3_bind_int64(p->stmtRowidsInsertRowid, 1, suppliedRowid); sqlite3_bind_int64(p->stmtRowidsInsertRowid, 1, suppliedRowid);
rc = sqlite3_step(p->stmtRowidsInsertRowid); rc = sqlite3_step(p->stmtRowidsInsertRowid);
@ -4420,9 +4437,11 @@ int vec0Update_InsertRowidStep(vec0_vtab *p, sqlite3_value *idValue,
complete2: complete2:
sqlite3_reset(p->stmtRowidsInsertRowid); sqlite3_reset(p->stmtRowidsInsertRowid);
sqlite3_clear_bindings(p->stmtRowidsInsertRowid); sqlite3_clear_bindings(p->stmtRowidsInsertRowid);
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_leave) { if (sqlite3_mutex_leave) {
sqlite3_mutex_leave(sqlite3_db_mutex(p->db)); sqlite3_mutex_leave(sqlite3_db_mutex(p->db));
} }
#endif
return rc; return rc;
} }
@ -4435,10 +4454,11 @@ int vec0Update_InsertRowidStep(vec0_vtab *p, sqlite3_value *idValue,
p->tableName); p->tableName);
return SQLITE_ERROR; return SQLITE_ERROR;
} }
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_enter) { if (sqlite3_mutex_enter) {
sqlite3_mutex_enter(sqlite3_db_mutex(p->db)); sqlite3_mutex_enter(sqlite3_db_mutex(p->db));
} }
#endif
// no need to bind a value to ?1 here: needs to be NULL // no need to bind a value to ?1 here: needs to be NULL
// so we can get the next autoincremented rowid value. // so we can get the next autoincremented rowid value.
@ -4456,9 +4476,11 @@ int vec0Update_InsertRowidStep(vec0_vtab *p, sqlite3_value *idValue,
complete3: complete3:
sqlite3_reset(p->stmtRowidsInsertId); sqlite3_reset(p->stmtRowidsInsertId);
sqlite3_clear_bindings(p->stmtRowidsInsertId); sqlite3_clear_bindings(p->stmtRowidsInsertId);
#ifdef SQLITE_THREADSAFE
if (sqlite3_mutex_leave) { if (sqlite3_mutex_leave) {
sqlite3_mutex_leave(sqlite3_db_mutex(p->db)); sqlite3_mutex_leave(sqlite3_db_mutex(p->db));
} }
#endif
return rc; return rc;
} }

View file

@ -15,6 +15,7 @@ from math import isclose
EXT_PATH = "./dist/vec0" EXT_PATH = "./dist/vec0"
SUPPORTS_SUBTYPE = sqlite3.version_info[1] > 38 SUPPORTS_SUBTYPE = sqlite3.version_info[1] > 38
SUPPORTS_DROP_COLUMN = sqlite3.version_info[1] >= 35
def bitmap_full(n: int) -> bytearray: def bitmap_full(n: int) -> bytearray:
@ -604,14 +605,15 @@ def test_vec0_updates():
db.set_authorizer(None) db.set_authorizer(None)
# EVIDENCE-OF: V22053_06123 vec0 INSERT error on reading validity blob # EVIDENCE-OF: V22053_06123 vec0 INSERT error on reading validity blob
db.commit() if SUPPORTS_DROP_COLUMN:
db.execute("begin") db.commit()
db.execute("ALTER TABLE t1_chunks DROP COLUMN validity") db.execute("begin")
with _raises( db.execute("ALTER TABLE t1_chunks DROP COLUMN validity")
"Internal sqlite-vec error: could not open validity blob on main.t1_chunks.1" with _raises(
): "Internal sqlite-vec error: could not open validity blob on main.t1_chunks.1"
db.execute("insert into t1 values (9999, '[2,2,2,2]')") ):
db.rollback() db.execute("insert into t1 values (9999, '[2,2,2,2]')")
db.rollback()
# EVIDENCE-OF: V29362_13432 vec0 INSERT validity blob size mismatch with chunk_size # EVIDENCE-OF: V29362_13432 vec0 INSERT validity blob size mismatch with chunk_size
db.commit() db.commit()
@ -634,14 +636,15 @@ def test_vec0_updates():
db.rollback() db.rollback()
# EVIDENCE-OF: V09221_26060 vec0 INSERT rowids blob open error # EVIDENCE-OF: V09221_26060 vec0 INSERT rowids blob open error
db.commit() if SUPPORTS_DROP_COLUMN:
db.execute("begin") db.commit()
db.execute("ALTER TABLE t1_chunks DROP COLUMN rowids") db.execute("begin")
with _raises( db.execute("ALTER TABLE t1_chunks DROP COLUMN rowids")
"Internal sqlite-vec error: could not open rowids blob on main.t1_chunks.1" with _raises(
): "Internal sqlite-vec error: could not open rowids blob on main.t1_chunks.1"
db.execute("insert into t1 values (9999, '[2,2,2,2]')") ):
db.rollback() db.execute("insert into t1 values (9999, '[2,2,2,2]')")
db.rollback()
# EVIDENCE-OF: V12779_29618 vec0 INSERT rowids blob validates size # EVIDENCE-OF: V12779_29618 vec0 INSERT rowids blob validates size
db.commit() db.commit()
@ -964,14 +967,14 @@ def test_vec0_constructor():
): ):
db.execute("create virtual table v using vec0(chunk_size=7)") db.execute("create virtual table v using vec0(chunk_size=7)")
table_option_errors = ['chunk_size=', 'chunk_size=8 x'] table_option_errors = ["chunk_size=", "chunk_size=8 x"]
for x in table_option_errors: for x in table_option_errors:
with _raises( with _raises(
f"vec0 constructor error: could not parse table option '{x}'", f"vec0 constructor error: could not parse table option '{x}'",
sqlite3.DatabaseError, sqlite3.DatabaseError,
): ):
db.execute(f"create virtual table v using vec0({x})") db.execute(f"create virtual table v using vec0({x})")
with _raises( with _raises(
"vec0 constructor error: Could not parse '4'", "vec0 constructor error: Could not parse '4'",
@ -979,6 +982,7 @@ def test_vec0_constructor():
): ):
db.execute("create virtual table v using vec0(4)") db.execute("create virtual table v using vec0(4)")
def test_vec0_create_errors(): def test_vec0_create_errors():
# EVIDENCE-OF: V17740_01811 vec0 create _chunks error handling # EVIDENCE-OF: V17740_01811 vec0 create _chunks error handling
db.set_authorizer(authorizer_deny_on(sqlite3.SQLITE_CREATE_TABLE, "t1_chunks")) db.set_authorizer(authorizer_deny_on(sqlite3.SQLITE_CREATE_TABLE, "t1_chunks"))