meadow-connection-sqlite 1.0.10 → 1.0.11

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.
package/README.md CHANGED
@@ -131,15 +131,15 @@ Generate a `DROP TABLE IF EXISTS` SQL statement for the given table name.
131
131
 
132
132
  | Meadow Type | SQLite Column |
133
133
  |-------------|---------------|
134
- | `ID` | `INT NOT NULL IDENTITY PRIMARY KEY` |
135
- | `GUID` | `VARCHAR(254)` with default GUID |
136
- | `ForeignKey` | `INT UNSIGNED NOT NULL DEFAULT 0` |
137
- | `Numeric` | `INT NOT NULL DEFAULT 0` |
138
- | `Decimal` | `DECIMAL(size)` |
139
- | `String` | `VARCHAR(size) DEFAULT ''` |
134
+ | `ID` | `INTEGER PRIMARY KEY AUTOINCREMENT` |
135
+ | `GUID` | `TEXT DEFAULT '0000...'` |
136
+ | `ForeignKey` | `INTEGER NOT NULL DEFAULT 0` |
137
+ | `Numeric` | `INTEGER NOT NULL DEFAULT 0` |
138
+ | `Decimal` | `REAL` |
139
+ | `String` | `TEXT NOT NULL DEFAULT ''` |
140
140
  | `Text` | `TEXT` |
141
- | `DateTime` | `DATETIME` |
142
- | `Boolean` | `TINYINT DEFAULT 0` |
141
+ | `DateTime` | `TEXT` |
142
+ | `Boolean` | `INTEGER NOT NULL DEFAULT 0` |
143
143
 
144
144
  ## Part of the Retold Framework
145
145
 
package/docs/api.md CHANGED
@@ -251,6 +251,4 @@ The provider logs connection events through the Fable logging system:
251
251
 
252
252
  ## Known Limitations
253
253
 
254
- - **Table generation** — The `generateCreateTableStatement()` and `createTable()` methods produce MSSQL-syntax SQL that is not compatible with SQLite. Use `db.exec()` with SQLite-native `CREATE TABLE` statements instead.
255
- - **Prepared statement getter** — The `preparedStatement` property references an uninitialized connection pool. Use `db.prepare()` directly for prepared statements.
256
254
  - **No async queries** — better-sqlite3 is synchronous by design. For CPU-bound workloads, consider running queries in a worker thread.
@@ -54,7 +54,39 @@ The database file is created automatically if it does not exist. WAL journal mod
54
54
 
55
55
  ## Step 2: Create a Table
56
56
 
57
- Use SQLite-native `CREATE TABLE` syntax through `db.exec()`:
57
+ ### Using createTable()
58
+
59
+ Pass a Meadow table schema object to `createTable()` and it generates the correct SQLite DDL automatically:
60
+
61
+ ```javascript
62
+ let tmpBookSchema =
63
+ {
64
+ TableName: 'Book',
65
+ Columns:
66
+ [
67
+ { Column: 'IDBook', DataType: 'ID' },
68
+ { Column: 'GUIDBook', DataType: 'GUID' },
69
+ { Column: 'Title', DataType: 'String', Size: '256' },
70
+ { Column: 'Author', DataType: 'String', Size: '128' },
71
+ { Column: 'YearPublished', DataType: 'Numeric' },
72
+ { Column: 'Price', DataType: 'Decimal', Size: '10,2' },
73
+ { Column: 'InPrint', DataType: 'Boolean' },
74
+ { Column: 'CreateDate', DataType: 'DateTime' },
75
+ { Column: 'UpdateDate', DataType: 'DateTime' }
76
+ ]
77
+ };
78
+
79
+ _Fable.MeadowSQLiteProvider.createTable(tmpBookSchema,
80
+ (pError) =>
81
+ {
82
+ if (pError) { _Fable.log.error(`Create table failed: ${pError}`); return; }
83
+ // Table is ready for queries
84
+ });
85
+ ```
86
+
87
+ ### Using raw db.exec()
88
+
89
+ For tables with custom constraints, expressions, or indexes, use `db.exec()` directly:
58
90
 
