Skip to content

Commit 47e332d

Browse files
authored
sqlite: read column count after step in StatementSync.all()
Signed-off-by: Guilherme Araújo <arauujogui@gmail.com> PR-URL: #64219 Reviewed-By: Edy Silva <edigleyssonsilva@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
1 parent 4a62a61 commit 47e332d

2 files changed

Lines changed: 74 additions & 1 deletion

File tree

src/node_sqlite.cc

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2865,12 +2865,16 @@ MaybeLocal<Value> StatementExecutionHelper::All(Environment* env,
28652865
Isolate* isolate = env->isolate();
28662866
EscapableHandleScope scope(isolate);
28672867
int r;
2868-
int num_cols = sqlite3_column_count(stmt);
2868+
int num_cols = 0;
28692869
LocalVector<Value> rows(isolate);
28702870
LocalVector<Value> row_values(isolate);
28712871
LocalVector<Name> row_keys(isolate);
28722872

28732873
while ((r = sqlite3_step(stmt)) == SQLITE_ROW) {
2874+
if (num_cols == 0) {
2875+
num_cols = sqlite3_column_count(stmt);
2876+
}
2877+
28742878
if (ExtractRowValues(env, stmt, num_cols, use_big_ints, &row_values)
28752879
.IsNothing()) {
28762880
return MaybeLocal<Value>();

test/parallel/test-sqlite-statement-sync.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,29 @@ suite('StatementSync.prototype.get()', () => {
5353
const stmt = db.prepare('SELECT 1 as __proto__, 2 as constructor, 3 as toString');
5454
t.assert.deepStrictEqual(stmt.get(), { __proto__: null, ['__proto__']: 1, constructor: 2, toString: 3 });
5555
});
56+
57+
test('reflects an added column after the schema changes', (t) => {
58+
using db = new DatabaseSync(':memory:');
59+
db.exec('CREATE TABLE storage(key TEXT, val TEXT)');
60+
db.prepare('INSERT INTO storage (key, val) VALUES (?, ?)').run('key1', 'val1');
61+
const stmt = db.prepare('SELECT * FROM storage ORDER BY key');
62+
db.exec("ALTER TABLE storage ADD COLUMN extra TEXT DEFAULT 'def'");
63+
t.assert.deepStrictEqual(stmt.get(), {
64+
__proto__: null, key: 'key1', val: 'val1', extra: 'def',
65+
});
66+
});
67+
68+
test('reflects a dropped column after the schema changes', (t) => {
69+
using db = new DatabaseSync(':memory:');
70+
db.exec('CREATE TABLE storage(key TEXT, val TEXT, extra TEXT)');
71+
db.prepare('INSERT INTO storage (key, val, extra) VALUES (?, ?, ?)')
72+
.run('key1', 'val1', 'x');
73+
const stmt = db.prepare('SELECT * FROM storage ORDER BY key');
74+
db.exec('ALTER TABLE storage DROP COLUMN extra');
75+
t.assert.deepStrictEqual(stmt.get(), {
76+
__proto__: null, key: 'key1', val: 'val1',
77+
});
78+
});
5679
});
5780

5881
suite('StatementSync.prototype.all()', () => {
@@ -83,6 +106,29 @@ suite('StatementSync.prototype.all()', () => {
83106
{ __proto__: null, key: 'key2', val: 'val2' },
84107
]);
85108
});
109+
110+
test('reflects an added column after the schema changes', (t) => {
111+
using db = new DatabaseSync(':memory:');
112+
db.exec('CREATE TABLE storage(key TEXT, val TEXT)');
113+
db.prepare('INSERT INTO storage (key, val) VALUES (?, ?)').run('key1', 'val1');
114+
const stmt = db.prepare('SELECT * FROM storage ORDER BY key');
115+
db.exec("ALTER TABLE storage ADD COLUMN extra TEXT DEFAULT 'def'");
116+
t.assert.deepStrictEqual(stmt.all(), [
117+
{ __proto__: null, key: 'key1', val: 'val1', extra: 'def' },
118+
]);
119+
});
120+
121+
test('reflects a dropped column after the schema changes', (t) => {
122+
using db = new DatabaseSync(':memory:');
123+
db.exec('CREATE TABLE storage(key TEXT, val TEXT, extra TEXT)');
124+
db.prepare('INSERT INTO storage (key, val, extra) VALUES (?, ?, ?)')
125+
.run('key1', 'val1', 'x');
126+
const stmt = db.prepare('SELECT * FROM storage ORDER BY key');
127+
db.exec('ALTER TABLE storage DROP COLUMN extra');
128+
t.assert.deepStrictEqual(stmt.all(), [
129+
{ __proto__: null, key: 'key1', val: 'val1' },
130+
]);
131+
});
86132
});
87133

88134
suite('StatementSync.prototype.iterate()', () => {
@@ -125,6 +171,29 @@ suite('StatementSync.prototype.iterate()', () => {
125171
}
126172
});
127173

174+
test('reflects an added column after the schema changes', (t) => {
175+
using db = new DatabaseSync(':memory:');
176+
db.exec('CREATE TABLE storage(key TEXT, val TEXT)');
177+
db.prepare('INSERT INTO storage (key, val) VALUES (?, ?)').run('key1', 'val1');
178+
const stmt = db.prepare('SELECT * FROM storage ORDER BY key');
179+
db.exec("ALTER TABLE storage ADD COLUMN extra TEXT DEFAULT 'def'");
180+
t.assert.deepStrictEqual(stmt.iterate().toArray(), [
181+
{ __proto__: null, key: 'key1', val: 'val1', extra: 'def' },
182+
]);
183+
});
184+
185+
test('reflects a dropped column after the schema changes', (t) => {
186+
using db = new DatabaseSync(':memory:');
187+
db.exec('CREATE TABLE storage(key TEXT, val TEXT, extra TEXT)');
188+
db.prepare('INSERT INTO storage (key, val, extra) VALUES (?, ?, ?)')
189+
.run('key1', 'val1', 'x');
190+
const stmt = db.prepare('SELECT * FROM storage ORDER BY key');
191+
db.exec('ALTER TABLE storage DROP COLUMN extra');
192+
t.assert.deepStrictEqual(stmt.iterate().toArray(), [
193+
{ __proto__: null, key: 'key1', val: 'val1' },
194+
]);
195+
});
196+
128197
test('iterator keeps the prepared statement from being collected', (t) => {
129198
const db = new DatabaseSync(':memory:');
130199
db.exec(`

0 commit comments

Comments
 (0)