meadow 2.0.6 → 2.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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meadow",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.11",
|
|
4
4
|
"description": "A data access library.",
|
|
5
5
|
"main": "source/Meadow.js",
|
|
6
6
|
"scripts": {
|
|
@@ -46,28 +46,28 @@
|
|
|
46
46
|
},
|
|
47
47
|
"homepage": "https://github.com/stevenvelozo/meadow",
|
|
48
48
|
"devDependencies": {
|
|
49
|
-
"alasql": "^
|
|
49
|
+
"alasql": "^4.1.3",
|
|
50
50
|
"browserify": "^17.0.0",
|
|
51
51
|
"chai": "4.3.7",
|
|
52
|
-
"fable": "^3.0.
|
|
52
|
+
"fable": "^3.0.75",
|
|
53
53
|
"gulp": "^4.0.2",
|
|
54
54
|
"gulp-babel": "^8.0.0",
|
|
55
55
|
"gulp-sourcemaps": "^3.0.0",
|
|
56
56
|
"gulp-terser": "^2.1.0",
|
|
57
57
|
"gulp-util": "^3.0.8",
|
|
58
|
-
"meadow-connection-mssql": "^1.0.
|
|
59
|
-
"meadow-connection-mysql": "^1.0.
|
|
58
|
+
"meadow-connection-mssql": "^1.0.4",
|
|
59
|
+
"meadow-connection-mysql": "^1.0.4",
|
|
60
60
|
"mocha": "10.2.0",
|
|
61
|
-
"mysql2": "^3.
|
|
61
|
+
"mysql2": "^3.5.2",
|
|
62
62
|
"nyc": "^15.1.0",
|
|
63
63
|
"vinyl-buffer": "^1.0.1",
|
|
64
64
|
"vinyl-source-stream": "^2.0.0"
|
|
65
65
|
},
|
|
66
66
|
"dependencies": {
|
|
67
67
|
"async": "3.2.4",
|
|
68
|
-
"foxhound": "^2.0.
|
|
68
|
+
"foxhound": "^2.0.10",
|
|
69
69
|
"is-my-json-valid": "2.20.6",
|
|
70
|
-
"npm-check-updates": "^16.10.
|
|
70
|
+
"npm-check-updates": "^16.10.17",
|
|
71
71
|
"simple-get": "^4.0.1"
|
|
72
72
|
}
|
|
73
73
|
}
|
package/source/Meadow.js
CHANGED
|
@@ -135,6 +135,7 @@ var Meadow = function()
|
|
|
135
135
|
'ALASQL': require(`./providers/Meadow-Provider-ALASQL.js`),
|
|
136
136
|
'MeadowEndpoints': require(`./providers/Meadow-Provider-MeadowEndpoints.js`),
|
|
137
137
|
'MySQL': require(`./providers/Meadow-Provider-MySQL.js`),
|
|
138
|
+
'MSSQL': require(`./providers/Meadow-Provider-MSSQL.js`),
|
|
138
139
|
'None': require(`./providers/Meadow-Provider-None.js`),
|
|
139
140
|
});
|
|
140
141
|
var setProvider = function(pProviderName)
|
|
@@ -46,6 +46,36 @@ var MeadowProvider = function ()
|
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
|
|
49
|
+
var getPreparedStatementFromQuery = function (pQuery)
|
|
50
|
+
{
|
|
51
|
+
// Create the MS SQL Prepared Statement class
|
|
52
|
+
let tmpPreparedStatement = _Fable.MeadowMSSQLProvider.preparedStatement;
|
|
53
|
+
// Map the Parameters to Types
|
|
54
|
+
let tmpParameterTypeKeys = Object.keys(pQuery.query.parameterTypes)
|
|
55
|
+
for (let i = 0; i < tmpParameterTypeKeys.length; i++)
|
|
56
|
+
{
|
|
57
|
+
let tmpParameterType = pQuery.query.parameterTypes[tmpParameterTypeKeys[i]];
|
|
58
|
+
if (_Fable.MeadowMSSQLProvider.MSSQL[tmpParameterType] === undefined)
|
|
59
|
+
{
|
|
60
|
+
tmpParameterType = 'Char';
|
|
61
|
+
}
|
|
62
|
+
// TODO: Decide how to filter better cleansing to this layer from the schema; we have access to proper lengths.
|
|
63
|
+
// BEFORE WE ADD THIS BEHAVIOR, DECIDE CONCISTENCY WITH OTHER PROVIDERS WHO ALLOW OVERFLOWING STRINGS
|
|
64
|
+
let tmpParameterEntry = false;
|
|
65
|
+
if ((tmpParameterType === 'Char') || (tmpParameterType === 'VarChar'))
|
|
66
|
+
{
|
|
67
|
+
tmpParameterEntry = _Fable.MeadowMSSQLProvider.MSSQL[tmpParameterType](64);
|
|
68
|
+
}
|
|
69
|
+
else
|
|
70
|
+
{
|
|
71
|
+
tmpParameterEntry = _Fable.MeadowMSSQLProvider.MSSQL[tmpParameterType];
|
|
72
|
+
}
|
|
73
|
+
tmpPreparedStatement.input(tmpParameterTypeKeys[i], tmpParameterEntry);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return tmpPreparedStatement;
|
|
77
|
+
};
|
|
78
|
+
|
|
49
79
|
var Create = function (pQuery, fCallback)
|
|
50
80
|
{
|
|
51
81
|
var tmpResult = pQuery.parameters.result;
|
|
@@ -53,37 +83,51 @@ var MeadowProvider = function ()
|
|
|
53
83
|
pQuery.setDialect('MSSQL').buildCreateQuery();
|
|
54
84
|
|
|
55
85
|
// TODO: Test the query before executing
|
|
56
|
-
if (pQuery.logLevel > 0 ||
|
|
57
|
-
_GlobalLogLevel > 0)
|
|
86
|
+
if (pQuery.logLevel > 0 || _GlobalLogLevel > 0)
|
|
58
87
|
{
|
|
59
88
|
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
60
89
|
}
|
|
61
90
|
|
|
62
|
-
|
|
63
|
-
{
|
|
64
|
-
pDBConnection.query(
|
|
65
|
-
pQuery.query.body,
|
|
66
|
-
pQuery.query.parameters,
|
|
67
|
-
// The MSSQL library also returns the Fields as the third parameter
|
|
68
|
-
function (pError, pRows)
|
|
69
|
-
{
|
|
70
|
-
pDBConnection.release();
|
|
71
|
-
tmpResult.error = pError;
|
|
72
|
-
tmpResult.value = false;
|
|
73
|
-
try
|
|
74
|
-
{
|
|
75
|
-
tmpResult.value = pRows.insertId;
|
|
76
|
-
}
|
|
77
|
-
catch (pErrorGettingRowcount)
|
|
78
|
-
{
|
|
79
|
-
_Fable.log.warn('Error getting insert ID during create query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
|
|
80
|
-
}
|
|
91
|
+
let tmpPreparedStatement = getPreparedStatementFromQuery(pQuery);
|
|
81
92
|
|
|
82
|
-
|
|
83
|
-
|
|
93
|
+
let tmpQueryBody = `${pQuery.query.body} \nSELECT @@IDENTITY AS value;`
|
|
94
|
+
|
|
95
|
+
tmpPreparedStatement.prepare(tmpQueryBody,
|
|
96
|
+
(pPrepareError) =>
|
|
97
|
+
{
|
|
98
|
+
// TODO: This will likely blow up the world. It will definitely happen when the schema doesn't generate good constraints from the inputs.
|
|
99
|
+
if (pPrepareError)
|
|
100
|
+
{
|
|
101
|
+
_Fable.log.error(`CREATE Error preparing prepared statement: ${pPrepareError}`, pPrepareError);
|
|
84
102
|
}
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
|
|
104
|
+
tmpPreparedStatement.execute(pQuery.query.parameters,
|
|
105
|
+
(pPreparedExecutionError, pPreparedResult) =>
|
|
106
|
+
{
|
|
107
|
+
// release the connection after queries are executed
|
|
108
|
+
tmpPreparedStatement.unprepare(
|
|
109
|
+
(pPreparedStatementUnprepareError) =>
|
|
110
|
+
{
|
|
111
|
+
if (pPreparedStatementUnprepareError)
|
|
112
|
+
{
|
|
113
|
+
_Fable.log.error(`CREATE Error unpreparing prepared statement: ${pPreparedStatementUnprepareError}`, pPreparedStatementUnprepareError);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
tmpResult.error = pPreparedExecutionError;
|
|
117
|
+
if (pPreparedResult
|
|
118
|
+
&& Array.isArray(pPreparedResult.recordset)
|
|
119
|
+
&& (pPreparedResult.recordset.length > 0)
|
|
120
|
+
&& (pPreparedResult.recordset[0].value))
|
|
121
|
+
{
|
|
122
|
+
tmpResult.value = pPreparedResult.recordset[0].value;
|
|
123
|
+
}
|
|
124
|
+
tmpResult.executed = true;
|
|
125
|
+
|
|
126
|
+
// TODO: Fix very old pattern by es6-izing this whole bash
|
|
127
|
+
return fCallback();
|
|
128
|
+
});
|
|
129
|
+
});
|
|
130
|
+
});
|
|
87
131
|
};
|
|
88
132
|
|
|
89
133
|
// This is a synchronous read, good for a few records.
|
|
@@ -100,42 +144,43 @@ var MeadowProvider = function ()
|
|
|
100
144
|
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
101
145
|
}
|
|
102
146
|
|
|
103
|
-
let tmpPreparedStatement =
|
|
104
|
-
// Now define the inputs for the prepared statement based on the parameters and the schema.
|
|
105
|
-
|
|
106
|
-
//tmpPreparedStatement.input('param', _Fable.MeadowMSSQLProvider.MSSQL.Int);
|
|
147
|
+
let tmpPreparedStatement = getPreparedStatementFromQuery(pQuery);
|
|
107
148
|
tmpPreparedStatement.prepare(pQuery.query.body,
|
|
108
149
|
(pPrepareError) =>
|
|
109
150
|
{
|
|
151
|
+
// TODO: This will likely blow up the world. It will definitely happen when the schema doesn't generate good constraints from the inputs.
|
|
152
|
+
if (pPrepareError)
|
|
153
|
+
{
|
|
154
|
+
_Fable.log.error(`READ Error preparing prepared statement: ${pPrepareError}`, pPrepareError);
|
|
155
|
+
}
|
|
156
|
+
|
|
110
157
|
tmpPreparedStatement.execute(pQuery.query.parameters,
|
|
111
158
|
(pPreparedExecutionError, pPreparedResult) =>
|
|
112
159
|
{
|
|
113
|
-
_Fable.log.info(`Prepared statement returned...`, pPreparedResult);
|
|
114
160
|
// release the connection after queries are executed
|
|
115
161
|
tmpPreparedStatement.unprepare(
|
|
116
162
|
(pPreparedStatementUnprepareError) =>
|
|
117
163
|
{
|
|
118
|
-
|
|
119
|
-
|
|
164
|
+
if (pPreparedStatementUnprepareError)
|
|
165
|
+
{
|
|
166
|
+
_Fable.log.error(`READ Error unpreparing prepared statement: ${pPreparedStatementUnprepareError}`, pPreparedStatementUnprepareError);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
//_Fable.log.info(`Prepared statement returned...`, pPreparedResult);
|
|
170
|
+
tmpResult.error = pPreparedExecutionError;
|
|
171
|
+
try
|
|
172
|
+
{
|
|
173
|
+
tmpResult.value = pPreparedResult.recordset;
|
|
174
|
+
}
|
|
175
|
+
catch(pMarshalError)
|
|
176
|
+
{
|
|
177
|
+
_Fable.log.error(`READ Error marshaling prepared statement result: ${pMarshalError}`, pMarshalError);
|
|
178
|
+
}
|
|
179
|
+
tmpResult.executed = true;
|
|
180
|
+
return fCallback();
|
|
120
181
|
});
|
|
121
182
|
})
|
|
122
183
|
});
|
|
123
|
-
getSQLPool().getConnection(function (pError, pDBConnection)
|
|
124
|
-
{
|
|
125
|
-
pDBConnection.query(
|
|
126
|
-
pQuery.query.body,
|
|
127
|
-
pQuery.query.parameters,
|
|
128
|
-
// The MSSQL library also returns the Fields as the third parameter
|
|
129
|
-
function (pError, pRows)
|
|
130
|
-
{
|
|
131
|
-
pDBConnection.release();
|
|
132
|
-
tmpResult.error = pError;
|
|
133
|
-
tmpResult.value = pRows;
|
|
134
|
-
tmpResult.executed = true;
|
|
135
|
-
return fCallback();
|
|
136
|
-
}
|
|
137
|
-
);
|
|
138
|
-
});
|
|
139
184
|
};
|
|
140
185
|
|
|
141
186
|
var Update = function (pQuery, fCallback)
|
|
@@ -150,22 +195,36 @@ var MeadowProvider = function ()
|
|
|
150
195
|
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
151
196
|
}
|
|
152
197
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
function (pError, pRows)
|
|
198
|
+
let tmpPreparedStatement = getPreparedStatementFromQuery(pQuery);
|
|
199
|
+
tmpPreparedStatement.prepare(pQuery.query.body,
|
|
200
|
+
(pPrepareError) =>
|
|
201
|
+
{
|
|
202
|
+
// TODO: This will likely blow up the world. It will definitely happen when the schema doesn't generate good constraints from the inputs.
|
|
203
|
+
if (pPrepareError)
|
|
160
204
|
{
|
|
161
|
-
|
|
162
|
-
tmpResult.error = pError;
|
|
163
|
-
tmpResult.value = pRows;
|
|
164
|
-
tmpResult.executed = true;
|
|
165
|
-
return fCallback();
|
|
205
|
+
_Fable.log.error(`UPDATE Error preparing prepared statement: ${pPrepareError}`, pPrepareError);
|
|
166
206
|
}
|
|
167
|
-
|
|
168
|
-
|
|
207
|
+
|
|
208
|
+
tmpPreparedStatement.execute(pQuery.query.parameters,
|
|
209
|
+
(pPreparedExecutionError, pPreparedResult) =>
|
|
210
|
+
{
|
|
211
|
+
// release the connection after queries are executed
|
|
212
|
+
tmpPreparedStatement.unprepare(
|
|
213
|
+
(pPreparedStatementUnprepareError) =>
|
|
214
|
+
{
|
|
215
|
+
if (pPreparedStatementUnprepareError)
|
|
216
|
+
{
|
|
217
|
+
_Fable.log.error(`UPDATE Error unpreparing prepared statement: ${pPreparedStatementUnprepareError}`, pPreparedStatementUnprepareError);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
//_Fable.log.info(`Prepared statement returned...`, pPreparedResult);
|
|
221
|
+
tmpResult.error = pPreparedExecutionError;
|
|
222
|
+
tmpResult.value = pPreparedResult;
|
|
223
|
+
tmpResult.executed = true;
|
|
224
|
+
return fCallback();
|
|
225
|
+
});
|
|
226
|
+
})
|
|
227
|
+
});
|
|
169
228
|
}
|
|
170
229
|
|
|
171
230
|
var Delete = function (pQuery, fCallback)
|
|
@@ -180,31 +239,44 @@ var MeadowProvider = function ()
|
|
|
180
239
|
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
181
240
|
}
|
|
182
241
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
242
|
+
let tmpPreparedStatement = getPreparedStatementFromQuery(pQuery);
|
|
243
|
+
tmpPreparedStatement.prepare(pQuery.query.body,
|
|
244
|
+
(pPrepareError) =>
|
|
245
|
+
{
|
|
246
|
+
// TODO: This will likely blow up the world. It will definitely happen when the schema doesn't generate good constraints from the inputs.
|
|
247
|
+
if (pPrepareError)
|
|
248
|
+
{
|
|
249
|
+
_Fable.log.error(`DELETE Error preparing prepared statement: ${pPrepareError}`, pPrepareError);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
tmpPreparedStatement.execute(pQuery.query.parameters,
|
|
253
|
+
(pPreparedExecutionError, pPreparedResult) =>
|
|
191
254
|
{
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
255
|
+
// release the connection after queries are executed
|
|
256
|
+
tmpPreparedStatement.unprepare(
|
|
257
|
+
(pPreparedStatementUnprepareError) =>
|
|
258
|
+
{
|
|
259
|
+
if (pPreparedStatementUnprepareError)
|
|
260
|
+
{
|
|
261
|
+
_Fable.log.error(`DELETE Error unpreparing prepared statement: ${pPreparedStatementUnprepareError}`, pPreparedStatementUnprepareError);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
//_Fable.log.info(`Prepared statement returned...`, pPreparedResult);
|
|
265
|
+
tmpResult.error = pPreparedExecutionError;
|
|
266
|
+
tmpResult.value = false;
|
|
267
|
+
try
|
|
268
|
+
{
|
|
269
|
+
tmpResult.value = pPreparedResult.rowsAffected[0];
|
|
270
|
+
}
|
|
271
|
+
catch (pErrorGettingRowcount)
|
|
272
|
+
{
|
|
273
|
+
_Fable.log.warn('Error getting affected rowcount during delete query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
|
|
274
|
+
}
|
|
275
|
+
tmpResult.executed = true;
|
|
276
|
+
return fCallback();
|
|
277
|
+
});
|
|
278
|
+
})
|
|
279
|
+
});
|
|
208
280
|
};
|
|
209
281
|
|
|
210
282
|
var Undelete = function (pQuery, fCallback)
|
|
@@ -219,31 +291,44 @@ var MeadowProvider = function ()
|
|
|
219
291
|
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
220
292
|
}
|
|
221
293
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
294
|
+
let tmpPreparedStatement = getPreparedStatementFromQuery(pQuery);
|
|
295
|
+
tmpPreparedStatement.prepare(pQuery.query.body,
|
|
296
|
+
(pPrepareError) =>
|
|
297
|
+
{
|
|
298
|
+
// TODO: This will likely blow up the world. It will definitely happen when the schema doesn't generate good constraints from the inputs.
|
|
299
|
+
if (pPrepareError)
|
|
300
|
+
{
|
|
301
|
+
_Fable.log.error(`UNDELETE Error preparing prepared statement: ${pPrepareError}`, pPrepareError);
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
tmpPreparedStatement.execute(pQuery.query.parameters,
|
|
305
|
+
(pPreparedExecutionError, pPreparedResult) =>
|
|
230
306
|
{
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
307
|
+
// release the connection after queries are executed
|
|
308
|
+
tmpPreparedStatement.unprepare(
|
|
309
|
+
(pPreparedStatementUnprepareError) =>
|
|
310
|
+
{
|
|
311
|
+
if (pPreparedStatementUnprepareError)
|
|
312
|
+
{
|
|
313
|
+
_Fable.log.error(`UNDELETE Error unpreparing prepared statement: ${pPreparedStatementUnprepareError}`, pPreparedStatementUnprepareError);
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
//_Fable.log.info(`Prepared statement returned...`, pPreparedResult);
|
|
317
|
+
tmpResult.error = pPreparedExecutionError;
|
|
318
|
+
tmpResult.value = false;
|
|
319
|
+
try
|
|
320
|
+
{
|
|
321
|
+
tmpResult.value = pPreparedResult.rowsAffected[0];
|
|
322
|
+
}
|
|
323
|
+
catch (pErrorGettingRowcount)
|
|
324
|
+
{
|
|
325
|
+
_Fable.log.warn('Error getting affected rowcount during undelete query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
|
|
326
|
+
}
|
|
327
|
+
tmpResult.executed = true;
|
|
328
|
+
return fCallback();
|
|
329
|
+
});
|
|
330
|
+
})
|
|
331
|
+
});
|
|
247
332
|
};
|
|
248
333
|
|
|
249
334
|
var Count = function (pQuery, fCallback)
|
|
@@ -258,30 +343,44 @@ var MeadowProvider = function ()
|
|
|
258
343
|
_Fable.log.trace(pQuery.query.body, pQuery.query.parameters);
|
|
259
344
|
}
|
|
260
345
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
function (pError, pRows)
|
|
346
|
+
let tmpPreparedStatement = getPreparedStatementFromQuery(pQuery);
|
|
347
|
+
tmpPreparedStatement.prepare(pQuery.query.body,
|
|
348
|
+
(pPrepareError) =>
|
|
349
|
+
{
|
|
350
|
+
// TODO: This will likely blow up the world. It will definitely happen when the schema doesn't generate good constraints from the inputs.
|
|
351
|
+
if (pPrepareError)
|
|
268
352
|
{
|
|
269
|
-
|
|
270
|
-
tmpResult.executed = true;
|
|
271
|
-
tmpResult.error = pError;
|
|
272
|
-
tmpResult.value = false;
|
|
273
|
-
try
|
|
274
|
-
{
|
|
275
|
-
tmpResult.value = pRows[0].RowCount;
|
|
276
|
-
}
|
|
277
|
-
catch (pErrorGettingRowcount)
|
|
278
|
-
{
|
|
279
|
-
_Fable.log.warn('Error getting rowcount during count query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
|
|
280
|
-
}
|
|
281
|
-
return fCallback();
|
|
353
|
+
_Fable.log.error(`COUNT Error preparing prepared statement: ${pPrepareError}`, pPrepareError);
|
|
282
354
|
}
|
|
283
|
-
|
|
284
|
-
|
|
355
|
+
|
|
356
|
+
tmpPreparedStatement.execute(pQuery.query.parameters,
|
|
357
|
+
(pPreparedExecutionError, pPreparedResult) =>
|
|
358
|
+
{
|
|
359
|
+
// release the connection after queries are executed
|
|
360
|
+
tmpPreparedStatement.unprepare(
|
|
361
|
+
(pPreparedStatementUnprepareError) =>
|
|
362
|
+
{
|
|
363
|
+
if (pPreparedStatementUnprepareError)
|
|
364
|
+
{
|
|
365
|
+
_Fable.log.error(`COUNT Error unpreparing prepared statement: ${pPreparedStatementUnprepareError}`, pPreparedStatementUnprepareError);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
//_Fable.log.info(`Prepared statement returned...`, pPreparedResult);
|
|
369
|
+
tmpResult.error = pPreparedExecutionError;
|
|
370
|
+
tmpResult.value = false;
|
|
371
|
+
try
|
|
372
|
+
{
|
|
373
|
+
tmpResult.value = pPreparedResult.recordset[0].Row_Count;
|
|
374
|
+
}
|
|
375
|
+
catch (pErrorGettingRowcount)
|
|
376
|
+
{
|
|
377
|
+
_Fable.log.warn('Error getting affected rowcount during count query', { Body: pQuery.query.body, Parameters: pQuery.query.parameters });
|
|
378
|
+
}
|
|
379
|
+
tmpResult.executed = true;
|
|
380
|
+
return fCallback();
|
|
381
|
+
});
|
|
382
|
+
})
|
|
383
|
+
});
|
|
285
384
|
};
|
|
286
385
|
|
|
287
386
|
var tmpNewProvider = (
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
var Chai = require("chai");
|
|
12
12
|
var Expect = Chai.expect;
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
var libAsyncWaterfall = require('async/waterfall');
|
|
14
|
+
const libMeadowConnectionMSSQL = require('meadow-connection-mssql');
|
|
16
15
|
|
|
17
16
|
var tmpFableSettings = (
|
|
18
17
|
{
|
|
@@ -44,8 +43,8 @@ var tmpFableSettings = (
|
|
|
44
43
|
|
|
45
44
|
var libFable = new (require('fable'))(tmpFableSettings);
|
|
46
45
|
|
|
47
|
-
|
|
48
|
-
|
|
46
|
+
libFable.serviceManager.addServiceType('MeadowMSSQLProvider', libMeadowConnectionMSSQL);
|
|
47
|
+
libFable.serviceManager.instantiateServiceProvider('MeadowMSSQLProvider');
|
|
49
48
|
|
|
50
49
|
var _AnimalJsonSchema = (
|
|
51
50
|
{
|
|
@@ -78,7 +77,10 @@ var _AnimalSchema = (
|
|
|
78
77
|
{ Column: "UpdatingIDUser", Type: "UpdateIDUser" },
|
|
79
78
|
{ Column: "Deleted", Type: "Deleted" },
|
|
80
79
|
{ Column: "DeletingIDUser", Type: "DeleteIDUser" },
|
|
81
|
-
{ Column: "DeleteDate", Type: "DeleteDate" }
|
|
80
|
+
{ Column: "DeleteDate", Type: "DeleteDate" },
|
|
81
|
+
{ Column: "Name", Type: "String" },
|
|
82
|
+
{ Column: "Type", Type: "String" },
|
|
83
|
+
{ Column: "Age", Type: "Integer" }
|
|
82
84
|
]);
|
|
83
85
|
var _AnimalDefault = (
|
|
84
86
|
{
|
|
@@ -106,7 +108,7 @@ suite
|
|
|
106
108
|
|
|
107
109
|
var getAnimalInsert = function (pName, pType)
|
|
108
110
|
{
|
|
109
|
-
return "INSERT INTO
|
|
111
|
+
return "INSERT INTO FableTest (GUIDAnimal, CreateDate, CreatingIDUser, UpdateDate, UpdatingIDUser, Deleted, DeleteDate, DeletingIDUser, Name, Type) VALUES ('00000000-0000-0000-0000-000000000000', GETUTCDATE(), 1, GETUTCDATE(), 1, 0, NULL, 0, '" + pName + "', '" + pType + "'); ";
|
|
110
112
|
};
|
|
111
113
|
|
|
112
114
|
var newMeadow = function ()
|
|
@@ -127,55 +129,52 @@ suite
|
|
|
127
129
|
// Only do this for the first test.
|
|
128
130
|
if (!_SpooledUp)
|
|
129
131
|
{
|
|
130
|
-
_SQLConnectionPool = libMSSQL.createPool
|
|
131
|
-
(
|
|
132
|
-
{
|
|
133
|
-
connectionLimit: tmpFableSettings.MSSQL.ConnectionPoolLimit,
|
|
134
|
-
host: tmpFableSettings.MSSQL.Server,
|
|
135
|
-
port: tmpFableSettings.MSSQL.Port,
|
|
136
|
-
user: tmpFableSettings.MSSQL.User,
|
|
137
|
-
password: tmpFableSettings.MSSQL.Password,
|
|
138
|
-
database: tmpFableSettings.MSSQL.Database
|
|
139
|
-
}
|
|
140
|
-
);
|
|
141
|
-
|
|
142
132
|
// Tear down previous test data
|
|
143
|
-
|
|
133
|
+
libFable.Utility.waterfall(
|
|
144
134
|
[
|
|
145
|
-
function (
|
|
135
|
+
function (fStageComplete)
|
|
136
|
+
{
|
|
137
|
+
libFable.MeadowMSSQLProvider.connectAsync(
|
|
138
|
+
(pError, pConnectionPool) =>
|
|
139
|
+
{
|
|
140
|
+
if (pError)
|
|
141
|
+
{
|
|
142
|
+
libFable.log.error(`Error connecting to MS SQL Database: ${pError}`);
|
|
143
|
+
fStageComplete(pError);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
libFable.log.info('Connection opened!');
|
|
147
|
+
return fStageComplete();
|
|
148
|
+
}
|
|
149
|
+
);
|
|
150
|
+
},
|
|
151
|
+
function (fStageComplete)
|
|
146
152
|
{
|
|
147
|
-
|
|
148
|
-
function (pErrorUpdate, pResponse) { fCallBack(null); });
|
|
153
|
+
libFable.MeadowMSSQLProvider.pool.query('DROP TABLE IF EXISTS FableTest').then(()=>{ return fStageComplete(); }).catch(fStageComplete);
|
|
149
154
|
},
|
|
150
|
-
function (
|
|
155
|
+
function (fStageComplete)
|
|
151
156
|
{
|
|
152
|
-
|
|
153
|
-
function (pErrorUpdate, pResponse) { fCallBack(null); });
|
|
157
|
+
libFable.MeadowMSSQLProvider.pool.query("CREATE TABLE FableTest (IDAnimal INT IDENTITY(1,1) NOT NULL, GUIDAnimal VARCHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000', CreateDate DATETIME, CreatingIDUser INT NOT NULL DEFAULT '0', UpdateDate DATETIME, UpdatingIDUser INT NOT NULL DEFAULT '0', Deleted TINYINT NOT NULL DEFAULT '0', DeleteDate DATETIME, DeletingIDUser INT NOT NULL DEFAULT '0', Name VARCHAR(128) NOT NULL DEFAULT '', Type VARCHAR(128) NOT NULL DEFAULT '' );").then(()=>{ return fStageComplete(); }).catch(fStageComplete);
|
|
154
158
|
},
|
|
155
|
-
function (
|
|
159
|
+
function (fStageComplete)
|
|
156
160
|
{
|
|
157
|
-
|
|
158
|
-
function (pErrorUpdate, pResponse) { fCallBack(null); });
|
|
161
|
+
libFable.MeadowMSSQLProvider.pool.query(getAnimalInsert('Foo Foo', 'Bunny')).then(()=>{ return fStageComplete(); }).catch(fStageComplete);
|
|
159
162
|
},
|
|
160
|
-
function (
|
|
163
|
+
function (fStageComplete)
|
|
161
164
|
{
|
|
162
|
-
|
|
163
|
-
function (pErrorUpdate, pResponse) { fCallBack(null); });
|
|
165
|
+
libFable.MeadowMSSQLProvider.pool.query(getAnimalInsert('Red Riding Hood', 'Girl')).then(()=>{ return fStageComplete(); }).catch(fStageComplete);
|
|
164
166
|
},
|
|
165
|
-
function (
|
|
167
|
+
function (fStageComplete)
|
|
166
168
|
{
|
|
167
|
-
|
|
168
|
-
function (pErrorUpdate, pResponse) { fCallBack(null); });
|
|
169
|
+
libFable.MeadowMSSQLProvider.pool.query(getAnimalInsert('Red', 'Dog')).then(()=>{ return fStageComplete(); }).catch(fStageComplete);
|
|
169
170
|
},
|
|
170
|
-
function (
|
|
171
|
+
function (fStageComplete)
|
|
171
172
|
{
|
|
172
|
-
|
|
173
|
-
function (pErrorUpdate, pResponse) { fCallBack(null); });
|
|
173
|
+
libFable.MeadowMSSQLProvider.pool.query(getAnimalInsert('Spot', 'Dog')).then(()=>{ return fStageComplete(); }).catch(fStageComplete);
|
|
174
174
|
},
|
|
175
|
-
function (
|
|
175
|
+
function (fStageComplete)
|
|
176
176
|
{
|
|
177
|
-
|
|
178
|
-
function (pErrorUpdate, pResponse) { fCallBack(null); });
|
|
177
|
+
libFable.MeadowMSSQLProvider.pool.query(getAnimalInsert('Gertrude', 'Frog')).then(()=>{ return fStageComplete(); }).catch(fStageComplete);
|
|
179
178
|
}
|
|
180
179
|
],
|
|
181
180
|
function (pError, pResult)
|
|
@@ -195,7 +194,7 @@ suite
|
|
|
195
194
|
|
|
196
195
|
suiteTeardown((fDone) =>
|
|
197
196
|
{
|
|
198
|
-
_SQLConnectionPool.end(fDone);
|
|
197
|
+
//_SQLConnectionPool.end(fDone);
|
|
199
198
|
}
|
|
200
199
|
);
|
|
201
200
|
|
|
@@ -248,55 +247,6 @@ suite
|
|
|
248
247
|
}
|
|
249
248
|
);
|
|
250
249
|
test
|
|
251
|
-
(
|
|
252
|
-
'New provider format',
|
|
253
|
-
function (fDone)
|
|
254
|
-
{
|
|
255
|
-
let _FableClass = require('fable');
|
|
256
|
-
let _Fable = new _FableClass({
|
|
257
|
-
MSSQL:
|
|
258
|
-
{
|
|
259
|
-
// This is queued up for Travis defaults.
|
|
260
|
-
Server: "localhost",
|
|
261
|
-
Port: 3306,
|
|
262
|
-
User: "root",
|
|
263
|
-
Password: "123456789",
|
|
264
|
-
Database: "FableTest",
|
|
265
|
-
ConnectionPoolLimit: 20
|
|
266
|
-
},
|
|
267
|
-
MeadowConnectionMSSQLAutoConnect: true
|
|
268
|
-
});
|
|
269
|
-
_Fable.serviceManager.addAndInstantiateServiceType('MeadowMSSQLProvider', require('meadow-connection-mssql'));
|
|
270
|
-
|
|
271
|
-
var testMeadow = require('../source/Meadow.js')
|
|
272
|
-
.new(_Fable, 'FableTest')
|
|
273
|
-
.setProvider('MSSQL')
|
|
274
|
-
.setSchema(_AnimalSchema)
|
|
275
|
-
.setJsonSchema(_AnimalJsonSchema)
|
|
276
|
-
.setDefaultIdentifier('IDAnimal')
|
|
277
|
-
.setDefault(_AnimalDefault);
|
|
278
|
-
|
|
279
|
-
testMeadow.setIDUser(90210);
|
|
280
|
-
|
|
281
|
-
var tmpQuery = testMeadow.query.addFilter('IDAnimal', 1);
|
|
282
|
-
|
|
283
|
-
testMeadow.doRead(tmpQuery,
|
|
284
|
-
function (pError, pQuery, pRecord)
|
|
285
|
-
{
|
|
286
|
-
// We should have a record ....
|
|
287
|
-
Expect(pRecord.IDAnimal)
|
|
288
|
-
.to.equal(1);
|
|
289
|
-
Expect(pRecord.Name)
|
|
290
|
-
.to.equal('Foo Foo');
|
|
291
|
-
|
|
292
|
-
testMeadow.fable.settings.QueryThresholdWarnTime = 1000;
|
|
293
|
-
|
|
294
|
-
fDone();
|
|
295
|
-
}
|
|
296
|
-
)
|
|
297
|
-
}
|
|
298
|
-
);
|
|
299
|
-
test
|
|
300
250
|
(
|
|
301
251
|
'Create a record in the database with Deleted bit already set',
|
|
302
252
|
function (fDone)
|
|
@@ -753,7 +703,7 @@ suite
|
|
|
753
703
|
function (pError, pQuery, pRecord)
|
|
754
704
|
{
|
|
755
705
|
Expect(pError.code)
|
|
756
|
-
.to.equal("
|
|
706
|
+
.to.equal("ENOTPREPARED");
|
|
757
707
|
fDone();
|
|
758
708
|
}
|
|
759
709
|
)
|
|
@@ -774,7 +724,7 @@ suite
|
|
|
774
724
|
{
|
|
775
725
|
// We should have no record because the default id is IDFableTest and our tables identity is IDAnimal
|
|
776
726
|
Expect(pError.code)
|
|
777
|
-
.to.equal('
|
|
727
|
+
.to.equal('ENOTPREPARED');
|
|
778
728
|
fDone();
|
|
779
729
|
}
|
|
780
730
|
)
|
|
@@ -794,8 +744,8 @@ suite
|
|
|
794
744
|
function (pError, pQuery, pQueryRead, pRecord)
|
|
795
745
|
{
|
|
796
746
|
// We should have no record because the default id is IDFableTest and our tables identity is IDAnimal
|
|
797
|
-
Expect(pError)
|
|
798
|
-
.to.equal('
|
|
747
|
+
Expect(pError.code)
|
|
748
|
+
.to.equal('EPARAM');
|
|
799
749
|
fDone();
|
|
800
750
|
}
|
|
801
751
|
)
|
|
@@ -872,7 +822,7 @@ suite
|
|
|
872
822
|
function (pError, pQuery, pRecord)
|
|
873
823
|
{
|
|
874
824
|
Expect(pError.code)
|
|
875
|
-
.to.equal('
|
|
825
|
+
.to.equal('ENOTPREPARED');
|
|
876
826
|
fDone();
|
|
877
827
|
}
|
|
878
828
|
)
|
|
@@ -892,7 +842,7 @@ suite
|
|
|
892
842
|
function (pError, pQuery, pRecord)
|
|
893
843
|
{
|
|
894
844
|
Expect(pError.code)
|
|
895
|
-
.to.equal('
|
|
845
|
+
.to.equal('ENOTPREPARED');
|
|
896
846
|
fDone();
|
|
897
847
|
}
|
|
898
848
|
)
|
|
@@ -912,7 +862,7 @@ suite
|
|
|
912
862
|
function (pError, pQuery, pRecord)
|
|
913
863
|
{
|
|
914
864
|
Expect(pError.code)
|
|
915
|
-
.to.equal('
|
|
865
|
+
.to.equal('ENOTPREPARED');
|
|
916
866
|
fDone();
|
|
917
867
|
}
|
|
918
868
|
)
|
|
@@ -957,23 +907,6 @@ suite
|
|
|
957
907
|
)
|
|
958
908
|
}
|
|
959
909
|
);
|
|
960
|
-
test
|
|
961
|
-
(
|
|
962
|
-
'Update a record in the database without passing a record in',
|
|
963
|
-
function (fDone)
|
|
964
|
-
{
|
|
965
|
-
var testMeadow = newMeadow();
|
|
966
|
-
|
|
967
|
-
testMeadow.doUpdate(testMeadow.query,
|
|
968
|
-
function (pError, pQuery, pQueryRead, pRecord)
|
|
969
|
-
{
|
|
970
|
-
Expect(pError)
|
|
971
|
-
.to.equal('No record submitted');
|
|
972
|
-
fDone();
|
|
973
|
-
}
|
|
974
|
-
)
|
|
975
|
-
}
|
|
976
|
-
);
|
|
977
910
|
test
|
|
978
911
|
(
|
|
979
912
|
'Update a record in the database with a bad record passed in (no default identifier)',
|
|
@@ -1101,73 +1034,6 @@ suite
|
|
|
1101
1034
|
});
|
|
1102
1035
|
}
|
|
1103
1036
|
);
|
|
1104
|
-
test
|
|
1105
|
-
(
|
|
1106
|
-
'Read records from a custom query, then delete one, then read them again then update and create.',
|
|
1107
|
-
function (fDone)
|
|
1108
|
-
{
|
|
1109
|
-
var testMeadow = newMeadow();
|
|
1110
|
-
testMeadow.setDefaultIdentifier('IDAnimal');
|
|
1111
|
-
testMeadow.rawQueries.setQuery('Delete', 'DELETE FROM FableTest WHERE IDAnimal = 1;')
|
|
1112
|
-
testMeadow.rawQueries.setQuery('Count', 'SELECT 1337 AS RowCount;')
|
|
1113
|
-
testMeadow.rawQueries.setQuery('Read', 'SELECT IDAnimal, Type AS AnimalTypeCustom FROM FableTest <%= Where %>')
|
|
1114
|
-
testMeadow.rawQueries.setQuery('Update', "UPDATE FableTest SET Type = 'FrogLeg' <%= Where %>")
|
|
1115
|
-
|
|
1116
|
-
// And this, my friends, is why we use async.js
|
|
1117
|
-
testMeadow.rawQueries.loadQuery('Reads', __dirname + '/Meadow-Provider-MSSQL-AnimalReadQuery.sql',
|
|
1118
|
-
function (pSuccess)
|
|
1119
|
-
{
|
|
1120
|
-
// Now try to read the record
|
|
1121
|
-
testMeadow.doReads(testMeadow.query.addFilter('IDAnimal', 2),
|
|
1122
|
-
function (pError, pQuery, pRecords)
|
|
1123
|
-
{
|
|
1124
|
-
Expect(pRecords[1].AnimalTypeCustom)
|
|
1125
|
-
.to.equal('HumanGirl');
|
|
1126
|
-
testMeadow.doDelete(testMeadow.query.addFilter('IDAnimal', 2),
|
|
1127
|
-
function (pError, pQuery, pRecord)
|
|
1128
|
-
{
|
|
1129
|
-
// It returns the number of rows deleted
|
|
1130
|
-
Expect(pRecord)
|
|
1131
|
-
.to.equal(1);
|
|
1132
|
-
testMeadow.doCount(testMeadow.query.addFilter('IDAnimal', 2),
|
|
1133
|
-
function (pError, pQuery, pRecord)
|
|
1134
|
-
{
|
|
1135
|
-
// It returns the number of rows deleted
|
|
1136
|
-
Expect(pRecord)
|
|
1137
|
-
.to.equal(1337);
|
|
1138
|
-
var tmpQuery = testMeadow.query
|
|
1139
|
-
.addRecord({ IDAnimal: 5, Type: 'Bartfast' });
|
|
1140
|
-
|
|
1141
|
-
testMeadow.doUpdate(tmpQuery,
|
|
1142
|
-
function (pError, pQuery, pQueryRead, pRecord)
|
|
1143
|
-
{
|
|
1144
|
-
// We should have a record ....
|
|
1145
|
-
Expect(pRecord.AnimalTypeCustom)
|
|
1146
|
-
.to.equal('Bartfast');
|
|
1147
|
-
var tmpQuery = testMeadow.query
|
|
1148
|
-
.addRecord({ Name: 'Bambi', Type: 'CustomSheep' });
|
|
1149
|
-
|
|
1150
|
-
testMeadow.doCreate(tmpQuery,
|
|
1151
|
-
function (pError, pQuery, pQueryRead, pRecord)
|
|
1152
|
-
{
|
|
1153
|
-
// We should have a record ....
|
|
1154
|
-
Expect(pRecord.AnimalTypeCustom)
|
|
1155
|
-
.to.equal('CustomSheep');
|
|
1156
|
-
fDone();
|
|
1157
|
-
}
|
|
1158
|
-
)
|
|
1159
|
-
}
|
|
1160
|
-
)
|
|
1161
|
-
}
|
|
1162
|
-
)
|
|
1163
|
-
}
|
|
1164
|
-
)
|
|
1165
|
-
}
|
|
1166
|
-
)
|
|
1167
|
-
}
|
|
1168
|
-
);
|
|
1169
|
-
}
|
|
1170
|
-
);
|
|
1171
1037
|
test
|
|
1172
1038
|
(
|
|
1173
1039
|
'Create a record in the database with bad fields',
|
|
@@ -1182,7 +1048,7 @@ suite
|
|
|
1182
1048
|
function (pError, pQuery, pQueryRead, pRecord)
|
|
1183
1049
|
{
|
|
1184
1050
|
Expect(pError.code)
|
|
1185
|
-
.to.equal('
|
|
1051
|
+
.to.equal('ENOTPREPARED');
|
|
1186
1052
|
fDone();
|
|
1187
1053
|
}
|
|
1188
1054
|
)
|
|
@@ -24,7 +24,7 @@ var tmpFableSettings = (
|
|
|
24
24
|
Port: 3306,
|
|
25
25
|
User: "root",
|
|
26
26
|
Password: "123456789",
|
|
27
|
-
Database: "
|
|
27
|
+
Database: "bookstore",
|
|
28
28
|
ConnectionPoolLimit: 20
|
|
29
29
|
},
|
|
30
30
|
LogStreams:
|
|
@@ -271,7 +271,7 @@ suite
|
|
|
271
271
|
Port: 3306,
|
|
272
272
|
User: "root",
|
|
273
273
|
Password: "123456789",
|
|
274
|
-
Database: "
|
|
274
|
+
Database: "bookstore",
|
|
275
275
|
ConnectionPoolLimit: 20
|
|
276
276
|
},
|
|
277
277
|
MeadowConnectionMySQLAutoConnect: true
|