Skip to content

Commit 1298c4b

Browse files
Copilotmathiasrw
andauthored
Let SERIAL columns handle explicitly provided values including NULL to fix #895 (#2204)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: mathiasrw <1063454+mathiasrw@users.noreply.github.com> Co-authored-by: Mathias Wulff <m@rawu.dk>
1 parent 8247c9e commit 1298c4b

File tree

2 files changed

+137
-2
lines changed

2 files changed

+137
-2
lines changed

src/60createtable.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,10 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
356356
for (var columnid in table.identities) {
357357
var ident = table.identities[columnid];
358358
// console.log(ident);
359-
r[columnid] = ident.value;
359+
// Only auto-assign identity value if not explicitly provided or if NULL
360+
if (typeof r[columnid] === 'undefined' || r[columnid] === null) {
361+
r[columnid] = ident.value;
362+
}
360363
// console.log(ident);
361364
}
362365
//console.log(270,r);
@@ -420,7 +423,17 @@ yy.CreateTable.prototype.execute = function (databaseid, params, cb) {
420423
for (var columnid in table.identities) {
421424
var ident = table.identities[columnid];
422425
// console.log(ident);
423-
ident.value += ident.step;
426+
// Only increment if we used the auto-generated value
427+
// If user provided explicit value >= current counter, update counter
428+
if (
429+
typeof r[columnid] !== 'undefined' &&
430+
r[columnid] !== null &&
431+
+r[columnid] >= ident.value
432+
) {
433+
ident.value = +r[columnid] + ident.step;
434+
} else {
435+
ident.value += ident.step;
436+
}
424437
// console.log(ident);
425438
}
426439

test/test895.js

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
if (typeof exports === 'object') {
2+
var assert = require('assert');
3+
var alasql = require('..');
4+
}
5+
6+
describe('Test 895 - SERIAL type should not overwrite explicitly provided values', function () {
7+
const testId = '895';
8+
9+
before(() => {
10+
alasql('create database test' + testId);
11+
alasql('use test' + testId);
12+
});
13+
14+
after(() => {
15+
alasql('drop database test' + testId);
16+
});
17+
18+
it('A) SERIAL column should auto-increment when not provided', () => {
19+
alasql(`
20+
CREATE TABLE users (id serial, name varchar(50));
21+
INSERT INTO users (name) VALUES ("first");
22+
INSERT INTO users (name) VALUES ("second");
23+
INSERT INTO users (name) VALUES ("third");
24+
`);
25+
var res = alasql('SELECT * FROM users ORDER BY id');
26+
assert.deepEqual(res, [
27+
{id: 1, name: 'first'},
28+
{id: 2, name: 'second'},
29+
{id: 3, name: 'third'},
30+
]);
31+
});
32+
33+
it('B) SERIAL column should accept explicitly provided value', () => {
34+
alasql(`
35+
CREATE TABLE products (id serial, name varchar(50));
36+
INSERT INTO products (id, name) VALUES (10, "first");
37+
INSERT INTO products (id, name) VALUES (20, "second");
38+
INSERT INTO products (id, name) VALUES (30, "third");
39+
`);
40+
var res = alasql('SELECT * FROM products ORDER BY id');
41+
assert.deepEqual(res, [
42+
{id: 10, name: 'first'},
43+
{id: 20, name: 'second'},
44+
{id: 30, name: 'third'},
45+
]);
46+
});
47+
48+
it('C) SERIAL column should accept explicitly provided value even if lower than counter', () => {
49+
alasql(`
50+
CREATE TABLE orders (id serial, name varchar(50));
51+
INSERT INTO orders (name) VALUES ("auto1");
52+
INSERT INTO orders (name) VALUES ("auto2");
53+
INSERT INTO orders (name) VALUES ("auto3");
54+
INSERT INTO orders (id, name) VALUES (100, "explicit");
55+
`);
56+
var res = alasql('SELECT * FROM orders ORDER BY id');
57+
assert.deepEqual(res, [
58+
{id: 1, name: 'auto1'},
59+
{id: 2, name: 'auto2'},
60+
{id: 3, name: 'auto3'},
61+
{id: 100, name: 'explicit'},
62+
]);
63+
});
64+
65+
it('D) SERIAL with mixed auto and explicit values', () => {
66+
alasql(`
67+
CREATE TABLE customers (id serial, name varchar(50));
68+
INSERT INTO customers (id, name) VALUES (5, "explicit5");
69+
INSERT INTO customers (name) VALUES ("auto");
70+
INSERT INTO customers (id, name) VALUES (10, "explicit10");
71+
INSERT INTO customers (name) VALUES ("auto2");
72+
`);
73+
var res = alasql('SELECT * FROM customers ORDER BY id');
74+
assert.deepEqual(res, [
75+
{id: 5, name: 'explicit5'},
76+
{id: 6, name: 'auto'},
77+
{id: 10, name: 'explicit10'},
78+
{id: 11, name: 'auto2'},
79+
]);
80+
});
81+
82+
it('E) Bulk insert with explicit SERIAL values', () => {
83+
alasql(`
84+
CREATE TABLE items (id serial, name varchar(50));
85+
INSERT INTO items (id, name) VALUES (4, "item4"), (8, "item8"), (12, "item12");
86+
`);
87+
var res = alasql('SELECT * FROM items ORDER BY id');
88+
assert.deepEqual(res, [
89+
{id: 4, name: 'item4'},
90+
{id: 8, name: 'item8'},
91+
{id: 12, name: 'item12'},
92+
]);
93+
});
94+
95+
it('F) Re-inserting data after truncate with explicit IDs', () => {
96+
alasql(`
97+
CREATE TABLE records (id serial, name varchar(50));
98+
INSERT INTO records (name) VALUES ("first"), ("second"), ("third");
99+
`);
100+
var res1 = alasql('SELECT * FROM records ORDER BY id');
101+
assert.deepEqual(res1, [
102+
{id: 1, name: 'first'},
103+
{id: 2, name: 'second'},
104+
{id: 3, name: 'third'},
105+
]);
106+
107+
// Simulate the flush scenario from the issue
108+
alasql(`
109+
DELETE FROM records;
110+
INSERT INTO records (id, name) VALUES (4, "item4");
111+
INSERT INTO records (id, name) VALUES (7, "item7");
112+
INSERT INTO records (id, name) VALUES (9, "item9");
113+
`);
114+
115+
var res2 = alasql('SELECT * FROM records ORDER BY id');
116+
assert.deepEqual(res2, [
117+
{id: 4, name: 'item4'},
118+
{id: 7, name: 'item7'},
119+
{id: 9, name: 'item9'},
120+
]);
121+
});
122+
});

0 commit comments

Comments
 (0)