Skip to content

Commit 64031a6

Browse files
authored
refactor: Quoted identifiers (#97)
1 parent 2db5627 commit 64031a6

File tree

11 files changed

+100
-57
lines changed

11 files changed

+100
-57
lines changed

src/connection/connection_v2.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -152,10 +152,10 @@ export class ConnectionV2 extends BaseConnection {
152152

153153
if (this.accountInfo.infraVersion >= 2) {
154154
if (database) {
155-
await this.execute(`USE DATABASE ${database}`);
155+
await this.execute(`USE DATABASE "${database}"`);
156156
}
157157
if (engineName) {
158-
await this.execute(`USE ENGINE ${engineName}`);
158+
await this.execute(`USE ENGINE "${engineName}"`);
159159
}
160160
} else {
161161
if (engineName && database) {

src/service/engine/model.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ export class EngineModel {
1717
}
1818

1919
async start() {
20-
const query = `START ENGINE ${this.name}`;
20+
const query = `START ENGINE "${this.name}"`;
2121
await this.connection.execute(query);
2222
await this.refreshStatus();
2323
const res: Engine = {
@@ -34,7 +34,7 @@ export class EngineModel {
3434
}
3535

3636
async stop() {
37-
const query = `STOP ENGINE ${this.name}`;
37+
const query = `STOP ENGINE "${this.name}"`;
3838
await this.connection.execute(query);
3939
await this.refreshStatus();
4040
const res: Engine = {

test/integration/v1/bytea.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,19 @@ describe("bytea", () => {
5353

5454
const connection = await firebolt.connect(connectionParams);
5555

56-
await connection.execute("CREATE TABLE bytea_test (id int, data bytea)");
56+
await connection.execute('CREATE TABLE "bytea_test" (id int, data bytea)');
5757
const bytea_value = Buffer.from("hello_world_123ツ\n\u0048");
5858

59-
await connection.execute("INSERT INTO bytea_test VALUES (1, ?::bytea)", {
59+
await connection.execute('INSERT INTO "bytea_test" VALUES (1, ?::bytea)', {
6060
parameters: [bytea_value]
6161
});
6262

63-
const statement = await connection.execute("SELECT data FROM bytea_test");
63+
const statement = await connection.execute('SELECT data FROM "bytea_test"');
6464

6565
const { data, meta } = await statement.fetchResult();
6666
expect(meta[0].type).toEqual("bytea");
6767
const row = data[0];
6868
expect((row as unknown[])[0]).toEqual(bytea_value);
69-
await connection.execute("DROP TABLE IF EXISTS bytea_test");
69+
await connection.execute('DROP TABLE IF EXISTS "bytea_test"');
7070
});
7171
});

test/integration/v1/date.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ const connectionParams = {
1212
jest.setTimeout(100000);
1313

1414
const dml = `
15-
CREATE FACT TABLE IF NOT EXISTS t1
15+
CREATE FACT TABLE IF NOT EXISTS "t1"
1616
(
1717
id INT NOT NULL,
1818
description TEXT NULL,
@@ -25,7 +25,7 @@ PRIMARY INDEX id;
2525
`;
2626

2727
const insertValues = `
28-
INSERT INTO t1 VALUES
28+
INSERT INTO "t1" VALUES
2929
(1, 'fitst value', '0001-01-01', '0001-01-01 00:00:00.000000 UTC', '0001-01-01 00:00:00.000000', TRUE),
3030
(2, 'second value', '0301-05-08', '0342-01-12 15:16:00.000000 UTC', '0343-12-01 12:14:00.000000', TRUE),
3131
(3, 'thirds value', '1500-12-10', '1479-01-01 00:00:00.000000 UTC', '1562-01-11 00:00:22.000000', TRUE),
@@ -45,7 +45,7 @@ describe("new date data format", () => {
4545
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
4646
});
4747
const connection = await firebolt.connect(connectionParams);
48-
await connection.execute(`drop table if exists t1`);
48+
await connection.execute(`drop table if exists "t1"`);
4949
} catch (e) {
5050
console.log(e);
5151
}
@@ -60,7 +60,7 @@ describe("new date data format", () => {
6060

6161
await connection.execute(dml);
6262
await connection.execute(insertValues);
63-
const statement = await connection.execute(`select * from t1 limit 10`);
63+
const statement = await connection.execute(`select * from "t1" limit 10`);
6464
const { data, meta } = await statement.fetchResult();
6565
expect(meta[2].type).toEqual("date");
6666
expect(meta[3].type).toEqual("timestamptz");

test/integration/v1/systemEngine.test.ts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,25 +25,27 @@ describe("system engine", () => {
2525
});
2626

2727
await connection
28-
.execute(`drop engine if exists ${engineName}`)
28+
.execute(`drop engine if exists "${engineName}"`)
2929
.catch(error => {
3030
console.log(error);
3131
});
3232

3333
await connection
34-
.execute(`drop database if exists ${databaseName}`)
34+
.execute(`drop database if exists "${databaseName}"`)
3535
.catch(error => {
3636
console.log(error);
3737
});
3838
try {
39-
await connection.execute(`create database if not exists ${databaseName}`);
39+
await connection.execute(
40+
`create database if not exists "${databaseName}"`
41+
);
4042

4143
await connection.execute(
42-
`create engine if not exists ${engineName} with REGION = 'us-east-1' SPEC = 'B1' SCALE = 1`
44+
`create engine if not exists "${engineName}" with REGION = 'us-east-1' SPEC = 'B1' SCALE = 1`
4345
);
4446

4547
await connection.execute(
46-
`attach engine ${engineName} to ${databaseName}`
48+
`attach engine "${engineName}" to "${databaseName}"`
4749
);
4850
} catch (error) {
4951
console.log(error);
@@ -62,8 +64,8 @@ describe("system engine", () => {
6264
});
6365

6466
try {
65-
await connection.execute(`drop engine if exists ${engineName}`);
66-
await connection.execute(`drop database if exists ${databaseName}`);
67+
await connection.execute(`drop engine if exists "${engineName}"`);
68+
await connection.execute(`drop database if exists "${databaseName}"`);
6769
} catch (error) {
6870
console.log(error);
6971
expect(true).toEqual(false);
@@ -134,8 +136,8 @@ describe("system engine", () => {
134136
});
135137

136138
try {
137-
await connection.execute(`start engine ${engineName}`);
138-
await connection.execute(`stop engine ${engineName}`);
139+
await connection.execute(`start engine "${engineName}"`);
140+
await connection.execute(`stop engine "${engineName}"`);
139141
} catch (error) {
140142
console.log(error);
141143
expect(true).toEqual(false);

test/integration/v2/bytea.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,20 +55,20 @@ describe("bytea", () => {
5555
const connection = await firebolt.connect(connectionParams);
5656

5757
await connection.execute(
58-
"CREATE TABLE bytea_test (id int, data bytea not null)"
58+
'CREATE TABLE "bytea_test" (id int, data bytea not null)'
5959
);
6060
const bytea_value = Buffer.from("hello_world_123ツ\n\u0048");
6161

62-
await connection.execute("INSERT INTO bytea_test VALUES (1, ?::bytea)", {
62+
await connection.execute('INSERT INTO "bytea_test" VALUES (1, ?::bytea)', {
6363
parameters: [bytea_value]
6464
});
6565

66-
const statement = await connection.execute("SELECT data FROM bytea_test");
66+
const statement = await connection.execute('SELECT data FROM "bytea_test"');
6767

6868
const { data, meta } = await statement.fetchResult();
6969
expect(meta[0].type).toEqual("bytea");
7070
const row = data[0];
7171
expect((row as unknown[])[0]).toEqual(bytea_value);
72-
await connection.execute("DROP TABLE IF EXISTS bytea_test");
72+
await connection.execute('DROP TABLE IF EXISTS "bytea_test"');
7373
});
7474
});

test/integration/v2/date.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ const connectionParams = {
1313
jest.setTimeout(100000);
1414

1515
const dml = `
16-
CREATE FACT TABLE IF NOT EXISTS t1
16+
CREATE FACT TABLE IF NOT EXISTS "t1"
1717
(
1818
id INT NOT NULL,
1919
description TEXT NULL,
@@ -26,7 +26,7 @@ PRIMARY INDEX id;
2626
`;
2727

2828
const insertValues = `
29-
INSERT INTO t1 VALUES
29+
INSERT INTO "t1" VALUES
3030
(1, 'fitst value', '0001-01-01', '0001-01-01 00:00:00.000000 UTC', '0001-01-01 00:00:00.000000', TRUE),
3131
(2, 'second value', '0301-05-08', '0342-01-12 15:16:00.000000 UTC', '0343-12-01 12:14:00.000000', TRUE),
3232
(3, 'thirds value', '1500-12-10', '1479-01-01 00:00:00.000000 UTC', '1562-01-11 00:00:22.000000', TRUE),
@@ -46,7 +46,7 @@ describe("new date data format", () => {
4646
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
4747
});
4848
const connection = await firebolt.connect(connectionParams);
49-
await connection.execute(`drop table if exists t1`);
49+
await connection.execute(`drop table if exists "t1"`);
5050
} catch (e) {
5151
console.log(e);
5252
}
@@ -61,7 +61,7 @@ describe("new date data format", () => {
6161

6262
await connection.execute(dml);
6363
await connection.execute(insertValues);
64-
const statement = await connection.execute(`select * from t1 limit 10`);
64+
const statement = await connection.execute(`select * from "t1" limit 10`);
6565
const { data, meta } = await statement.fetchResult();
6666
expect(meta[2].type).toEqual("date"); // PGDate is aliased as date
6767
expect(meta[3].type).toEqual("timestamptz");

test/integration/v2/index.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,10 @@ describe("new identity integration test", () => {
8080
});
8181

8282
await connection.execute(
83-
"CREATE TABLE IF NOT EXISTS dummy_connectivity_test (id INT)"
83+
'CREATE TABLE IF NOT EXISTS "dummy_connectivity_test" (id INT)'
8484
);
8585
const statement = await connection.execute(
86-
"SELECT * FROM dummy_connectivity_test"
86+
'SELECT * FROM "dummy_connectivity_test"'
8787
);
8888
const { data, meta } = await statement.fetchResult();
8989
expect(data.length).toEqual(0);
@@ -101,10 +101,10 @@ describe("new identity integration test", () => {
101101
});
102102

103103
await connection.execute(
104-
"CREATE TABLE IF NOT EXISTS dummy_connectivity_test (id INT)"
104+
'CREATE TABLE IF NOT EXISTS "dummy_connectivity_test" (id INT)'
105105
);
106106
const statement = await connection.execute(
107-
"SELECT * FROM dummy_connectivity_test"
107+
'SELECT * FROM "dummy_connectivity_test"'
108108
);
109109
const { data, meta } = await statement.fetchResult();
110110
expect(data.length).toEqual(0);

test/integration/v2/infraV2.test.ts

Lines changed: 48 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ const connectionParams = {
1414
engineName: process.env.FIREBOLT_ENGINE_NAME as string
1515
};
1616

17+
const mixedCaseDBName = process.env.FIREBOLT_DATABASE + "MiXeDcAsE";
18+
const mixedCaseEngineName = process.env.FIREBOLT_ENGINE_NAME + "MiXeDcAsE";
19+
1720
jest.setTimeout(500000);
1821

1922
describe("infra v2 integration test", () => {
@@ -23,10 +26,10 @@ describe("infra v2 integration test", () => {
2326
});
2427
const connection = await firebolt.connect(systemEngineConnectionParams);
2528
await connection.execute(
26-
`CREATE ENGINE IF NOT EXISTS ${connectionParams.engineName}`
29+
`CREATE ENGINE IF NOT EXISTS "${connectionParams.engineName}"`
2730
);
2831
await connection.execute(
29-
`CREATE DATABASE IF NOT EXISTS ${connectionParams.database}`
32+
`CREATE DATABASE IF NOT EXISTS "${connectionParams.database}"`
3033
);
3134
});
3235

@@ -35,13 +38,20 @@ describe("infra v2 integration test", () => {
3538
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
3639
});
3740
const connection = await firebolt.connect(systemEngineConnectionParams);
38-
await connection.execute(`STOP ENGINE ${connectionParams.engineName}`);
41+
await connection.execute(`STOP ENGINE "${connectionParams.engineName}"`);
3942
await connection.execute(
40-
`DROP ENGINE IF EXISTS ${connectionParams.engineName}`
43+
`DROP ENGINE IF EXISTS "${connectionParams.engineName}"`
4144
);
4245
await connection.execute(
43-
`DROP DATABASE IF EXISTS ${connectionParams.database}`
46+
`DROP DATABASE IF EXISTS "${connectionParams.database}"`
4447
);
48+
try {
49+
await connection.execute(`STOP ENGINE "${mixedCaseEngineName}"`);
50+
} catch (error) {
51+
// Ignore the error if the engine does not exist
52+
}
53+
await connection.execute(`DROP ENGINE IF EXISTS "${mixedCaseEngineName}"`);
54+
await connection.execute(`DROP DATABASE IF EXISTS "${mixedCaseDBName}"`);
4555
});
4656

4757
it("connects", async () => {
@@ -65,7 +75,7 @@ describe("infra v2 integration test", () => {
6575
const connection = await firebolt.connect(systemEngineConnectionParams);
6676

6777
const engine_name = process.env.FIREBOLT_ENGINE_NAME as string;
68-
await connection.execute(`USE ENGINE ${engine_name}`);
78+
await connection.execute(`USE ENGINE "${engine_name}"`);
6979

7080
const statement = await connection.execute("SELECT 1");
7181
const { data, meta } = await statement.fetchResult();
@@ -75,8 +85,8 @@ describe("infra v2 integration test", () => {
7585

7686
it("supports use database and use engine", async () => {
7787
const table_name = "test_use_database";
78-
const create_table_sql = `create table if not exists ${table_name} (id text)`;
79-
const insert_sql = `insert into ${table_name} values ('1')`;
88+
const create_table_sql = `create table if not exists "${table_name}" (id text)`;
89+
const insert_sql = `insert into "${table_name}" values ('1')`;
8090

8191
const database_name = process.env.FIREBOLT_DATABASE as string;
8292
const engine_name = process.env.FIREBOLT_ENGINE_NAME as string;
@@ -89,17 +99,44 @@ describe("infra v2 integration test", () => {
8999
// should not create table when database is not specified
90100
await expect(connection.execute(create_table_sql)).rejects.toThrow();
91101

92-
await connection.execute(`use database ${database_name}`);
102+
await connection.execute(`use database "${database_name}"`);
93103
await connection.execute(create_table_sql);
94104

95105
await expect(connection.execute(insert_sql)).rejects.toThrow();
96106

97-
await connection.execute(`use engine ${engine_name}`);
107+
await connection.execute(`use engine "${engine_name}"`);
98108

99109
await connection.execute(insert_sql);
100110

101-
await connection.execute(`use engine system`);
111+
await connection.execute(`use engine "system"`);
102112

103113
await expect(connection.execute(insert_sql)).rejects.toThrow();
104114
});
115+
116+
it("can handle mixed case engines and db", async () => {
117+
const table_name = "test_mixed_case_database";
118+
const create_table_sql = `create table if not exists "${table_name}" (id text)`;
119+
const insert_sql = `insert into "${table_name}" values ('1')`;
120+
121+
const firebolt = Firebolt({
122+
apiEndpoint: process.env.FIREBOLT_API_ENDPOINT as string
123+
});
124+
125+
const connection = await firebolt.connect(systemEngineConnectionParams);
126+
127+
await connection.execute(`CREATE DATABASE "${mixedCaseDBName}"`);
128+
await connection.execute(`CREATE ENGINE "${mixedCaseEngineName}"`);
129+
130+
const mixedCaseConnectionParams = {
131+
...systemEngineConnectionParams,
132+
database: mixedCaseDBName,
133+
engineName: mixedCaseEngineName
134+
};
135+
136+
const mixedCaseConnection = await firebolt.connect(
137+
mixedCaseConnectionParams
138+
);
139+
await mixedCaseConnection.execute(create_table_sql);
140+
await mixedCaseConnection.execute(insert_sql);
141+
});
105142
});

0 commit comments

Comments
 (0)