Fix virtual table limit offset

* Don't care limit and offset constraints of user-defined virtual tables

* Add a test case for https://github.com/WiseLibs/better-sqlite3/issues/872

Co-authored-by: Ryusei Yamaguchi <[email protected]>
This commit is contained in:
Mahesh Bandara Wijerathna
2022-11-01 11:49:34 +05:30
co-authored by Ryusei Yamaguchi
parent 8b0ab0d99b
commit e99ea79d2a
4 changed files with 48 additions and 10 deletions
+9 -2
View File
@@ -1748,6 +1748,13 @@ int CustomTable::xBestIndex (sqlite3_vtab * vtab, sqlite3_index_info * output)
auto item = output->aConstraint[i];
if (item.op == SQLITE_INDEX_CONSTRAINT_LIMIT || item.op == SQLITE_INDEX_CONSTRAINT_OFFSET) {
continue;
}
if (item.iColumn >= 0 && item.iColumn < parameter_count) {
if (item.op != SQLITE_INDEX_CONSTRAINT_EQ) {
sqlite3_free(vtab->zErrMsg);
@@ -1782,9 +1789,9 @@ int CustomTable::xBestIndex (sqlite3_vtab * vtab, sqlite3_index_info * output)
output->estimatedCost = output->estimatedRows = 1000000000 / (argument_count + 1);
return SQLITE_OK;
}
#line 387 "./src/util/custom-table.lzz"
#line 394 "./src/util/custom-table.lzz"
void CustomTable::PropagateJSError ()
#line 387 "./src/util/custom-table.lzz"
#line 394 "./src/util/custom-table.lzz"
{
assert(db->GetState()->was_js_error == false);
db->GetState()->was_js_error = true;
+8 -8
View File
@@ -666,17 +666,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 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"
void PropagateJSError ();
#line 399 "./src/util/custom-table.lzz"
Addon * const addon;
#line 400 "./src/util/custom-table.lzz"
v8::Isolate * const isolate;
#line 401 "./src/util/custom-table.lzz"
Database * const db;
#line 395 "./src/util/custom-table.lzz"
#line 402 "./src/util/custom-table.lzz"
std::string const name;
#line 396 "./src/util/custom-table.lzz"
#line 403 "./src/util/custom-table.lzz"
CopyablePersistent <v8::Function> const factory;
};
#line 65 "./src/util/data.lzz"
+7
View File
@@ -348,6 +348,13 @@ private:
for (int i = 0, len = output->nConstraint; i < len; ++i) {
auto item = output->aConstraint[i];
// The SQLITE_INDEX_CONSTRAINT_LIMIT and SQLITE_INDEX_CONSTRAINT_OFFSET
// operators have no left-hand operand, and so for those operators the
// corresponding item.iColumn is meaningless.
// We don't care those constraints.
if (item.op == SQLITE_INDEX_CONSTRAINT_LIMIT || item.op == SQLITE_INDEX_CONSTRAINT_OFFSET) {
continue;
}
// We only care about constraints on parameters, not regular columns.
if (item.iColumn >= 0 && item.iColumn < parameter_count) {
if (item.op != SQLITE_INDEX_CONSTRAINT_EQ) {
+24
View File
@@ -668,4 +668,28 @@ describe('Database#table()', function () {
throw new TypeError('Expected the statement to throw an exception');
});
});
it('should correctly handle limit and offset clause', function () {
let lastValue;
this.db.table('vtab', {
columns: ['x'],
*rows() {
lastValue = 1;
yield { x: lastValue };
lastValue = 2;
yield { x: lastValue };
lastValue = 3;
yield { x: lastValue };
lastValue = null;
},
});
expect(this.db.prepare('SELECT * FROM vtab LIMIT 1').all())
.to.deep.equal([{ x: 1 }]);
expect(lastValue).to.equal(1);
expect(this.db.prepare('SELECT * FROM vtab LIMIT 1 OFFSET 2').all())
.to.deep.equal([{ x: 3 }]);
expect(lastValue).to.equal(3);
expect(this.db.prepare('SELECT * FROM vtab LIMIT 100 OFFSET 1').all())
.to.deep.equal([{ x: 2 }, { x: 3 }]);
expect(lastValue).to.be.null;
});
});