@reldens/storage 0.114.0 → 0.115.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -1,156 +1,163 @@
|
|
|
1
|
-
/**
|
|
2
|
-
*
|
|
3
|
-
* Reldens - MikroOrmDataServer
|
|
4
|
-
*
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
const { MikroOrmDriver } = require('./mikro-orm-driver');
|
|
8
|
-
const { BaseDataServer } = require('../base-data-server');
|
|
9
|
-
const { MySQLTablesProvider } = require('../mysql-tables-provider');
|
|
10
|
-
const { MikroORM } = require('@mikro-orm/core');
|
|
11
|
-
const { MySqlDriver } = require('@mikro-orm/mysql');
|
|
12
|
-
const { MongoDriver } = require('@mikro-orm/mongodb');
|
|
13
|
-
const { Logger, sc } = require('@reldens/utils');
|
|
14
|
-
|
|
15
|
-
class MikroOrmDataServer extends BaseDataServer
|
|
16
|
-
{
|
|
17
|
-
|
|
18
|
-
orm = {};
|
|
19
|
-
clientsMapped = {
|
|
20
|
-
mysql: MySqlDriver,
|
|
21
|
-
mongodb: MongoDriver
|
|
22
|
-
};
|
|
23
|
-
|
|
24
|
-
constructor(props)
|
|
25
|
-
{
|
|
26
|
-
super(props);
|
|
27
|
-
this.entitiesPath = props.entitiesPath;
|
|
28
|
-
this.warnWhenNoEntities = Boolean(props.warnWhenNoEntities);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
getEntitiesToRegister()
|
|
32
|
-
{
|
|
33
|
-
if(this.entitiesPath){
|
|
34
|
-
//Logger.debug('MikroORM using entitiesPath');
|
|
35
|
-
return this.entitiesPath;
|
|
36
|
-
}
|
|
37
|
-
if(0 < Object.keys(this.entities).length){
|
|
38
|
-
//Logger.debug('MikroORM using this.entities: '+Object.keys(this.entities).join(', '));
|
|
39
|
-
return this.entities;
|
|
40
|
-
}
|
|
41
|
-
if(!this.rawEntities){
|
|
42
|
-
//Logger.debug('MikroORM has no entities!');
|
|
43
|
-
return [];
|
|
44
|
-
}
|
|
45
|
-
let entities = Object.values(this.rawEntities);
|
|
46
|
-
//Logger.debug('MikroORM extracting from rawEntities, count: '+entities.length);
|
|
47
|
-
return entities.map(rawEntity => {
|
|
48
|
-
return (rawEntity && rawEntity.schema) ? rawEntity.schema : rawEntity;
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async connect()
|
|
53
|
-
{
|
|
54
|
-
if(this.initialized){
|
|
55
|
-
return this.initialized;
|
|
56
|
-
}
|
|
57
|
-
let providedSetup = {
|
|
58
|
-
driver: this.clientsMapped[(this.client || 'mongodb')],
|
|
59
|
-
dbName: this.config.database,
|
|
60
|
-
clientUrl: this.connectString,
|
|
61
|
-
allowGlobalContext: true,
|
|
62
|
-
multipleStatements: this.multipleStatements
|
|
63
|
-
};
|
|
64
|
-
providedSetup.entities = this.getEntitiesToRegister();
|
|
65
|
-
providedSetup.discovery = {warnWhenNoEntities: this.warnWhenNoEntities};
|
|
66
|
-
this.orm = await MikroORM.init(providedSetup);
|
|
67
|
-
this.initialized = Date.now();
|
|
68
|
-
return this.initialized;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
async disconnect()
|
|
72
|
-
{
|
|
73
|
-
if(!this.orm){
|
|
74
|
-
return false;
|
|
75
|
-
}
|
|
76
|
-
await this.orm.close();
|
|
77
|
-
this.initialized = null;
|
|
78
|
-
return true;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
generateEntities()
|
|
82
|
-
{
|
|
83
|
-
if(!this.initialized){
|
|
84
|
-
Logger.critical('In order to generate entities with Mikro ORM driver you need to connect to the server.');
|
|
85
|
-
return {};
|
|
86
|
-
}
|
|
87
|
-
if(!this.rawEntities){
|
|
88
|
-
Logger.warning('Empty raw entities array, none entities generated.');
|
|
89
|
-
return {};
|
|
90
|
-
}
|
|
91
|
-
this.entities = {};
|
|
92
|
-
for(let i of Object.keys(this.rawEntities)){
|
|
93
|
-
let rawEntity = this.rawEntities[i];
|
|
94
|
-
this.entities[i] = new MikroOrmDriver({
|
|
95
|
-
rawModel: rawEntity,
|
|
96
|
-
id: i,
|
|
97
|
-
name: i,
|
|
98
|
-
config: { dbName: this.orm.config.get('dbName') },
|
|
99
|
-
orm: this.orm,
|
|
100
|
-
server: this
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
this.entityManager.setEntities(this.entities);
|
|
104
|
-
return this.entities;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
name()
|
|
108
|
-
{
|
|
109
|
-
return this.name || 'Mikro-ORM Data Server Driver';
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async rawQuery(content)
|
|
113
|
-
{
|
|
114
|
-
try {
|
|
115
|
-
let queryResult = await this.orm.em.execute(content);
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - MikroOrmDataServer
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { MikroOrmDriver } = require('./mikro-orm-driver');
|
|
8
|
+
const { BaseDataServer } = require('../base-data-server');
|
|
9
|
+
const { MySQLTablesProvider } = require('../mysql-tables-provider');
|
|
10
|
+
const { MikroORM } = require('@mikro-orm/core');
|
|
11
|
+
const { MySqlDriver } = require('@mikro-orm/mysql');
|
|
12
|
+
const { MongoDriver } = require('@mikro-orm/mongodb');
|
|
13
|
+
const { Logger, sc } = require('@reldens/utils');
|
|
14
|
+
|
|
15
|
+
class MikroOrmDataServer extends BaseDataServer
|
|
16
|
+
{
|
|
17
|
+
|
|
18
|
+
orm = {};
|
|
19
|
+
clientsMapped = {
|
|
20
|
+
mysql: MySqlDriver,
|
|
21
|
+
mongodb: MongoDriver
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
constructor(props)
|
|
25
|
+
{
|
|
26
|
+
super(props);
|
|
27
|
+
this.entitiesPath = props.entitiesPath;
|
|
28
|
+
this.warnWhenNoEntities = Boolean(props.warnWhenNoEntities);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
getEntitiesToRegister()
|
|
32
|
+
{
|
|
33
|
+
if(this.entitiesPath){
|
|
34
|
+
//Logger.debug('MikroORM using entitiesPath');
|
|
35
|
+
return this.entitiesPath;
|
|
36
|
+
}
|
|
37
|
+
if(0 < Object.keys(this.entities).length){
|
|
38
|
+
//Logger.debug('MikroORM using this.entities: '+Object.keys(this.entities).join(', '));
|
|
39
|
+
return this.entities;
|
|
40
|
+
}
|
|
41
|
+
if(!this.rawEntities){
|
|
42
|
+
//Logger.debug('MikroORM has no entities!');
|
|
43
|
+
return [];
|
|
44
|
+
}
|
|
45
|
+
let entities = Object.values(this.rawEntities);
|
|
46
|
+
//Logger.debug('MikroORM extracting from rawEntities, count: '+entities.length);
|
|
47
|
+
return entities.map(rawEntity => {
|
|
48
|
+
return (rawEntity && rawEntity.schema) ? rawEntity.schema : rawEntity;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async connect()
|
|
53
|
+
{
|
|
54
|
+
if(this.initialized){
|
|
55
|
+
return this.initialized;
|
|
56
|
+
}
|
|
57
|
+
let providedSetup = {
|
|
58
|
+
driver: this.clientsMapped[(this.client || 'mongodb')],
|
|
59
|
+
dbName: this.config.database,
|
|
60
|
+
clientUrl: this.connectString,
|
|
61
|
+
allowGlobalContext: true,
|
|
62
|
+
multipleStatements: this.multipleStatements
|
|
63
|
+
};
|
|
64
|
+
providedSetup.entities = this.getEntitiesToRegister();
|
|
65
|
+
providedSetup.discovery = {warnWhenNoEntities: this.warnWhenNoEntities};
|
|
66
|
+
this.orm = await MikroORM.init(providedSetup);
|
|
67
|
+
this.initialized = Date.now();
|
|
68
|
+
return this.initialized;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async disconnect()
|
|
72
|
+
{
|
|
73
|
+
if(!this.orm){
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
await this.orm.close();
|
|
77
|
+
this.initialized = null;
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
generateEntities()
|
|
82
|
+
{
|
|
83
|
+
if(!this.initialized){
|
|
84
|
+
Logger.critical('In order to generate entities with Mikro ORM driver you need to connect to the server.');
|
|
85
|
+
return {};
|
|
86
|
+
}
|
|
87
|
+
if(!this.rawEntities){
|
|
88
|
+
Logger.warning('Empty raw entities array, none entities generated.');
|
|
89
|
+
return {};
|
|
90
|
+
}
|
|
91
|
+
this.entities = {};
|
|
92
|
+
for(let i of Object.keys(this.rawEntities)){
|
|
93
|
+
let rawEntity = this.rawEntities[i];
|
|
94
|
+
this.entities[i] = new MikroOrmDriver({
|
|
95
|
+
rawModel: rawEntity,
|
|
96
|
+
id: i,
|
|
97
|
+
name: i,
|
|
98
|
+
config: { dbName: this.orm.config.get('dbName') },
|
|
99
|
+
orm: this.orm,
|
|
100
|
+
server: this
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
this.entityManager.setEntities(this.entities);
|
|
104
|
+
return this.entities;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
name()
|
|
108
|
+
{
|
|
109
|
+
return this.name || 'Mikro-ORM Data Server Driver';
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async rawQuery(content)
|
|
113
|
+
{
|
|
114
|
+
try {
|
|
115
|
+
let queryResult = await this.orm.em.execute(content, [], 'run');
|
|
116
|
+
let rows = sc.get(queryResult, 'rows', []);
|
|
117
|
+
if(!sc.isArray(rows)){
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
if(0 < rows.length){
|
|
121
|
+
return rows;
|
|
122
|
+
}
|
|
123
|
+
if(0 < queryResult.affectedRows){
|
|
124
|
+
return {affectedRows: queryResult.affectedRows, insertId: queryResult.insertId};
|
|
125
|
+
}
|
|
126
|
+
return rows;
|
|
127
|
+
} catch(error) {
|
|
128
|
+
Logger.error('Raw query failed: '+error.message);
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async fetchEntitiesFromDatabase()
|
|
134
|
+
{
|
|
135
|
+
if(!this.initialized){
|
|
136
|
+
Logger.critical('Connection was not initialized, please use the connect method first.');
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
try {
|
|
140
|
+
if('mysql' === this.client){
|
|
141
|
+
return await MySQLTablesProvider.fetchTables(this);
|
|
142
|
+
}
|
|
143
|
+
if('mongodb' === this.client){
|
|
144
|
+
let tables = {};
|
|
145
|
+
let collections = await this.orm.em.getDriver().getConnection().db().listCollections().toArray();
|
|
146
|
+
for(let collection of collections){
|
|
147
|
+
tables[collection.name] = {
|
|
148
|
+
name: collection.name,
|
|
149
|
+
columns: {}
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return tables;
|
|
153
|
+
}
|
|
154
|
+
Logger.critical('Unsupported client type: '+this.client);
|
|
155
|
+
} catch(error) {
|
|
156
|
+
Logger.critical('MikroORM tables fetch failed. ' + error.message);
|
|
157
|
+
}
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
module.exports.MikroOrmDataServer = MikroOrmDataServer;
|
package/package.json
CHANGED
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Reldens - Raw Queries Integration Test
|
|
4
|
+
* Tests rawQuery with single and multiple SQL statements across all drivers
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const { TestRunner, assert } = require('../utils/test-runner');
|
|
9
|
+
const { TestHelpers } = require('../utils/test-helpers');
|
|
10
|
+
|
|
11
|
+
class RawQueriesTest
|
|
12
|
+
{
|
|
13
|
+
|
|
14
|
+
constructor(dataServer, repos, driverName)
|
|
15
|
+
{
|
|
16
|
+
this.dataServer = dataServer;
|
|
17
|
+
this.driverName = driverName;
|
|
18
|
+
this.runner = new TestRunner();
|
|
19
|
+
this.insertPrefix = 'INSERT INTO test_categories (id, name, slug, is_active, display_order) VALUES ';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async run()
|
|
23
|
+
{
|
|
24
|
+
this.runner.suite('Raw Queries - Driver: '+this.driverName);
|
|
25
|
+
await this.testSingleWriteStatements();
|
|
26
|
+
await this.testSingleDdlStatements();
|
|
27
|
+
await this.testSingleReadStatements();
|
|
28
|
+
await this.testFailingStatements();
|
|
29
|
+
await this.testMultipleWriteStatements();
|
|
30
|
+
await this.testMultipleReadStatements();
|
|
31
|
+
return this.runner.getResults();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async rawQueryOrFalse(content)
|
|
35
|
+
{
|
|
36
|
+
return await this.dataServer.rawQuery(content).catch(() => false);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async selectNames(whereClause)
|
|
40
|
+
{
|
|
41
|
+
return await this.dataServer.rawQuery('SELECT name FROM test_categories WHERE '+whereClause+' ORDER BY id');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
assertNames(rows, expectedNames)
|
|
45
|
+
{
|
|
46
|
+
assert.ok(Array.isArray(rows), 'Rows must be an array');
|
|
47
|
+
assert.strictEqual(rows.length, expectedNames.length);
|
|
48
|
+
for(let i = 0; i < expectedNames.length; i++){
|
|
49
|
+
assert.strictEqual(rows[i].name, expectedNames[i]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
assertResultsCount(results, expectedCount)
|
|
54
|
+
{
|
|
55
|
+
assert.ok(Array.isArray(results), 'Multiple statements must return an array');
|
|
56
|
+
assert.strictEqual(results.length, expectedCount);
|
|
57
|
+
for(let result of results){
|
|
58
|
+
assert.notStrictEqual(result, false);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async testSingleWriteStatements()
|
|
63
|
+
{
|
|
64
|
+
this.runner.group('Single Write Statement');
|
|
65
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
66
|
+
await this.runner.test('should return a truthy result for a single INSERT', async () => {
|
|
67
|
+
let result = await this.dataServer.rawQuery(
|
|
68
|
+
this.insertPrefix+'(9001, \'Raw Single Test\', \'raw-single-test\', 1, 99)'
|
|
69
|
+
);
|
|
70
|
+
assert.ok(result, 'Single INSERT must not be reported as a failed query');
|
|
71
|
+
});
|
|
72
|
+
await this.runner.test('should keep a semicolon inside a quoted value on a single INSERT', async () => {
|
|
73
|
+
let result = await this.dataServer.rawQuery(this.insertPrefix+'(9006, \'Raw; Quoted\', \'raw-quoted\', 1, 98)');
|
|
74
|
+
assert.ok(result, 'Single INSERT with quoted semicolon must not be reported as a failed query');
|
|
75
|
+
this.assertNames(await this.selectNames('id = 9006'), ['Raw; Quoted']);
|
|
76
|
+
});
|
|
77
|
+
await this.runner.test('should return a truthy result for a single UPDATE matching rows', async () => {
|
|
78
|
+
let result = await this.dataServer.rawQuery(
|
|
79
|
+
'UPDATE test_categories SET name = \'Updated Raw Single\' WHERE id = 9001'
|
|
80
|
+
);
|
|
81
|
+
assert.ok(result, 'Single UPDATE must not be reported as a failed query');
|
|
82
|
+
this.assertNames(await this.selectNames('id = 9001'), ['Updated Raw Single']);
|
|
83
|
+
});
|
|
84
|
+
await this.runner.test('should not return false for a single UPDATE matching no rows', async () => {
|
|
85
|
+
let result = await this.dataServer.rawQuery('UPDATE test_categories SET name = \'Nobody\' WHERE id = 9999');
|
|
86
|
+
assert.notStrictEqual(result, false, 'UPDATE matching no rows is not a failed query');
|
|
87
|
+
});
|
|
88
|
+
await this.runner.test('should return a truthy result for a single DELETE matching rows', async () => {
|
|
89
|
+
let result = await this.dataServer.rawQuery('DELETE FROM test_categories WHERE id = 9006');
|
|
90
|
+
assert.ok(result, 'Single DELETE must not be reported as a failed query');
|
|
91
|
+
this.assertNames(await this.selectNames('id = 9006'), []);
|
|
92
|
+
});
|
|
93
|
+
await this.runner.test('should not return false for a single DELETE matching no rows', async () => {
|
|
94
|
+
let result = await this.dataServer.rawQuery('DELETE FROM test_categories WHERE id = 9999');
|
|
95
|
+
assert.notStrictEqual(result, false, 'DELETE matching no rows is not a failed query');
|
|
96
|
+
});
|
|
97
|
+
await this.runner.test('should not return false for a single DELETE without WHERE on an empty table', async () => {
|
|
98
|
+
let result = await this.dataServer.rawQuery('DELETE FROM test_reviews');
|
|
99
|
+
assert.notStrictEqual(result, false, 'DELETE on an empty table is not a failed query');
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async testSingleDdlStatements()
|
|
104
|
+
{
|
|
105
|
+
this.runner.group('Single DDL Statement');
|
|
106
|
+
await this.runner.test('should return a truthy result for a single CREATE TABLE', async () => {
|
|
107
|
+
let result = await this.dataServer.rawQuery('CREATE TABLE test_raw_ddl (id INT NOT NULL PRIMARY KEY)');
|
|
108
|
+
assert.ok(result, 'Single CREATE TABLE must not be reported as a failed query');
|
|
109
|
+
let rows = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_raw_ddl\'');
|
|
110
|
+
assert.strictEqual(rows.length, 1);
|
|
111
|
+
});
|
|
112
|
+
await this.runner.test('should return a truthy result for a single ALTER TABLE', async () => {
|
|
113
|
+
let result = await this.dataServer.rawQuery('ALTER TABLE test_raw_ddl ADD COLUMN label VARCHAR(50) NULL');
|
|
114
|
+
assert.ok(result, 'Single ALTER TABLE must not be reported as a failed query');
|
|
115
|
+
let rows = await this.dataServer.rawQuery('SHOW COLUMNS FROM test_raw_ddl LIKE \'label\'');
|
|
116
|
+
assert.strictEqual(rows.length, 1);
|
|
117
|
+
});
|
|
118
|
+
await this.runner.test('should return a truthy result for a single DROP TABLE', async () => {
|
|
119
|
+
let result = await this.dataServer.rawQuery('DROP TABLE test_raw_ddl');
|
|
120
|
+
assert.ok(result, 'Single DROP TABLE must not be reported as a failed query');
|
|
121
|
+
let rows = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_raw_ddl\'');
|
|
122
|
+
assert.ok(Array.isArray(rows));
|
|
123
|
+
assert.strictEqual(rows.length, 0);
|
|
124
|
+
});
|
|
125
|
+
await this.runner.test('should not return false for a single SET statement', async () => {
|
|
126
|
+
let result = await this.dataServer.rawQuery('SET FOREIGN_KEY_CHECKS=1');
|
|
127
|
+
assert.notStrictEqual(result, false, 'SET statement is not a failed query');
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async testSingleReadStatements()
|
|
132
|
+
{
|
|
133
|
+
this.runner.group('Single Read Statement');
|
|
134
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
135
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9001, \'Raw Read 1\', \'raw-read-1\', 1, 1)');
|
|
136
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9002, \'Raw Read 2\', \'raw-read-2\', 1, 2)');
|
|
137
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9003, \'Raw Read 3\', \'raw-read-3\', 0, 3)');
|
|
138
|
+
await this.runner.test('should return one row for a SELECT matching one record', async () => {
|
|
139
|
+
let result = await this.dataServer.rawQuery('SELECT id, name, slug FROM test_categories WHERE id = 9001');
|
|
140
|
+
this.assertNames(result, ['Raw Read 1']);
|
|
141
|
+
assert.strictEqual(result[0].slug, 'raw-read-1');
|
|
142
|
+
});
|
|
143
|
+
await this.runner.test('should return all rows in the requested order for a SELECT matching many', async () => {
|
|
144
|
+
let result = await this.dataServer.rawQuery(
|
|
145
|
+
'SELECT name FROM test_categories WHERE id IN (9001, 9002, 9003) ORDER BY id DESC'
|
|
146
|
+
);
|
|
147
|
+
this.assertNames(result, ['Raw Read 3', 'Raw Read 2', 'Raw Read 1']);
|
|
148
|
+
});
|
|
149
|
+
await this.runner.test('should return an empty array for a SELECT matching no rows', async () => {
|
|
150
|
+
let result = await this.dataServer.rawQuery('SELECT id FROM test_categories WHERE id = 9999');
|
|
151
|
+
assert.ok(Array.isArray(result), 'Empty SELECT must return an array, not false');
|
|
152
|
+
assert.strictEqual(result.length, 0);
|
|
153
|
+
});
|
|
154
|
+
await this.runner.test('should return a row for a SELECT without FROM', async () => {
|
|
155
|
+
let result = await this.dataServer.rawQuery('SELECT \'raw-constant\' AS value');
|
|
156
|
+
assert.ok(Array.isArray(result));
|
|
157
|
+
assert.strictEqual(result.length, 1);
|
|
158
|
+
assert.strictEqual(result[0].value, 'raw-constant');
|
|
159
|
+
});
|
|
160
|
+
await this.runner.test('should return rows for a SELECT with trailing semicolon and whitespace', async () => {
|
|
161
|
+
let result = await this.dataServer.rawQuery('\n SELECT name FROM test_categories WHERE id = 9002 ; \n');
|
|
162
|
+
this.assertNames(result, ['Raw Read 2']);
|
|
163
|
+
});
|
|
164
|
+
await this.runner.test('should return rows for a SELECT preceded by line and block comments', async () => {
|
|
165
|
+
let result = await this.dataServer.rawQuery(
|
|
166
|
+
'-- line comment; with semicolon\n/* block comment; with semicolon */\n'
|
|
167
|
+
+'SELECT name FROM test_categories WHERE id = 9003'
|
|
168
|
+
);
|
|
169
|
+
this.assertNames(result, ['Raw Read 3']);
|
|
170
|
+
});
|
|
171
|
+
await this.runner.test('should return rows for a SHOW statement', async () => {
|
|
172
|
+
let result = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_categories\'');
|
|
173
|
+
assert.ok(Array.isArray(result));
|
|
174
|
+
assert.strictEqual(result.length, 1);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async testFailingStatements()
|
|
179
|
+
{
|
|
180
|
+
this.runner.group('Failing Statement');
|
|
181
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
182
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9001, \'Raw Fail 1\', \'raw-fail-1\', 1, 1)');
|
|
183
|
+
await this.runner.test('should not return a truthy result for invalid SQL', async () => {
|
|
184
|
+
assert.strictEqual(await this.rawQueryOrFalse('THIS IS NOT SQL'), false);
|
|
185
|
+
});
|
|
186
|
+
await this.runner.test('should not return a truthy result for an empty string', async () => {
|
|
187
|
+
assert.strictEqual(await this.rawQueryOrFalse(''), false);
|
|
188
|
+
});
|
|
189
|
+
await this.runner.test('should not return a truthy result for a whitespace only string', async () => {
|
|
190
|
+
assert.strictEqual(await this.rawQueryOrFalse(' \n '), false);
|
|
191
|
+
});
|
|
192
|
+
await this.runner.test('should not return a truthy result for a SELECT on a missing table', async () => {
|
|
193
|
+
assert.strictEqual(await this.rawQueryOrFalse('SELECT id FROM test_missing_table'), false);
|
|
194
|
+
});
|
|
195
|
+
await this.runner.test('should not return a truthy result for an INSERT violating a unique key', async () => {
|
|
196
|
+
let result = await this.rawQueryOrFalse(this.insertPrefix+'(9007, \'Raw Duplicate\', \'raw-fail-1\', 1, 2)');
|
|
197
|
+
assert.strictEqual(result, false);
|
|
198
|
+
this.assertNames(await this.selectNames('id = 9007'), []);
|
|
199
|
+
});
|
|
200
|
+
await this.runner.test('should not return a truthy result when a later statement is invalid', async () => {
|
|
201
|
+
let result = await this.rawQueryOrFalse('SELECT id FROM test_categories WHERE id = 9001; THIS IS NOT SQL;');
|
|
202
|
+
assert.strictEqual(result, false);
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
async testMultipleWriteStatements()
|
|
207
|
+
{
|
|
208
|
+
this.runner.group('Multiple Write Statements');
|
|
209
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
210
|
+
await this.runner.test('should return one result per statement for multiple INSERTs', async () => {
|
|
211
|
+
let results = await this.dataServer.rawQuery(
|
|
212
|
+
this.insertPrefix+'(9002, \'Raw Multi 1\', \'raw-multi-1\', 1, 1);'
|
|
213
|
+
+this.insertPrefix+'(9003, \'Raw Multi 2\', \'raw-multi-2\', 1, 2);'
|
|
214
|
+
);
|
|
215
|
+
this.assertResultsCount(results, 2);
|
|
216
|
+
this.assertNames(await this.selectNames('id IN (9002, 9003)'), ['Raw Multi 1', 'Raw Multi 2']);
|
|
217
|
+
});
|
|
218
|
+
await this.runner.test('should return one result per statement for an UPDATE and a DELETE', async () => {
|
|
219
|
+
let results = await this.dataServer.rawQuery(
|
|
220
|
+
'UPDATE test_categories SET name = \'Raw Multi Updated\' WHERE id = 9002;'
|
|
221
|
+
+'DELETE FROM test_categories WHERE id = 9003;'
|
|
222
|
+
);
|
|
223
|
+
this.assertResultsCount(results, 2);
|
|
224
|
+
this.assertNames(await this.selectNames('id IN (9002, 9003)'), ['Raw Multi Updated']);
|
|
225
|
+
});
|
|
226
|
+
await this.runner.test('should return one result per statement for a CREATE and a DROP TABLE', async () => {
|
|
227
|
+
let results = await this.dataServer.rawQuery(
|
|
228
|
+
'CREATE TABLE test_raw_multi_ddl (id INT NOT NULL PRIMARY KEY);DROP TABLE test_raw_multi_ddl;'
|
|
229
|
+
);
|
|
230
|
+
this.assertResultsCount(results, 2);
|
|
231
|
+
let rows = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_raw_multi_ddl\'');
|
|
232
|
+
assert.strictEqual(rows.length, 0);
|
|
233
|
+
});
|
|
234
|
+
await this.runner.test('should ignore comments and blank lines between statements', async () => {
|
|
235
|
+
let results = await this.dataServer.rawQuery(
|
|
236
|
+
'-- first statement\n'
|
|
237
|
+
+this.insertPrefix+'(9005, \'Raw Commented 1\', \'raw-commented-1\', 1, 4);\n\n'
|
|
238
|
+
+'/* second statement */\n'
|
|
239
|
+
+this.insertPrefix+'(9008, \'Raw Commented 2\', \'raw-commented-2\', 1, 5);\n'
|
|
240
|
+
);
|
|
241
|
+
this.assertResultsCount(results, 2);
|
|
242
|
+
this.assertNames(await this.selectNames('id IN (9005, 9008)'), ['Raw Commented 1', 'Raw Commented 2']);
|
|
243
|
+
});
|
|
244
|
+
await this.runner.test('should execute multiple sequential rawQuery calls', async () => {
|
|
245
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9009, \'Raw Sequential 1\', \'raw-sequential-1\', 1, 6)');
|
|
246
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9010, \'Raw Sequential 2\', \'raw-sequential-2\', 1, 7)');
|
|
247
|
+
this.assertNames(await this.selectNames('id IN (9009, 9010)'), ['Raw Sequential 1', 'Raw Sequential 2']);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async testMultipleReadStatements()
|
|
252
|
+
{
|
|
253
|
+
this.runner.group('Multiple Read Statements');
|
|
254
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
255
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9002, \'Raw Multi 1\', \'raw-multi-1\', 1, 1)');
|
|
256
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9003, \'Raw Multi 2\', \'raw-multi-2\', 1, 2)');
|
|
257
|
+
await this.runner.test('should return one result set per SELECT for multiple SELECTs', async () => {
|
|
258
|
+
let results = await this.dataServer.rawQuery(
|
|
259
|
+
'SELECT id, name FROM test_categories WHERE id = 9002;'
|
|
260
|
+
+'SELECT id, name FROM test_categories WHERE id = 9003;'
|
|
261
|
+
);
|
|
262
|
+
this.assertResultsCount(results, 2);
|
|
263
|
+
this.assertNames(results[0], ['Raw Multi 1']);
|
|
264
|
+
this.assertNames(results[1], ['Raw Multi 2']);
|
|
265
|
+
});
|
|
266
|
+
await this.runner.test('should return an empty result set for an empty SELECT among multiple SELECTs', async () => {
|
|
267
|
+
let results = await this.dataServer.rawQuery(
|
|
268
|
+
'SELECT id FROM test_categories WHERE id = 9999;'
|
|
269
|
+
+'SELECT name FROM test_categories WHERE id = 9002;'
|
|
270
|
+
);
|
|
271
|
+
this.assertResultsCount(results, 2);
|
|
272
|
+
this.assertNames(results[0], []);
|
|
273
|
+
this.assertNames(results[1], ['Raw Multi 1']);
|
|
274
|
+
});
|
|
275
|
+
await this.runner.test('should return one result per statement for a mixed INSERT and SELECT', async () => {
|
|
276
|
+
let results = await this.dataServer.rawQuery(
|
|
277
|
+
this.insertPrefix+'(9004, \'Raw Mixed\', \'raw-mixed\', 1, 3);'
|
|
278
|
+
+'SELECT name FROM test_categories WHERE id = 9004;'
|
|
279
|
+
);
|
|
280
|
+
this.assertResultsCount(results, 2);
|
|
281
|
+
this.assertNames(results[1], ['Raw Mixed']);
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
module.exports = RawQueriesTest;
|
|
@@ -16,111 +16,269 @@ class RawQueriesTest
|
|
|
16
16
|
this.dataServer = dataServer;
|
|
17
17
|
this.driverName = driverName;
|
|
18
18
|
this.runner = new TestRunner();
|
|
19
|
+
this.insertPrefix = 'INSERT INTO test_categories (id, name, slug, is_active, display_order) VALUES ';
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
async run()
|
|
22
23
|
{
|
|
23
24
|
this.runner.suite('Raw Queries - Driver: '+this.driverName);
|
|
24
|
-
await this.
|
|
25
|
-
await this.
|
|
25
|
+
await this.testSingleWriteStatements();
|
|
26
|
+
await this.testSingleDdlStatements();
|
|
27
|
+
await this.testSingleReadStatements();
|
|
28
|
+
await this.testFailingStatements();
|
|
29
|
+
await this.testMultipleWriteStatements();
|
|
30
|
+
await this.testMultipleReadStatements();
|
|
26
31
|
return this.runner.getResults();
|
|
27
32
|
}
|
|
28
33
|
|
|
29
|
-
async
|
|
34
|
+
async rawQueryOrFalse(content)
|
|
30
35
|
{
|
|
31
|
-
this.
|
|
36
|
+
return await this.dataServer.rawQuery(content).catch(() => false);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async selectNames(whereClause)
|
|
40
|
+
{
|
|
41
|
+
return await this.dataServer.rawQuery('SELECT name FROM test_categories WHERE '+whereClause+' ORDER BY id');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
assertNames(rows, expectedNames)
|
|
45
|
+
{
|
|
46
|
+
assert.ok(Array.isArray(rows), 'Rows must be an array');
|
|
47
|
+
assert.strictEqual(rows.length, expectedNames.length);
|
|
48
|
+
for(let i = 0; i < expectedNames.length; i++){
|
|
49
|
+
assert.strictEqual(rows[i].name, expectedNames[i]);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
assertResultsCount(results, expectedCount)
|
|
54
|
+
{
|
|
55
|
+
assert.ok(Array.isArray(results), 'Multiple statements must return an array');
|
|
56
|
+
assert.strictEqual(results.length, expectedCount);
|
|
57
|
+
for(let result of results){
|
|
58
|
+
assert.notStrictEqual(result, false);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async testSingleWriteStatements()
|
|
63
|
+
{
|
|
64
|
+
this.runner.group('Single Write Statement');
|
|
32
65
|
await TestHelpers.cleanDatabase(this.dataServer);
|
|
33
|
-
await this.
|
|
34
|
-
'INSERT INTO test_categories (id, name, slug, is_active, display_order)'
|
|
35
|
-
+' VALUES (9001, \'Raw Single Test\', \'raw-single-test\', 1, 99)'
|
|
36
|
-
);
|
|
37
|
-
await this.runner.test('should return rows from SELECT single statement', async () => {
|
|
66
|
+
await this.runner.test('should return a truthy result for a single INSERT', async () => {
|
|
38
67
|
let result = await this.dataServer.rawQuery(
|
|
39
|
-
'
|
|
68
|
+
this.insertPrefix+'(9001, \'Raw Single Test\', \'raw-single-test\', 1, 99)'
|
|
40
69
|
);
|
|
41
|
-
assert.ok(result);
|
|
42
|
-
assert.ok(Array.isArray(result));
|
|
43
|
-
assert.strictEqual(result.length, 1);
|
|
44
|
-
assert.strictEqual(result[0].name, 'Raw Single Test');
|
|
45
|
-
assert.strictEqual(result[0].slug, 'raw-single-test');
|
|
70
|
+
assert.ok(result, 'Single INSERT must not be reported as a failed query');
|
|
46
71
|
});
|
|
47
|
-
await this.runner.test('should
|
|
48
|
-
await this.dataServer.rawQuery(
|
|
72
|
+
await this.runner.test('should keep a semicolon inside a quoted value on a single INSERT', async () => {
|
|
73
|
+
let result = await this.dataServer.rawQuery(this.insertPrefix+'(9006, \'Raw; Quoted\', \'raw-quoted\', 1, 98)');
|
|
74
|
+
assert.ok(result, 'Single INSERT with quoted semicolon must not be reported as a failed query');
|
|
75
|
+
this.assertNames(await this.selectNames('id = 9006'), ['Raw; Quoted']);
|
|
76
|
+
});
|
|
77
|
+
await this.runner.test('should return a truthy result for a single UPDATE matching rows', async () => {
|
|
78
|
+
let result = await this.dataServer.rawQuery(
|
|
49
79
|
'UPDATE test_categories SET name = \'Updated Raw Single\' WHERE id = 9001'
|
|
50
80
|
);
|
|
81
|
+
assert.ok(result, 'Single UPDATE must not be reported as a failed query');
|
|
82
|
+
this.assertNames(await this.selectNames('id = 9001'), ['Updated Raw Single']);
|
|
83
|
+
});
|
|
84
|
+
await this.runner.test('should not return false for a single UPDATE matching no rows', async () => {
|
|
85
|
+
let result = await this.dataServer.rawQuery('UPDATE test_categories SET name = \'Nobody\' WHERE id = 9999');
|
|
86
|
+
assert.notStrictEqual(result, false, 'UPDATE matching no rows is not a failed query');
|
|
87
|
+
});
|
|
88
|
+
await this.runner.test('should return a truthy result for a single DELETE matching rows', async () => {
|
|
89
|
+
let result = await this.dataServer.rawQuery('DELETE FROM test_categories WHERE id = 9006');
|
|
90
|
+
assert.ok(result, 'Single DELETE must not be reported as a failed query');
|
|
91
|
+
this.assertNames(await this.selectNames('id = 9006'), []);
|
|
92
|
+
});
|
|
93
|
+
await this.runner.test('should not return false for a single DELETE matching no rows', async () => {
|
|
94
|
+
let result = await this.dataServer.rawQuery('DELETE FROM test_categories WHERE id = 9999');
|
|
95
|
+
assert.notStrictEqual(result, false, 'DELETE matching no rows is not a failed query');
|
|
96
|
+
});
|
|
97
|
+
await this.runner.test('should not return false for a single DELETE without WHERE on an empty table', async () => {
|
|
98
|
+
let result = await this.dataServer.rawQuery('DELETE FROM test_reviews');
|
|
99
|
+
assert.notStrictEqual(result, false, 'DELETE on an empty table is not a failed query');
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
async testSingleDdlStatements()
|
|
104
|
+
{
|
|
105
|
+
this.runner.group('Single DDL Statement');
|
|
106
|
+
await this.runner.test('should return a truthy result for a single CREATE TABLE', async () => {
|
|
107
|
+
let result = await this.dataServer.rawQuery('CREATE TABLE test_raw_ddl (id INT NOT NULL PRIMARY KEY)');
|
|
108
|
+
assert.ok(result, 'Single CREATE TABLE must not be reported as a failed query');
|
|
109
|
+
let rows = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_raw_ddl\'');
|
|
110
|
+
assert.strictEqual(rows.length, 1);
|
|
111
|
+
});
|
|
112
|
+
await this.runner.test('should return a truthy result for a single ALTER TABLE', async () => {
|
|
113
|
+
let result = await this.dataServer.rawQuery('ALTER TABLE test_raw_ddl ADD COLUMN label VARCHAR(50) NULL');
|
|
114
|
+
assert.ok(result, 'Single ALTER TABLE must not be reported as a failed query');
|
|
115
|
+
let rows = await this.dataServer.rawQuery('SHOW COLUMNS FROM test_raw_ddl LIKE \'label\'');
|
|
116
|
+
assert.strictEqual(rows.length, 1);
|
|
117
|
+
});
|
|
118
|
+
await this.runner.test('should return a truthy result for a single DROP TABLE', async () => {
|
|
119
|
+
let result = await this.dataServer.rawQuery('DROP TABLE test_raw_ddl');
|
|
120
|
+
assert.ok(result, 'Single DROP TABLE must not be reported as a failed query');
|
|
121
|
+
let rows = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_raw_ddl\'');
|
|
122
|
+
assert.ok(Array.isArray(rows));
|
|
123
|
+
assert.strictEqual(rows.length, 0);
|
|
124
|
+
});
|
|
125
|
+
await this.runner.test('should not return false for a single SET statement', async () => {
|
|
126
|
+
let result = await this.dataServer.rawQuery('SET FOREIGN_KEY_CHECKS=1');
|
|
127
|
+
assert.notStrictEqual(result, false, 'SET statement is not a failed query');
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async testSingleReadStatements()
|
|
132
|
+
{
|
|
133
|
+
this.runner.group('Single Read Statement');
|
|
134
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
135
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9001, \'Raw Read 1\', \'raw-read-1\', 1, 1)');
|
|
136
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9002, \'Raw Read 2\', \'raw-read-2\', 1, 2)');
|
|
137
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9003, \'Raw Read 3\', \'raw-read-3\', 0, 3)');
|
|
138
|
+
await this.runner.test('should return one row for a SELECT matching one record', async () => {
|
|
139
|
+
let result = await this.dataServer.rawQuery('SELECT id, name, slug FROM test_categories WHERE id = 9001');
|
|
140
|
+
this.assertNames(result, ['Raw Read 1']);
|
|
141
|
+
assert.strictEqual(result[0].slug, 'raw-read-1');
|
|
142
|
+
});
|
|
143
|
+
await this.runner.test('should return all rows in the requested order for a SELECT matching many', async () => {
|
|
51
144
|
let result = await this.dataServer.rawQuery(
|
|
52
|
-
'SELECT
|
|
145
|
+
'SELECT name FROM test_categories WHERE id IN (9001, 9002, 9003) ORDER BY id DESC'
|
|
53
146
|
);
|
|
54
|
-
|
|
147
|
+
this.assertNames(result, ['Raw Read 3', 'Raw Read 2', 'Raw Read 1']);
|
|
148
|
+
});
|
|
149
|
+
await this.runner.test('should return an empty array for a SELECT matching no rows', async () => {
|
|
150
|
+
let result = await this.dataServer.rawQuery('SELECT id FROM test_categories WHERE id = 9999');
|
|
151
|
+
assert.ok(Array.isArray(result), 'Empty SELECT must return an array, not false');
|
|
152
|
+
assert.strictEqual(result.length, 0);
|
|
153
|
+
});
|
|
154
|
+
await this.runner.test('should return a row for a SELECT without FROM', async () => {
|
|
155
|
+
let result = await this.dataServer.rawQuery('SELECT \'raw-constant\' AS value');
|
|
55
156
|
assert.ok(Array.isArray(result));
|
|
56
157
|
assert.strictEqual(result.length, 1);
|
|
57
|
-
assert.strictEqual(result[0].
|
|
158
|
+
assert.strictEqual(result[0].value, 'raw-constant');
|
|
58
159
|
});
|
|
59
|
-
await this.runner.test('should
|
|
60
|
-
await this.dataServer.rawQuery('
|
|
160
|
+
await this.runner.test('should return rows for a SELECT with trailing semicolon and whitespace', async () => {
|
|
161
|
+
let result = await this.dataServer.rawQuery('\n SELECT name FROM test_categories WHERE id = 9002 ; \n');
|
|
162
|
+
this.assertNames(result, ['Raw Read 2']);
|
|
163
|
+
});
|
|
164
|
+
await this.runner.test('should return rows for a SELECT preceded by line and block comments', async () => {
|
|
61
165
|
let result = await this.dataServer.rawQuery(
|
|
62
|
-
'
|
|
166
|
+
'-- line comment; with semicolon\n/* block comment; with semicolon */\n'
|
|
167
|
+
+'SELECT name FROM test_categories WHERE id = 9003'
|
|
63
168
|
);
|
|
64
|
-
|
|
65
|
-
|
|
169
|
+
this.assertNames(result, ['Raw Read 3']);
|
|
170
|
+
});
|
|
171
|
+
await this.runner.test('should return rows for a SHOW statement', async () => {
|
|
172
|
+
let result = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_categories\'');
|
|
173
|
+
assert.ok(Array.isArray(result));
|
|
174
|
+
assert.strictEqual(result.length, 1);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
async testFailingStatements()
|
|
179
|
+
{
|
|
180
|
+
this.runner.group('Failing Statement');
|
|
181
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
182
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9001, \'Raw Fail 1\', \'raw-fail-1\', 1, 1)');
|
|
183
|
+
await this.runner.test('should not return a truthy result for invalid SQL', async () => {
|
|
184
|
+
assert.strictEqual(await this.rawQueryOrFalse('THIS IS NOT SQL'), false);
|
|
185
|
+
});
|
|
186
|
+
await this.runner.test('should not return a truthy result for an empty string', async () => {
|
|
187
|
+
assert.strictEqual(await this.rawQueryOrFalse(''), false);
|
|
188
|
+
});
|
|
189
|
+
await this.runner.test('should not return a truthy result for a whitespace only string', async () => {
|
|
190
|
+
assert.strictEqual(await this.rawQueryOrFalse(' \n '), false);
|
|
191
|
+
});
|
|
192
|
+
await this.runner.test('should not return a truthy result for a SELECT on a missing table', async () => {
|
|
193
|
+
assert.strictEqual(await this.rawQueryOrFalse('SELECT id FROM test_missing_table'), false);
|
|
194
|
+
});
|
|
195
|
+
await this.runner.test('should not return a truthy result for an INSERT violating a unique key', async () => {
|
|
196
|
+
let result = await this.rawQueryOrFalse(this.insertPrefix+'(9007, \'Raw Duplicate\', \'raw-fail-1\', 1, 2)');
|
|
197
|
+
assert.strictEqual(result, false);
|
|
198
|
+
this.assertNames(await this.selectNames('id = 9007'), []);
|
|
199
|
+
});
|
|
200
|
+
await this.runner.test('should not return a truthy result when a later statement is invalid', async () => {
|
|
201
|
+
let result = await this.rawQueryOrFalse('SELECT id FROM test_categories WHERE id = 9001; THIS IS NOT SQL;');
|
|
202
|
+
assert.strictEqual(result, false);
|
|
66
203
|
});
|
|
67
204
|
}
|
|
68
205
|
|
|
69
|
-
async
|
|
206
|
+
async testMultipleWriteStatements()
|
|
70
207
|
{
|
|
71
|
-
this.runner.group('Multiple Statements');
|
|
208
|
+
this.runner.group('Multiple Write Statements');
|
|
72
209
|
await TestHelpers.cleanDatabase(this.dataServer);
|
|
73
|
-
await this.runner.test('should
|
|
210
|
+
await this.runner.test('should return one result per statement for multiple INSERTs', async () => {
|
|
74
211
|
let results = await this.dataServer.rawQuery(
|
|
75
|
-
'
|
|
76
|
-
+'
|
|
77
|
-
+'INSERT INTO test_categories (id, name, slug, is_active, display_order)'
|
|
78
|
-
+' VALUES (9003, \'Raw Multi 2\', \'raw-multi-2\', 1, 2);'
|
|
212
|
+
this.insertPrefix+'(9002, \'Raw Multi 1\', \'raw-multi-1\', 1, 1);'
|
|
213
|
+
+this.insertPrefix+'(9003, \'Raw Multi 2\', \'raw-multi-2\', 1, 2);'
|
|
79
214
|
);
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
215
|
+
this.assertResultsCount(results, 2);
|
|
216
|
+
this.assertNames(await this.selectNames('id IN (9002, 9003)'), ['Raw Multi 1', 'Raw Multi 2']);
|
|
217
|
+
});
|
|
218
|
+
await this.runner.test('should return one result per statement for an UPDATE and a DELETE', async () => {
|
|
219
|
+
let results = await this.dataServer.rawQuery(
|
|
220
|
+
'UPDATE test_categories SET name = \'Raw Multi Updated\' WHERE id = 9002;'
|
|
221
|
+
+'DELETE FROM test_categories WHERE id = 9003;'
|
|
85
222
|
);
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
assert.strictEqual(rows.length, 2);
|
|
89
|
-
assert.strictEqual(rows[0].name, 'Raw Multi 1');
|
|
90
|
-
assert.strictEqual(rows[1].name, 'Raw Multi 2');
|
|
223
|
+
this.assertResultsCount(results, 2);
|
|
224
|
+
this.assertNames(await this.selectNames('id IN (9002, 9003)'), ['Raw Multi Updated']);
|
|
91
225
|
});
|
|
92
|
-
await this.runner.test('should return one result
|
|
226
|
+
await this.runner.test('should return one result per statement for a CREATE and a DROP TABLE', async () => {
|
|
93
227
|
let results = await this.dataServer.rawQuery(
|
|
94
|
-
'
|
|
95
|
-
+'SELECT id, name FROM test_categories WHERE id = 9003;'
|
|
228
|
+
'CREATE TABLE test_raw_multi_ddl (id INT NOT NULL PRIMARY KEY);DROP TABLE test_raw_multi_ddl;'
|
|
96
229
|
);
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
assert.strictEqual(
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
230
|
+
this.assertResultsCount(results, 2);
|
|
231
|
+
let rows = await this.dataServer.rawQuery('SHOW TABLES LIKE \'test_raw_multi_ddl\'');
|
|
232
|
+
assert.strictEqual(rows.length, 0);
|
|
233
|
+
});
|
|
234
|
+
await this.runner.test('should ignore comments and blank lines between statements', async () => {
|
|
235
|
+
let results = await this.dataServer.rawQuery(
|
|
236
|
+
'-- first statement\n'
|
|
237
|
+
+this.insertPrefix+'(9005, \'Raw Commented 1\', \'raw-commented-1\', 1, 4);\n\n'
|
|
238
|
+
+'/* second statement */\n'
|
|
239
|
+
+this.insertPrefix+'(9008, \'Raw Commented 2\', \'raw-commented-2\', 1, 5);\n'
|
|
240
|
+
);
|
|
241
|
+
this.assertResultsCount(results, 2);
|
|
242
|
+
this.assertNames(await this.selectNames('id IN (9005, 9008)'), ['Raw Commented 1', 'Raw Commented 2']);
|
|
106
243
|
});
|
|
107
244
|
await this.runner.test('should execute multiple sequential rawQuery calls', async () => {
|
|
108
|
-
await this.dataServer.rawQuery(
|
|
109
|
-
|
|
110
|
-
|
|
245
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9009, \'Raw Sequential 1\', \'raw-sequential-1\', 1, 6)');
|
|
246
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9010, \'Raw Sequential 2\', \'raw-sequential-2\', 1, 7)');
|
|
247
|
+
this.assertNames(await this.selectNames('id IN (9009, 9010)'), ['Raw Sequential 1', 'Raw Sequential 2']);
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
async testMultipleReadStatements()
|
|
252
|
+
{
|
|
253
|
+
this.runner.group('Multiple Read Statements');
|
|
254
|
+
await TestHelpers.cleanDatabase(this.dataServer);
|
|
255
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9002, \'Raw Multi 1\', \'raw-multi-1\', 1, 1)');
|
|
256
|
+
await this.dataServer.rawQuery(this.insertPrefix+'(9003, \'Raw Multi 2\', \'raw-multi-2\', 1, 2)');
|
|
257
|
+
await this.runner.test('should return one result set per SELECT for multiple SELECTs', async () => {
|
|
258
|
+
let results = await this.dataServer.rawQuery(
|
|
259
|
+
'SELECT id, name FROM test_categories WHERE id = 9002;'
|
|
260
|
+
+'SELECT id, name FROM test_categories WHERE id = 9003;'
|
|
111
261
|
);
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
262
|
+
this.assertResultsCount(results, 2);
|
|
263
|
+
this.assertNames(results[0], ['Raw Multi 1']);
|
|
264
|
+
this.assertNames(results[1], ['Raw Multi 2']);
|
|
265
|
+
});
|
|
266
|
+
await this.runner.test('should return an empty result set for an empty SELECT among multiple SELECTs', async () => {
|
|
267
|
+
let results = await this.dataServer.rawQuery(
|
|
268
|
+
'SELECT id FROM test_categories WHERE id = 9999;'
|
|
269
|
+
+'SELECT name FROM test_categories WHERE id = 9002;'
|
|
115
270
|
);
|
|
116
|
-
|
|
117
|
-
|
|
271
|
+
this.assertResultsCount(results, 2);
|
|
272
|
+
this.assertNames(results[0], []);
|
|
273
|
+
this.assertNames(results[1], ['Raw Multi 1']);
|
|
274
|
+
});
|
|
275
|
+
await this.runner.test('should return one result per statement for a mixed INSERT and SELECT', async () => {
|
|
276
|
+
let results = await this.dataServer.rawQuery(
|
|
277
|
+
this.insertPrefix+'(9004, \'Raw Mixed\', \'raw-mixed\', 1, 3);'
|
|
278
|
+
+'SELECT name FROM test_categories WHERE id = 9004;'
|
|
118
279
|
);
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
assert.strictEqual(result.length, 2);
|
|
122
|
-
assert.strictEqual(result[0].name, 'Raw Sequential 1');
|
|
123
|
-
assert.strictEqual(result[1].name, 'Raw Sequential 2');
|
|
280
|
+
this.assertResultsCount(results, 2);
|
|
281
|
+
this.assertNames(results[1], ['Raw Mixed']);
|
|
124
282
|
});
|
|
125
283
|
}
|
|
126
284
|
|