mirror of
https://github.com/hanzoai/better-sqlite3-multiple-ciphers.git
synced 2026-09-24 16:57:19 +00:00
fixed bug in edge case
This commit is contained in:
+14
-5
@@ -1734,6 +1734,7 @@ int CustomTable::xBestIndex (sqlite3_vtab * vtab, sqlite3_index_info * output)
|
||||
{
|
||||
int parameter_count = VTab::Upcast(vtab)->parameter_count;
|
||||
int argument_count = 0;
|
||||
std::vector<std::pair<int, int>> forwarded;
|
||||
|
||||
for (int i = 0, len = output->nConstraint; i < len; ++i) {
|
||||
auto item = output->aConstraint[i];
|
||||
@@ -1753,10 +1754,18 @@ int CustomTable::xBestIndex (sqlite3_vtab * vtab, sqlite3_index_info * output)
|
||||
|
||||
return SQLITE_CONSTRAINT;
|
||||
}
|
||||
forwarded.emplace_back(item.iColumn, i);
|
||||
}
|
||||
}
|
||||
|
||||
output->aConstraintUsage[i].argvIndex = ++argument_count;
|
||||
output->aConstraintUsage[i].omit = 1;
|
||||
output->idxNum |= 1 << item.iColumn;
|
||||
|
||||
std::sort(forwarded.begin(), forwarded.end());
|
||||
for (std::pair<int, int> pair : forwarded) {
|
||||
int bit = 1 << pair.first;
|
||||
if (!(output->idxNum & bit)) {
|
||||
output->idxNum |= bit;
|
||||
output->aConstraintUsage[pair.second].argvIndex = ++argument_count;
|
||||
output->aConstraintUsage[pair.second].omit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1765,9 +1774,9 @@ int CustomTable::xBestIndex (sqlite3_vtab * vtab, sqlite3_index_info * output)
|
||||
output->estimatedCost = output->estimatedRows = 1000000000 / (argument_count + 1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
#line 378 "./src/util/custom-table.lzz"
|
||||
#line 387 "./src/util/custom-table.lzz"
|
||||
void CustomTable::PropagateJSError ()
|
||||
#line 378 "./src/util/custom-table.lzz"
|
||||
#line 387 "./src/util/custom-table.lzz"
|
||||
{
|
||||
assert(db->GetState()->was_js_error == false);
|
||||
db->GetState()->was_js_error = true;
|
||||
|
||||
+10
-10
@@ -663,17 +663,17 @@ private:
|
||||
static int xRowid (sqlite3_vtab_cursor * cursor, sqlite_int64 * output);
|
||||
#line 343 "./src/util/custom-table.lzz"
|
||||
static int xBestIndex (sqlite3_vtab * vtab, sqlite3_index_info * output);
|
||||
#line 378 "./src/util/custom-table.lzz"
|
||||
void PropagateJSError ();
|
||||
#line 383 "./src/util/custom-table.lzz"
|
||||
Addon * const addon;
|
||||
#line 384 "./src/util/custom-table.lzz"
|
||||
v8::Isolate * const isolate;
|
||||
#line 385 "./src/util/custom-table.lzz"
|
||||
Database * const db;
|
||||
#line 386 "./src/util/custom-table.lzz"
|
||||
std::string const name;
|
||||
#line 387 "./src/util/custom-table.lzz"
|
||||
void PropagateJSError ();
|
||||
#line 392 "./src/util/custom-table.lzz"
|
||||
Addon * const addon;
|
||||
#line 393 "./src/util/custom-table.lzz"
|
||||
v8::Isolate * const isolate;
|
||||
#line 394 "./src/util/custom-table.lzz"
|
||||
Database * const db;
|
||||
#line 395 "./src/util/custom-table.lzz"
|
||||
std::string const name;
|
||||
#line 396 "./src/util/custom-table.lzz"
|
||||
CopyablePersistent <v8::Function> const factory;
|
||||
};
|
||||
#line 64 "./src/util/data.lzz"
|
||||
|
||||
@@ -343,6 +343,7 @@ private:
|
||||
static int xBestIndex(sqlite3_vtab* vtab, sqlite3_index_info* output) {
|
||||
int parameter_count = VTab::Upcast(vtab)->parameter_count;
|
||||
int argument_count = 0;
|
||||
std::vector<std::pair<int, int>> forwarded;
|
||||
|
||||
for (int i = 0, len = output->nConstraint; i < len; ++i) {
|
||||
auto item = output->aConstraint[i];
|
||||
@@ -362,10 +363,18 @@ private:
|
||||
// could appear undefined in the generator function.
|
||||
return SQLITE_CONSTRAINT;
|
||||
}
|
||||
// Tell SQLite to forward arguments to xFilter.
|
||||
output->aConstraintUsage[i].argvIndex = ++argument_count;
|
||||
output->aConstraintUsage[i].omit = 1;
|
||||
output->idxNum |= 1 << item.iColumn;
|
||||
forwarded.emplace_back(item.iColumn, i);
|
||||
}
|
||||
}
|
||||
|
||||
// Tell SQLite to forward arguments to xFilter.
|
||||
std::sort(forwarded.begin(), forwarded.end());
|
||||
for (std::pair<int, int> pair : forwarded) {
|
||||
int bit = 1 << pair.first;
|
||||
if (!(output->idxNum & bit)) {
|
||||
output->idxNum |= bit;
|
||||
output->aConstraintUsage[pair.second].argvIndex = ++argument_count;
|
||||
output->aConstraintUsage[pair.second].omit = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -166,16 +166,56 @@ describe('Database#table()', function () {
|
||||
.to.throw(Database.SqliteError);
|
||||
});
|
||||
it('should correctly handle arguments even when used out of order', function () {
|
||||
const calls = [];
|
||||
this.db.table('vtab', {
|
||||
columns: ['x', 'y'],
|
||||
*rows(x, y) {
|
||||
calls.push([...arguments]);
|
||||
yield { x, y };
|
||||
},
|
||||
});
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$1" = ? AND "$2" = ?').get(10, 5))
|
||||
.to.deep.equal({ x: 10, y: 5 });
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 5]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = ? AND "$1" = ?').get(5, 10))
|
||||
.to.deep.equal({ x: 10, y: 5 });
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 5]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = ? AND "$2" = ? AND "$1" = ?').get(5, 5, 10))
|
||||
.to.deep.equal({ x: 10, y: 5 });
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 5]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = ? AND "$2" = ? AND "$1" = ?').get(5, 9, 10))
|
||||
.to.be.undefined;
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 5]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = ? AND "$2" = ? AND "$1" = ?').get(9, 5, 10))
|
||||
.to.be.undefined;
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 9]]);
|
||||
});
|
||||
it.skip('should correctly handle arguments that are constrained to other arguments', function () {
|
||||
// This test case fails due to a bug in SQLite (as of May 2021):
|
||||
// https://sqlite.org/forum/forumpost?udc=1&name=830d37b928&t=c
|
||||
const calls = [];
|
||||
this.db.table('vtab', {
|
||||
columns: ['x', 'y'],
|
||||
*rows(x, y) {
|
||||
calls.push([...arguments]);
|
||||
yield { x, y };
|
||||
},
|
||||
});
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$1" = ? AND "$2" = "$1"').get(10))
|
||||
.to.deep.equal({ x: 10, y: 10 });
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 10]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = "$1" AND "$1" = ?').get(10))
|
||||
.to.deep.equal({ x: 10, y: 10 });
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 10]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = ? AND "$2" = "$1" AND "$1" = ?').get(10, 10))
|
||||
.to.deep.equal({ x: 10, y: 10 });
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 10]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = ? AND "$2" = "$1" AND "$1" = ?').get(5, 10))
|
||||
.to.be.undefined;
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 5]]);
|
||||
expect(this.db.prepare('SELECT * FROM vtab WHERE "$2" = "$1" AND "$2" = ? AND "$1" = ?').get(5, 10))
|
||||
.to.be.undefined;
|
||||
expect(calls.splice(0)).to.deep.equal([[10, 10]]);
|
||||
});
|
||||
it('should throw an exception if the database is busy', function () {
|
||||
let ranOnce = false;
|
||||
|
||||
Reference in New Issue
Block a user