59
91
  ```javascript
60
92
  tmpDB.exec(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "meadow-connection-sqlite",
3
- "version": "1.0.10",
3
+ "version": "1.0.11",
4
4
  "description": "Meadow SQLite Plugin",
5
5
  "main": "source/Meadow-Connection-SQLite.js",
6
6
  "scripts": {
@@ -36,19 +36,16 @@ class MeadowConnectionSQLite extends libFableServiceProviderBase
36
36
 
37
37
  generateDropTableStatement(pTableName)
38
38
  {
39
- let tmpDropTableStatement = `IF OBJECT_ID('dbo.[${pTableName}]', 'U') IS NOT NULL\n`;
40
- tmpDropTableStatement += ` DROP TABLE dbo.[${pTableName}];\n`;
41
- tmpDropTableStatement += `GO`;
42
- return tmpDropTableStatement;
39
+ return `DROP TABLE IF EXISTS ${pTableName};`;
43
40
  }
44
41
 
45
42
  generateCreateTableStatement(pMeadowTableSchema)
46
43
  {
47
- this.log.info(`--> Building the table create string for ${pMeadowTableSchema} ...`);
44
+ this.log.info(`--> Building the table create string for ${pMeadowTableSchema.TableName} ...`);
48
45
 
49
46
  let tmpPrimaryKey = false;
50
47
  let tmpCreateTableStatement = `-- [ ${pMeadowTableSchema.TableName} ]`;
51
- tmpCreateTableStatement += `\nCREATE TABLE [dbo].[${pMeadowTableSchema.TableName}]\n (`;
48
+ tmpCreateTableStatement += `\nCREATE TABLE IF NOT EXISTS ${pMeadowTableSchema.TableName}\n (`;
52
49
  for (let j = 0; j < pMeadowTableSchema.Columns.length; j++)
53
50
  {
54
51
  let tmpColumn = pMeadowTableSchema.Columns[j];
@@ -60,54 +57,40 @@ class MeadowConnectionSQLite extends libFableServiceProviderBase
60
57
  }
61
58
 
62
59
  tmpCreateTableStatement += `\n`;
63
- // Dump out each column......
64
60
  switch (tmpColumn.DataType)
65
61
  {
66
62
  case 'ID':
67
- // if (this.options.AllowIdentityInsert)
68
- // {
69
- // tmpCreateTableStatement += ` [${tmpColumn.Column}] INT NOT NULL PRIMARY KEY`;
70
- // }
71
- // else
72
- // {
73
- // There is debate on whether IDENTITY(1,1) is better or not.
74
- tmpCreateTableStatement += ` [${tmpColumn.Column}] INT NOT NULL IDENTITY PRIMARY KEY`;
75
- //}
63
+ tmpCreateTableStatement += ` ${tmpColumn.Column} INTEGER PRIMARY KEY AUTOINCREMENT`;
76
64
  tmpPrimaryKey = tmpColumn.Column;
77
65
  break;
78
66
  case 'GUID':
79
- tmpCreateTableStatement += ` [${tmpColumn.Column}] VARCHAR(254) DEFAULT '00000000-0000-0000-0000-000000000000'`;
67
+ tmpCreateTableStatement += ` ${tmpColumn.Column} TEXT DEFAULT '00000000-0000-0000-0000-000000000000'`;
80
68
  break;
81
69
  case 'ForeignKey':
82
- tmpCreateTableStatement += ` [${tmpColumn.Column}] INT UNSIGNED NOT NULL DEFAULT 0`;
83
- tmpPrimaryKey = tmpColumn.Column;
70
+ tmpCreateTableStatement += ` ${tmpColumn.Column} INTEGER NOT NULL DEFAULT 0`;
84
71
  break;
85
72
  case 'Numeric':
86
- tmpCreateTableStatement += ` [${tmpColumn.Column}] INT NOT NULL DEFAULT 0`;
73
+ tmpCreateTableStatement += ` ${tmpColumn.Column} INTEGER NOT NULL DEFAULT 0`;
87
74
  break;
88
75
  case 'Decimal':
89
- tmpCreateTableStatement += ` [${tmpColumn.Column}] DECIMAL(${tmpColumn.Size})`;
76
+ tmpCreateTableStatement += ` ${tmpColumn.Column} REAL`;
90
77
  break;
91
78
  case 'String':
92
- tmpCreateTableStatement += ` [${tmpColumn.Column}] VARCHAR(${tmpColumn.Size}) DEFAULT ''`;
79
+ tmpCreateTableStatement += ` ${tmpColumn.Column} TEXT NOT NULL DEFAULT ''`;
93
80
  break;
94
81
  case 'Text':
95
- tmpCreateTableStatement += ` [${tmpColumn.Column}] TEXT`;
82
+ tmpCreateTableStatement += ` ${tmpColumn.Column} TEXT`;
96
83
  break;
97
84
  case 'DateTime':
98
- tmpCreateTableStatement += ` [${tmpColumn.Column}] DATETIME`;
85
+ tmpCreateTableStatement += ` ${tmpColumn.Column} TEXT`;
99
86
  break;
100
87
  case 'Boolean':
101
- tmpCreateTableStatement += ` [${tmpColumn.Column}] TINYINT DEFAULT 0`;
88
+ tmpCreateTableStatement += ` ${tmpColumn.Column} INTEGER NOT NULL DEFAULT 0`;
102
89
  break;
103
90
  default:
104
91
  break;
105
92
  }
106
93
  }
107
- if (tmpPrimaryKey)
108
- {
109
- // tmpCreateTableStatement += `,\n\n PRIMARY KEY (${tmpPrimaryKey$})`;
110
- }
111
94
  tmpCreateTableStatement += `\n );`;
112
95
 
113
96
  this.log.info(`Generated Create Table Statement: ${tmpCreateTableStatement}`);
@@ -136,34 +119,17 @@ class MeadowConnectionSQLite extends libFableServiceProviderBase
136
119
  createTable(pMeadowTableSchema, fCallback)
137
120
  {
138
121
  let tmpCreateTableStatement = this.generateCreateTableStatement(pMeadowTableSchema);
139
- this._ConnectionPool.query(tmpCreateTableStatement)
140
- .then((pResult) =>
141
- {
142
- this.log.info(`Meadow-SQLite CREATE TABLE ${pMeadowTableSchema.TableName} Success`);
143
- this.log.warn(`Meadow-SQLite Create Table Statement: ${tmpCreateTableStatement}`)
144
- return fCallback();
145
- })
146
- .catch((pError) =>
147
- {
148
- if (pError.hasOwnProperty('originalError')
149
- // TODO: This check may be extraneous; not familiar enough with the sqlite node driver yet
150
- && (pError.originalError.hasOwnProperty('info'))
151
- // TODO: Validate that there isn't a better way to find this (pError.code isn't explicit enough)
152
- && (pError.originalError.info.message.indexOf("There is already an object named") == 0)
153
- && (pError.originalError.info.message.indexOf('in the database.') > 0))
154
- {
155
- // The table already existed; log a warning but keep on keeping on.
156
- //this.log.warn(`Meadow-SQLite CREATE TABLE ${pMeadowTableSchema.TableName} executed but table already existed.`);
157
- //this.log.warn(`Meadow-SQLite Create Table Statement: ${tmpCreateTableStatement}`)
158
- return fCallback();
159
- }
160
- else
161
- {
162
- this.log.error(`Meadow-SQLite CREATE TABLE ${pMeadowTableSchema.TableName} failed!`, pError);
163
- //this.log.warn(`Meadow-SQLite Create Table Statement: ${tmpCreateTableStatement}`)
164
- return fCallback(pError);
165
- }
166
- });
122
+ try
123
+ {
124
+ this._database.exec(tmpCreateTableStatement);
125
+ this.log.info(`Meadow-SQLite CREATE TABLE ${pMeadowTableSchema.TableName} Success`);
126
+ return fCallback();
127
+ }
128
+ catch (pError)
129
+ {
130
+ this.log.error(`Meadow-SQLite CREATE TABLE ${pMeadowTableSchema.TableName} failed!`, pError);
131
+ return fCallback(pError);
132
+ }
167
133
  }
168
134
 
169
135
  connect()
@@ -222,13 +188,15 @@ class MeadowConnectionSQLite extends libFableServiceProviderBase
222
188
 
223
189
  get preparedStatement()
224
190
  {
225
- if (this.connected && this._ConnectionPool)
191
+ if (this.connected && this._database)
226
192
  {
227
- return new libSQLite.PreparedStatement(this._ConnectionPool);
193
+ // In better-sqlite3, prepared statements are created via db.prepare(sql)
194
+ // This getter is maintained for API consistency with other providers.
195
+ return this._database;
228
196
  }
229
197
  else
230
198
  {
231
- throw new Error('The Meadow Microsoft SQL provider could not create a prepared statement; disconnected or no valid connection pool.');
199
+ throw new Error('The Meadow SQLite provider is not connected; cannot create a prepared statement.');
232
200
  }
233
201
  }
234
202
 
@@ -34,6 +34,40 @@ const _FableConfig = (
34
34
  }
35
35
  });
36
36
 
37
+ // A sample Stricture-compiled Meadow table schema
38
+ const _BookTableSchema =
39
+ {
40
+ TableName: 'Book',
41
+ Domain: 'Default',
42
+ Columns:
43
+ [
44
+ { Column: 'IDBook', DataType: 'ID' },
45
+ { Column: 'GUIDBook', DataType: 'GUID' },
46
+ { Column: 'Title', DataType: 'String', Size: '256' },
47
+ { Column: 'Description', DataType: 'Text' },
48
+ { Column: 'Price', DataType: 'Decimal', Size: '10,2' },
49
+ { Column: 'PageCount', DataType: 'Numeric' },
50
+ { Column: 'PublishDate', DataType: 'DateTime' },
51
+ { Column: 'InPrint', DataType: 'Boolean' },
52
+ { Column: 'IDAuthor', DataType: 'ForeignKey' }
53
+ ],
54
+ Description: 'A table of books'
55
+ };
56
+
57
+ const _AuthorTableSchema =
58
+ {
59
+ TableName: 'Author',
60
+ Domain: 'Default',
61
+ Columns:
62
+ [
63
+ { Column: 'IDAuthor', DataType: 'ID' },
64
+ { Column: 'GUIDAuthor', DataType: 'GUID' },
65
+ { Column: 'Name', DataType: 'String', Size: '128' },
66
+ { Column: 'Bio', DataType: 'Text' }
67
+ ],
68
+ Description: 'A table of authors'
69
+ };
70
+
37
71
  suite
38
72
  (
39
73
  'Connection',
@@ -46,10 +80,10 @@ suite
46
80
  {
47
81
  libFS.unlinkSync('./dist/FableTest.db');
48
82
  }
49
-
50
- let _Fable = new libFable(_FableConfig);
51
- _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
52
- _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
83
+ if (!libFS.existsSync('./dist'))
84
+ {
85
+ libFS.mkdirSync('./dist', { recursive: true });
86
+ }
53
87
  return fDone();
54
88
  });
55
89
 
@@ -72,18 +106,324 @@ suite
72
106
  _Fable.MeadowSQLiteProvider.connectAsync(
73
107
  (pError) =>
74
108
  {
75
- if (pError)
76
- {
77
- return fDone(pError);
78
- }
79
- let tmpRows = _Fable.MeadowSQLiteProvider.db.prepare(`SELECT * FROM FableTest`).get();
80
- Expect(tmpRows).to.be.an('array');
109
+ Expect(pError).to.not.exist;
110
+ Expect(_Fable.MeadowSQLiteProvider.connected).to.equal(true);
111
+ Expect(_Fable.MeadowSQLiteProvider.db).to.be.an('object');
81
112
  return fDone();
82
113
  }
83
114
  );
84
115
  }
85
116
  );
117
+
118
+ test
119
+ (
120
+ 'attempt to connect twice should not error',
121
+ (fDone) =>
122
+ {
123
+ let _Fable = new libFable(_FableConfig);
124
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
125
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
126
+
127
+ _Fable.MeadowSQLiteProvider.connectAsync(
128
+ (pError) =>
129
+ {
130
+ Expect(pError).to.not.exist;
131
+ // Connect again -- should log an error but callback with the existing database
132
+ _Fable.MeadowSQLiteProvider.connectAsync(
133
+ (pSecondError, pDatabase) =>
134
+ {
135
+ // Should not be a hard error
136
+ Expect(pSecondError).to.not.exist;
137
+ Expect(pDatabase).to.be.an('object');
138
+ return fDone();
139
+ });
140
+ });
141
+ }
142
+ );
143
+
144
+ test
145
+ (
146
+ 'connect without a callback should not throw',
147
+ (fDone) =>
148
+ {
149
+ let _Fable = new libFable(_FableConfig);
150
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
151
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
152
+
153
+ // Call connect() (sync wrapper) which calls connectAsync without a callback
154
+ _Fable.MeadowSQLiteProvider.connect();
155
+ // Give it a tick to complete
156
+ setTimeout(
157
+ () =>
158
+ {
159
+ Expect(_Fable.MeadowSQLiteProvider.connected).to.equal(true);
160
+ return fDone();
161
+ }, 100);
162
+ }
163
+ );
164
+
165
+ test
166
+ (
167
+ 'fail to connect with no SQLiteFilePath',
168
+ (fDone) =>
169
+ {
170
+ let _Fable = new libFable(
171
+ {
172
+ Product: 'MeadowSQLiteTestNoPath',
173
+ ProductVersion: '1.0.0'
174
+ });
175
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
176
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
177
+
178
+ _Fable.MeadowSQLiteProvider.connectAsync(
179
+ (pError) =>
180
+ {
181
+ Expect(pError).to.be.an.instanceof(Error);
182
+ return fDone();
183
+ });
184
+ }
185
+ );
186
+ }
187
+ );
188
+
189
+ suite
190
+ (
191
+ 'DDL Generation',
192
+ ()=>
193
+ {
194
+ test
195
+ (
196
+ 'generate a DROP TABLE statement',
197
+ (fDone) =>
198
+ {
199
+ let _Fable = new libFable(_FableConfig);
200
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
201
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
202
+
203
+ let tmpDropStatement = _Fable.MeadowSQLiteProvider.generateDropTableStatement('Book');
204
+ Expect(tmpDropStatement).to.equal('DROP TABLE IF EXISTS Book;');
205
+ return fDone();
206
+ }
207
+ );
208
+
209
+ test
210
+ (
211
+ 'generate a CREATE TABLE statement from a Meadow table schema',
212
+ (fDone) =>
213
+ {
214
+ let _Fable = new libFable(_FableConfig);
215
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
216
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
217
+
218
+ _Fable.MeadowSQLiteProvider.connectAsync(
219
+ (pError) =>
220
+ {
221
+ Expect(pError).to.not.exist;
222
+ let tmpCreateStatement = _Fable.MeadowSQLiteProvider.generateCreateTableStatement(_BookTableSchema);
223
+
224
+ // Should use SQLite syntax, not MSSQL
225
+ Expect(tmpCreateStatement).to.contain('CREATE TABLE IF NOT EXISTS Book');
226
+ Expect(tmpCreateStatement).to.contain('IDBook INTEGER PRIMARY KEY AUTOINCREMENT');
227
+ Expect(tmpCreateStatement).to.contain('GUIDBook TEXT DEFAULT');
228
+ Expect(tmpCreateStatement).to.contain('Title TEXT NOT NULL DEFAULT');
229
+ Expect(tmpCreateStatement).to.contain('Description TEXT');
230
+ Expect(tmpCreateStatement).to.contain('Price REAL');
231
+ Expect(tmpCreateStatement).to.contain('PageCount INTEGER NOT NULL DEFAULT 0');
232
+ Expect(tmpCreateStatement).to.contain('PublishDate TEXT');
233
+ Expect(tmpCreateStatement).to.contain('InPrint INTEGER NOT NULL DEFAULT 0');
234
+ Expect(tmpCreateStatement).to.contain('IDAuthor INTEGER NOT NULL DEFAULT 0');
235
+
236
+ // Should NOT contain any MSSQL syntax
237
+ Expect(tmpCreateStatement).to.not.contain('[dbo]');
238
+ Expect(tmpCreateStatement).to.not.contain('IDENTITY');
239
+ Expect(tmpCreateStatement).to.not.contain('UNSIGNED');
240
+ Expect(tmpCreateStatement).to.not.contain('TINYINT');
241
+ Expect(tmpCreateStatement).to.not.contain('VARCHAR');
242
+
243
+ return fDone();
244
+ });
245
+ }
246
+ );
247
+ }
248
+ );
249
+
250
+ suite
251
+ (
252
+ 'Create Tables',
253
+ ()=>
254
+ {
255
+ test
256
+ (
257
+ 'create a single table',
258
+ (fDone) =>
259
+ {
260
+ let _Fable = new libFable(_FableConfig);
261
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
262
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
263
+
264
+ _Fable.MeadowSQLiteProvider.connectAsync(
265
+ (pError) =>
266
+ {
267
+ Expect(pError).to.not.exist;
268
+
269
+ _Fable.MeadowSQLiteProvider.createTable(_BookTableSchema,
270
+ (pCreateError) =>
271
+ {
272
+ Expect(pCreateError).to.not.exist;
273
+
274
+ // Verify the table was actually created by inserting and reading back
275
+ let tmpDB = _Fable.MeadowSQLiteProvider.db;
276
+ tmpDB.prepare('INSERT INTO Book (Title, Price, PageCount, InPrint) VALUES (?, ?, ?, ?)').run('Test Book', 19.99, 200, 1);
277
+
278
+ let tmpRow = tmpDB.prepare('SELECT * FROM Book WHERE IDBook = 1').get();
279
+ Expect(tmpRow).to.be.an('object');
280
+ Expect(tmpRow.Title).to.equal('Test Book');
281
+ Expect(tmpRow.Price).to.equal(19.99);
282
+ Expect(tmpRow.PageCount).to.equal(200);
283
+ Expect(tmpRow.InPrint).to.equal(1);
284
+ Expect(tmpRow.IDAuthor).to.equal(0);
285
+ Expect(tmpRow.GUIDBook).to.equal('00000000-0000-0000-0000-000000000000');
286
+ return fDone();
287
+ });
288
+ });
289
+ }
290
+ );
291
+
292
+ test
293
+ (
294
+ 'create a table that already exists (idempotent)',
295
+ (fDone) =>
296
+ {
297
+ let _Fable = new libFable(_FableConfig);
298
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
299
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
300
+
301
+ _Fable.MeadowSQLiteProvider.connectAsync(
302
+ (pError) =>
303
+ {
304
+ Expect(pError).to.not.exist;
305
+
306
+ // Create the table
307
+ _Fable.MeadowSQLiteProvider.createTable(_BookTableSchema,
308
+ (pCreateError) =>
309
+ {
310
+ Expect(pCreateError).to.not.exist;
311
+
312
+ // Create it again -- should not error because of IF NOT EXISTS
313
+ _Fable.MeadowSQLiteProvider.createTable(_BookTableSchema,
314
+ (pSecondCreateError) =>
315
+ {
316
+ Expect(pSecondCreateError).to.not.exist;
317
+ return fDone();
318
+ });
319
+ });
320
+ });
321
+ }
322
+ );
323
+
324
+ test
325
+ (
326
+ 'create multiple tables from a schema',
327
+ (fDone) =>
328
+ {
329
+ let _Fable = new libFable(_FableConfig);
330
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
331
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
332
+
333
+ _Fable.MeadowSQLiteProvider.connectAsync(
334
+ (pError) =>
335
+ {
336
+ Expect(pError).to.not.exist;
337
+
338
+ let tmpSchema =
339
+ {
340
+ Tables:
341
+ [
342
+ _BookTableSchema,
343
+ _AuthorTableSchema
344
+ ]
345
+ };
346
+
347
+ _Fable.MeadowSQLiteProvider.createTables(tmpSchema,
348
+ (pCreateError) =>
349
+ {
350
+ Expect(pCreateError).to.not.exist;
351
+
352
+ // Verify both tables exist
353
+ let tmpDB = _Fable.MeadowSQLiteProvider.db;
354
+
355
+ tmpDB.prepare('INSERT INTO Author (Name) VALUES (?)').run('Test Author');
356
+ let tmpAuthor = tmpDB.prepare('SELECT * FROM Author WHERE IDAuthor = 1').get();
357
+ Expect(tmpAuthor).to.be.an('object');
358
+ Expect(tmpAuthor.Name).to.equal('Test Author');
359
+
360
+ tmpDB.prepare('INSERT INTO Book (Title, IDAuthor) VALUES (?, ?)').run('Author Book', 1);
361
+ let tmpBook = tmpDB.prepare('SELECT * FROM Book WHERE IDBook = 1').get();
362
+ Expect(tmpBook).to.be.an('object');
363
+ Expect(tmpBook.Title).to.equal('Author Book');
364
+ Expect(tmpBook.IDAuthor).to.equal(1);
365
+
366
+ return fDone();
367
+ });
368
+ });
369
+ }
370
+ );
371
+ }
372
+ );
373
+
374
+ suite
375
+ (
376
+ 'Accessors',
377
+ ()=>
378
+ {
379
+ test
380
+ (
381
+ 'access the SQLite library via the SQLite getter',
382
+ (fDone) =>
383
+ {
384
+ let _Fable = new libFable(_FableConfig);
385
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
386
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
387
+
388
+ Expect(_Fable.MeadowSQLiteProvider.SQLite).to.be.a('function');
389
+ return fDone();
390
+ }
391
+ );
392
+
393
+ test
394
+ (
395
+ 'access the preparedStatement getter when connected',
396
+ (fDone) =>
397
+ {
398
+ let _Fable = new libFable(_FableConfig);
399
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
400
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
401
+
402
+ _Fable.MeadowSQLiteProvider.connectAsync(
403
+ (pError) =>
404
+ {
405
+ Expect(pError).to.not.exist;
406
+ let tmpPrepared = _Fable.MeadowSQLiteProvider.preparedStatement;
407
+ Expect(tmpPrepared).to.be.an('object');
408
+ return fDone();
409
+ });
410
+ }
411
+ );
412
+
413
+ test
414
+ (
415
+ 'preparedStatement getter throws when disconnected',
416
+ (fDone) =>
417
+ {
418
+ let _Fable = new libFable(_FableConfig);
419
+ _Fable.serviceManager.addServiceType('MeadowSQLiteProvider', libMeadowConnectionSQLite);
420
+ _Fable.serviceManager.instantiateServiceProvider('MeadowSQLiteProvider');
421
+
422
+ Expect(() => _Fable.MeadowSQLiteProvider.preparedStatement).to.throw('The Meadow SQLite provider is not connected');
423
+ return fDone();
424
+ }
425
+ );
86
426
  }
87
427
  );
88
428
  }
89
- );
429
+ );