retold-data-service 1.0.2 → 1.0.3

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.
Files changed (77) hide show
  1. package/.config/configstore/update-notifier-npm-check-updates.json +1 -1
  2. package/.config/configstore/update-notifier-npm.json +1 -1
  3. package/.config/vscode-sqltools/runningInfo.json +13 -0
  4. package/.vscode/launch.json +24 -0
  5. package/.vscode/settings.json +17 -0
  6. package/Dockerfile_LUXURYCode +94 -0
  7. package/debug/Harness.js +34 -2
  8. package/debug/bookstore-configuration.json +29 -0
  9. package/debug/bookstore-serve-meadow-endpoint-apis.js +41 -0
  10. package/debug/data/books.csv +10001 -0
  11. package/debug/model/bookstore-api-endpoint-exercises.paw +0 -0
  12. package/debug/model/manual_scripts/MySQL-Laden-Entry.sh +17 -0
  13. package/debug/model/manual_scripts/MySQL-Security.sql +5 -0
  14. package/debug/model/manual_scripts/my.cnf +4 -0
  15. package/debug/model/sql_create/BookStore-CreateAndPopulateTables.sql +194 -0
  16. package/debug/package-lock.json +3999 -0
  17. package/debug/package.json +13 -0
  18. package/package.json +47 -17
  19. package/source/Retold-Data-Service.js +94 -299
  20. package/test/RetoldDataService_tests.js +16 -36
  21. package/test/model/fable-configuration.json +16 -0
  22. package/test/model/meadow/README.md +1 -0
  23. package/debug/Build-Database.sh +0 -12
  24. package/debug/Harness-Configuration.json +0 -51
  25. package/debug/model/doc/Dictionary.md +0 -18
  26. package/debug/model/doc/Model-Author.md +0 -20
  27. package/debug/model/doc/Model-Book.md +0 -26
  28. package/debug/model/doc/Model-BookAuthorJoin.md +0 -14
  29. package/debug/model/doc/Model-BookPrice.md +0 -25
  30. package/debug/model/doc/Model-Review.md +0 -22
  31. package/debug/model/doc/ModelChangeTracking.md +0 -17
  32. package/debug/model/doc/diagrams/Relationships.dot +0 -13
  33. package/debug/model/doc/diagrams/Relationships.png +0 -0
  34. package/debug/model/doc/diagrams/RelationshipsFull.dot +0 -13
  35. package/debug/model/doc/diagrams/RelationshipsFull.png +0 -0
  36. package/debug/model/mysql_create/MeadowModel-CreateMySQLDatabase.mysql.sql +0 -116
  37. package/source/Cumulation-Settings-Default.js +0 -19
  38. package/source/Cumulation.js +0 -90
  39. package/source/GraphGet.js +0 -607
  40. package/source/ProviderHelpers/Meadow-Provider-Helper-ALASQL.js +0 -48
  41. package/source/ProviderHelpers/Meadow-Provider-Helper-Base.js +0 -46
  42. package/source/ProviderHelpers/Meadow-Provider-Helper-MySQL.js +0 -62
  43. package/test/basic_test_configurations/fable-config-load_model.json +0 -45
  44. package/test/model/meadow_model/BookStore-PICT.json +0 -1
  45. package/test/model/meadow_model/README.md +0 -1
  46. /package/debug/model/{MeadowModel-Extended.json → Model-Extended.json} +0 -0
  47. /package/debug/model/{MeadowModel-PICT.json → Model-PICT.json} +0 -0
  48. /package/debug/model/{MeadowModel.json → Model.json} +0 -0
  49. /package/debug/{Model.ddl → model/ddl/BookStore.ddl} +0 -0
  50. /package/{test → debug}/model/generated_diagram/README.md +0 -0
  51. /package/{test → debug}/model/generated_diagram/Stricture_Output.dot +0 -0
  52. /package/{test → debug}/model/generated_diagram/Stricture_Output.png +0 -0
  53. /package/{test → debug}/model/generated_documentation/Dictionary.md +0 -0
  54. /package/{test → debug}/model/generated_documentation/Model-Author.md +0 -0
  55. /package/{test → debug}/model/generated_documentation/Model-Book.md +0 -0
  56. /package/{test → debug}/model/generated_documentation/Model-BookAuthorJoin.md +0 -0
  57. /package/{test → debug}/model/generated_documentation/Model-BookPrice.md +0 -0
  58. /package/{test → debug}/model/generated_documentation/Model-Review.md +0 -0
  59. /package/{test → debug}/model/generated_documentation/ModelChangeTracking.md +0 -0
  60. /package/{test → debug}/model/generated_documentation/README.md +0 -0
  61. /package/{test → debug}/model/manual_scripts/DropTables.sql +0 -0
  62. /package/{test → debug}/model/manual_scripts/README.md +0 -0
  63. /package/debug/model/meadow/{MeadowSchemaAuthor.json → Model-MeadowSchema-Author.json} +0 -0
  64. /package/debug/model/meadow/{MeadowSchemaBook.json → Model-MeadowSchema-Book.json} +0 -0
  65. /package/debug/model/meadow/{MeadowSchemaBookAuthorJoin.json → Model-MeadowSchema-BookAuthorJoin.json} +0 -0
  66. /package/debug/model/meadow/{MeadowSchemaBookPrice.json → Model-MeadowSchema-BookPrice.json} +0 -0
  67. /package/debug/model/meadow/{MeadowSchemaReview.json → Model-MeadowSchema-Review.json} +0 -0
  68. /package/{test/model/meadow_schema → debug/model/meadow}/README.md +0 -0
  69. /package/{test → debug}/model/sql_create/BookStore-CreateDatabase.mysql.sql +0 -0
  70. /package/{test → debug}/model/sql_create/README.md +0 -0
  71. /package/test/model/{meadow_model/BookStore-Extended.json → Model-Extended.json} +0 -0
  72. /package/test/model/{meadow_model/BookStore.json → Model.json} +0 -0
  73. /package/test/model/{meadow_schema/BookStore-MeadowSchema-Author.json → meadow/Model-MeadowSchema-Author.json} +0 -0
  74. /package/test/model/{meadow_schema/BookStore-MeadowSchema-Book.json → meadow/Model-MeadowSchema-Book.json} +0 -0
  75. /package/test/model/{meadow_schema/BookStore-MeadowSchema-BookAuthorJoin.json → meadow/Model-MeadowSchema-BookAuthorJoin.json} +0 -0
  76. /package/test/model/{meadow_schema/BookStore-MeadowSchema-BookPrice.json → meadow/Model-MeadowSchema-BookPrice.json} +0 -0
  77. /package/test/model/{meadow_schema/BookStore-MeadowSchema-Review.json → meadow/Model-MeadowSchema-Review.json} +0 -0
@@ -1,607 +0,0 @@
1
- /**
2
- * @license MIT
3
- * @author <steven@velozo.com>
4
- */
5
-
6
- /**
7
- * Cumulation Graph Read Library
8
- *
9
- * @class GraphGet
10
- */
11
-
12
- var libAsync = require('async');
13
- var libUnderscore = require('underscore');
14
-
15
- class GraphGet
16
- {
17
- constructor(pFable, pModel)
18
- {
19
- // Wire up logging
20
- this.log = pFable.log;
21
-
22
- // Wire up settings
23
- this._Settings = pFable.settings;
24
-
25
- // Get the data model graph
26
- this._DataModel = pModel;
27
-
28
- // Map of joins (Entity->Other Possible Entities)
29
- this._JoinMap = {};
30
-
31
- // The masquerade ball where all the columns who really mean other entities
32
- this._EntityMasquerade = {};
33
-
34
- // Map of incoming connections for Entities
35
- this._EntityIncomingConnectionMap = {};
36
-
37
- // Presolve the graph by flattening all the connections out
38
- this.unfoldJoins();
39
- };
40
-
41
- addCachedJoin(pJoinEntity, pTableName)
42
- {
43
- let tmpJoinedEntity = pJoinEntity.startsWith('ID') ? pJoinEntity.substring(2) : pJoinEntity;
44
- if (!this._JoinMap.hasOwnProperty(tmpJoinedEntity))
45
- {
46
- this._JoinMap[tmpJoinedEntity] = {};
47
- }
48
-
49
- this.addCachedEntityConnection(pTableName, tmpJoinedEntity);
50
-
51
- this._JoinMap[tmpJoinedEntity][pTableName] = true;
52
- };
53
-
54
- addCachedEntityConnection(pConnectedEntity, pIncomingEntity)
55
- {
56
- if (!this._EntityIncomingConnectionMap.hasOwnProperty(pConnectedEntity))
57
- this._EntityIncomingConnectionMap[pConnectedEntity] = {};
58
-
59
- this._EntityIncomingConnectionMap[pConnectedEntity][pIncomingEntity] = true;
60
- }
61
-
62
- unfoldJoins()
63
- {
64
- if (!this._DataModel.hasOwnProperty('Tables'))
65
- {
66
- this.log.warning(`The DataModel object does not have a Tables property so graph lookups won't work.`);
67
- return false;
68
- }
69
- // Enumerate each data set in the data model and create a join lookup
70
- for (let pEntity in this._DataModel.Tables)
71
- {
72
- let tmpTable = this._DataModel.Tables[pEntity];
73
-
74
- for (let i = 0; i < tmpTable.Columns.length; i++)
75
- {
76
- if (tmpTable.Columns[i].Join &&
77
- tmpTable.Columns[i].Column != 'IDCustomer' &&
78
- tmpTable.Columns[i].Column != 'CreatingIDUser' &&
79
- tmpTable.Columns[i].Column != 'UpdatingIDUser' &&
80
- tmpTable.Columns[i].Column != 'DeletingIDUser')
81
- {
82
- this.addCachedJoin(tmpTable.Columns[i].Join, tmpTable.TableName);
83
- }
84
- }
85
- }
86
-
87
- return true;
88
- };
89
-
90
- parseFilterObject(pEntityName, pFilterObject, fCallback)
91
- {
92
- /*
93
- Take in an object with filters, for instance:
94
- {
95
- Name: 'Biggest Sample Ever',
96
- Code: '7a9f-000139',
97
- IDMaterial: 38,
98
- CreatingIDUser: 100
99
- }
100
-
101
- And turn it into an object of filters; there are two types
102
- -> InRecord (the value is a column in the record)
103
- -> Join (the value is a join table between the two entities)
104
-
105
- {
106
- Material: {Type: 'InRecord', Value:38}
107
- }
108
- */
109
- // Parse the filter object for any column that is an ID Type column.
110
- // Eventually should this look for GUIDs?
111
- let tmpProperties = Object.keys(pFilterObject);
112
- // Get the schema for this entity
113
- let tmpEntityTable = this._DataModel.Tables[pEntityName];
114
- // A container for any valid filters that were passed in.
115
- let tmpValidFilters = {};
116
-
117
- // Get the join map for this entity so we can do a set intersection with other join maps
118
- if (this._JoinMap.hasOwnProperty(pEntityName))
119
- {
120
- tmpValidFilters[pEntityName] = (
121
- {
122
- Entity: pEntityName,
123
- Filter: false,
124
- Type: 'IdentityJoin',
125
- Value: false,
126
- PotentialJoins: this._JoinMap[pEntityName]
127
- });
128
- }
129
-
130
- if (this._Settings.DebugLog)
131
- this.log.debug(`[${pEntityName}] Scanning filter object for filterable properties...`);
132
-
133
- tmpProperties.forEach(
134
- (pFilterProperty)=>
135
- {
136
- if (typeof(pFilterObject[pFilterProperty]) === 'string')
137
- {
138
- // If the value is a string, do a potential LIKE expression
139
- let tmpColumnContained = false;
140
- // This isn't a join; check if this is a column contained in the Entity
141
- // --> Abstract this .. maybe? The string check is unique to this iteration.
142
- for (let i = 0; i < tmpEntityTable.Columns.length; i++)
143
- if ((tmpEntityTable.Columns[i].Column === pFilterProperty) && ((tmpEntityTable.Columns[i].DataType === 'String') || (tmpEntityTable.Columns[i].DataType === 'Text')))
144
- tmpColumnContained = true;
145
- // <-- End of Abstraction (repeated in stanza below)
146
- if (tmpColumnContained)
147
- {
148
- if (tmpValidFilters.hasOwnProperty(pFilterProperty))
149
- {
150
- this.log.warning(`[${pEntityName}] > Filter Property is Already Set for ${pFilterProperty} but there also exists a String column in the record.. defaulting to the column.`);
151
- tmpValidFilters[pFilterProperty].Type = 'InRecordString';
152
- }
153
- else
154
- {
155
- tmpValidFilters[pFilterProperty] = (
156
- {
157
- Entity: pEntityName,
158
- Filter: pFilterProperty,
159
- Type: 'InRecordString',
160
- Value: pFilterObject[pFilterProperty],
161
- PotentialJoins: false
162
- });
163
- if (this._Settings.DebugLog)
164
- this.log.debug(`[${pEntityName}] > Filter Property Set to InRecordString for ${pFilterProperty}.`);
165
- }
166
- }
167
- }
168
- else if (pFilterProperty.startsWith('ID') &&
169
- (Number.isInteger(pFilterObject[pFilterProperty]) || Array.isArray(pFilterObject[pFilterProperty])))
170
- {
171
- let tmpEntity = pFilterProperty.substring(2);
172
-
173
- /* TODO: Joins that aren't named what their entity is
174
- for (let i = 0; i < tmpEntityTable.Columns.length; i++)
175
- {
176
- if ((tmpEntityTable.Columns[i].Column === pFilterProperty) && (tmpEntityTable.Columns[i].hasOwnProperty('Join') && tmpEntityTable.Columns[i].Join.length > 0))
177
- {
178
- this.log.debug(`[${pEntityName}] >>> Found hard-mapped join in the graph for: ${tmpEntityTable.Columns[i].Column} ---> ${tmpEntityTable.Columns[i].Join})...`);
179
- tmpEntity = tmpEntityTable.Columns[i].Join.substring(2);
180
- }
181
- }
182
- */
183
-
184
- // This is an ID, so parse it as a possible filter property
185
- if (this._Settings.DebugLog)
186
- this.log.debug(`[${pEntityName}] -> found potential filter criteria on ${pFilterProperty} (to expected Entity ${tmpEntity})...`);
187
-
188
- if (this._JoinMap.hasOwnProperty(tmpEntity))
189
- {
190
- // This does not check for valid values ... that will happen later
191
- tmpValidFilters[pFilterProperty] = (
192
- {
193
- Entity: tmpEntity,
194
- Filter: pFilterProperty,
195
- Type: 'Join',
196
- Value: pFilterObject[pFilterProperty],
197
- PotentialJoins: this._JoinMap[tmpEntity]
198
- });
199
- if (this._Settings.DebugLog)
200
- this.log.debug(`[${pEntityName}] > Filter Property Set to Join for ${pFilterProperty}.`);
201
- }
202
- let tmpColumnContained = false;
203
- // This isn't a join; check if this is a column contained in the Entity
204
- for (let i = 0; i < tmpEntityTable.Columns.length; i++)
205
- {
206
- if (tmpEntityTable.Columns[i].Column === pFilterProperty)
207
- {
208
- tmpColumnContained = true;
209
- }
210
- }
211
- if (tmpColumnContained)
212
- {
213
- if (tmpValidFilters.hasOwnProperty(pFilterProperty))
214
- {
215
- this.log.warning(`[${pEntityName}] > Filter Property is Already Set to Join for ${pFilterProperty} but there also exists a column in the record.. defaulting to the column.`);
216
- tmpValidFilters[pFilterProperty].Type = 'InRecord';
217
- }
218
- else
219
- {
220
- tmpValidFilters[pFilterProperty] = (
221
- {
222
- Entity: tmpEntity,
223
- Filter: pFilterProperty,
224
- Type: 'InRecord',
225
- Value: pFilterObject[pFilterProperty],
226
- PotentialJoins: false
227
- });
228
- if (this._Settings.DebugLog)
229
- this.log.debug(`[${pEntityName}] > Filter Property Set to InRecord for ${pFilterProperty}.`);
230
- }
231
- }
232
- }
233
- });
234
-
235
- return fCallback(null, tmpValidFilters);
236
- };
237
-
238
- get(pEntityName, pFilterObject, pCumulation, fCallback)
239
- {
240
- // Get a set of EntityNames based on the FilterObject
241
- if (this._Settings.DebugLog)
242
- this.log.debug(`[${pEntityName}] Beginning to graph GET a set of records based on some filter criteria`,pFilterObject);
243
- //let tmpGraphGetTime = this.log.getTimeStamp();
244
-
245
- let tmpGraphHints = {};
246
- let tmpGraphIgnores = {};
247
- let tmpFilterExtensions = {};
248
- // Used for extended behavior modification
249
- let tmpExtendedProperties = {};
250
-
251
- if (pFilterObject.hasOwnProperty('IGNORES'))
252
- {
253
- tmpGraphIgnores = pFilterObject.IGNORES;
254
- delete pFilterObject.IGNORES;
255
- }
256
-
257
- if (pFilterObject.hasOwnProperty('HINTS'))
258
- {
259
- tmpGraphHints = pFilterObject.HINTS;
260
- delete pFilterObject.HINTS;
261
- }
262
-
263
- if (pFilterObject.hasOwnProperty('FILTERS'))
264
- {
265
- tmpFilterExtensions = pFilterObject.FILTERS;
266
- delete pFilterObject.FILTERS;
267
- }
268
-
269
- if (pFilterObject.hasOwnProperty('PROPERTIES'))
270
- {
271
- tmpExtendedProperties = pFilterObject.PROPERTIES;
272
- delete pFilterObject.PROPERTIES;
273
- }
274
-
275
- let tmpPagingString = '0/2000'
276
-
277
- if (pFilterObject.hasOwnProperty('PAGING'))
278
- {
279
- tmpPagingString = '';
280
- tmpPagingString += (typeof(pFilterObject.PAGING.Page) !== 'undefined') ? pFilterObject.PAGING.Page : 0;
281
- tmpPagingString += '/';
282
- tmpPagingString += (typeof(pFilterObject.PAGING.PageSize) !== 'undefined') ? pFilterObject.PAGING.PageSize : 2000;
283
- delete pFilterObject.PAGING;
284
- }
285
-
286
- libAsync.waterfall(
287
- [
288
- (fStageComplete)=>
289
- {
290
- // Parse the filter object and get any valid filters
291
- this.parseFilterObject(pEntityName, pFilterObject, fStageComplete);
292
- },
293
- (pValidFilters, fStageComplete)=>
294
- {
295
- // Get the joined tables for this entity
296
- let tmpEntityJoinedTables = false;
297
- // Map of entities and the number of times they are joined to
298
- let tmpJoinedEntityCounts = {};
299
- if (pValidFilters.hasOwnProperty(pEntityName))
300
- {
301
- // If there is a set of joins that join TO this entity, we are going to use them to find the intersection
302
- tmpEntityJoinedTables = Object.keys(pValidFilters[pEntityName].PotentialJoins);
303
- }
304
- // Now check the join filters for intersections with the entity
305
- for (let pFilterProperty in pValidFilters)
306
- {
307
- let tmpFilter = pValidFilters[pFilterProperty];
308
- if (tmpFilter.Type == 'Join')
309
- {
310
- let tmpJoins = Object.keys(tmpFilter.PotentialJoins);
311
- // Now intersect it with the joins
312
- if (tmpEntityJoinedTables)
313
- {
314
- tmpFilter.ValidJoins = libUnderscore.intersection(tmpJoins, tmpEntityJoinedTables);
315
-
316
- tmpFilter.ValidJoins.forEach(
317
- (pJoinedEntity) =>
318
- {
319
- if (!tmpJoinedEntityCounts.hasOwnProperty(pJoinedEntity))
320
- tmpJoinedEntityCounts[pJoinedEntity] = 0;
321
-
322
- tmpJoinedEntityCounts[pJoinedEntity]++;
323
- }
324
- )
325
- }
326
- else
327
- {
328
- tmpFilter.ValidJoins = false;
329
- }
330
- }
331
- }
332
- // Now get the joins that matter for the set stuff later
333
-
334
- // Now look for the joins with the largest intersection point with the set of filters.
335
- // If there are more than one, check to see about confluence with the rest of the filters
336
- let tmpFinalFilters = [];
337
- for (let pFilterProperty in pValidFilters)
338
- {
339
- let tmpFilter = pValidFilters[pFilterProperty];
340
-
341
- if (tmpGraphIgnores[pFilterProperty])
342
- {
343
- this.log.debug(`[${pEntityName}] Ignoring potential filter ${pFilterProperty} because it is in the ignores.`);
344
- }
345
- else
346
- {
347
- if (tmpFilter.Type == 'InRecord')
348
- {
349
- this.log.debug(`[${pEntityName}] Adding ${tmpFilter.Filter} as InRecord.`);
350
- tmpFinalFilters.push(tmpFilter);
351
- }
352
- else if (tmpFilter.Type == 'InRecordString')
353
- {
354
- this.log.debug(`[${pEntityName}] Adding ${tmpFilter.Filter} as InRecordString.`);
355
- tmpFinalFilters.push(tmpFilter);
356
- }
357
- else if ((tmpFilter.Type == 'Join') && (!tmpFilter.ValidJoins || tmpFilter.ValidJoins.length < 1))
358
- {
359
- this.log.debug(`[${pEntityName}] There was an attempt to join to ${tmpFilter.Filter} but no valid joins exist. Ignoring filter.`);
360
- }
361
- else if ((tmpFilter.Type == 'Join') && (tmpFilter.ValidJoins.length == 1))
362
- {
363
- this.log.debug(`[${pEntityName}] Adding ${tmpFilter.Filter} as a Join to ${tmpFilter.ValidJoins[0]}.`);
364
- tmpFilter.SatisfyingJoin = tmpFilter.ValidJoins[0];
365
- tmpFinalFilters.push(tmpFilter);
366
- }
367
- else if ((tmpFilter.Type == 'Join') && (tmpFilter.ValidJoins.length > 1))
368
- {
369
- this.log.debug(`[${pEntityName}] Determining best Join for filter: ${tmpFilter.Filter}`);
370
- // We want to find the join with the most synergy, without going over.
371
- let tmpSatisfyingHintValue = 1000;
372
- let tmpSatisfyingJoinValue = -1;
373
- let tmpSatisfyingJoinColumnCount = -1;
374
- let tmpSatisfyingJoin = false;
375
- for (let i = 0; i < tmpFilter.ValidJoins.length; i++)
376
- { // Check the graph hints to see if they are lower.
377
- let tmpFilterGraphHintValue = 1000;
378
- this.log.debug(`[${pEntityName}] ... testing ${tmpFilter.ValidJoins[i]}`);
379
- if (tmpGraphHints.hasOwnProperty(tmpFilter.Filter))
380
- {
381
- for (let k = 0; k < tmpGraphHints[tmpFilter.Filter].length; k++)
382
- {
383
- if (tmpGraphHints[tmpFilter.Filter][k] == tmpFilter.ValidJoins[i])
384
- tmpFilterGraphHintValue = k;
385
- }
386
- }
387
-
388
- // Bail out early if there is a hinted selection already in the chain
389
- if (tmpFilterGraphHintValue > tmpSatisfyingHintValue)
390
- {
391
- this.log.debug(`[${pEntityName}] ${tmpFilter.ValidJoins[i]} (hint ${tmpSatisfyingHintValue}, entitycount ${tmpSatisfyingJoinValue}, joincount ${tmpSatisfyingJoinColumnCount}) > ${tmpSatisfyingJoin} is being skipped due to hinting.`);
392
- }
393
- else if ((tmpFilterGraphHintValue <= tmpSatisfyingHintValue) ||
394
- //If there are more common connections for this than the others, use it.
395
- (tmpJoinedEntityCounts[tmpFilter.ValidJoins[i]] > tmpSatisfyingJoinValue) ||
396
- // OR Check for the most joined to table. If there is a tie use one with the least columns joined in.
397
- ((tmpJoinedEntityCounts[tmpFilter.ValidJoins[i]] == tmpSatisfyingJoinValue) && (Object.keys(this._EntityIncomingConnectionMap[tmpFilter.ValidJoins[i]]).length > tmpSatisfyingJoinColumnCount)))
398
- {
399
- tmpSatisfyingHintValue = tmpFilterGraphHintValue;
400
- tmpSatisfyingJoinValue = tmpJoinedEntityCounts[tmpFilter.ValidJoins[i]];
401
- // Get the column count for this join
402
- tmpSatisfyingJoinColumnCount = Object.keys(this._EntityIncomingConnectionMap[tmpFilter.ValidJoins[i]]).length;
403
- tmpSatisfyingJoin = tmpFilter.ValidJoins[i];
404
- this.log.debug(`[${pEntityName}] (hint ${tmpSatisfyingHintValue}, entitycount ${tmpSatisfyingJoinValue}, joincount ${tmpSatisfyingJoinColumnCount}) > ${tmpSatisfyingJoin} satisfies the criteria best to be used (so far)`);
405
- }
406
- }
407
- this.log.debug(`[${pEntityName}] Adding ${tmpFilter.Filter} as a Join to ${tmpSatisfyingJoin}.`);
408
- tmpFilter.SatisfyingJoin = tmpSatisfyingJoin;
409
- tmpFinalFilters.push(tmpFilter);
410
- }
411
- }
412
- }
413
-
414
- fStageComplete(null, pValidFilters, tmpFinalFilters);
415
- },
416
- (pValidFilters, pFinalFilters, fStageComplete)=>
417
- {
418
- // Get the joined records
419
- let tmpJoinedDataSets = {};
420
- libAsync.eachSeries(pFinalFilters,
421
- (pFilter, fCallback)=>
422
- {
423
- if (pFilter.Type != 'Join')
424
- return fCallback(null);
425
-
426
- // If we've already gotten this set don't worry about it.
427
- if (tmpJoinedDataSets.hasOwnProperty(pFilter.SatisfyingJoin))
428
- return fCallback(null);
429
- let tmpURIFilter = 'FilteredTo/';
430
-
431
- // See everything that joins to this entity and cover it
432
- for (let i = 0; i < pFinalFilters.length; i++)
433
- {
434
- let tmpCheckFilter = pFinalFilters[i];
435
- if (tmpCheckFilter.SatisfyingJoin == pFilter.SatisfyingJoin)
436
- {
437
- if (tmpURIFilter != 'FilteredTo/')
438
- tmpURIFilter += '~';
439
-
440
- if (Array.isArray(tmpCheckFilter.Value))
441
- tmpURIFilter += `FBL~${tmpCheckFilter.Filter}~INN~${tmpCheckFilter.Value}`;
442
- else
443
- tmpURIFilter += `FBV~${tmpCheckFilter.Filter}~EQ~${tmpCheckFilter.Value}`;
444
- }
445
- }
446
-
447
- // Filter joins with forced filters
448
- if (tmpFilterExtensions.hasOwnProperty(pFilter.SatisfyingJoin))
449
- {
450
- if (tmpURIFilter != 'FilteredTo/')
451
- tmpURIFilter += '~';
452
-
453
- tmpURIFilter += tmpFilterExtensions[pFilter.SatisfyingJoin];
454
- }
455
-
456
- // TODO: This is sick. Fix it.
457
- tmpURIFilter += `/0/10000`;
458
- pCumulation.fetchRecords(pFilter.SatisfyingJoin, tmpURIFilter,
459
- (pError, pData)=>
460
- {
461
- tmpJoinedDataSets[pFilter.Entity] = pData;
462
- return fCallback(pError);
463
- });
464
- },
465
- (pError)=>
466
- {
467
- return fStageComplete(pError, pValidFilters, pFinalFilters, tmpJoinedDataSets);
468
- });
469
- },
470
- (pValidFilters, pFinalFilters, pJoinedDataSets, fStageComplete)=>
471
- {
472
- // Check if there are joins in the filter; otherwise skip this step.
473
- let tmpJoinsInFilter = false;
474
- for (let i = 0; i < pFinalFilters.length; i++)
475
- {
476
- if (pFinalFilters[i].Type == 'Join')
477
- tmpJoinsInFilter = true;
478
- }
479
- if (!tmpJoinsInFilter)
480
- {
481
- this.log.debug(`[${pEntityName}] Skipping looking for Join identities because there were no valid Joins in the filter.`);
482
- return fStageComplete(null, pValidFilters, pFinalFilters, pJoinedDataSets, []);
483
- }
484
-
485
- let tmpRecordIdentityColumn = 'UNKNOWN';
486
- let tmpEntityTable = this._DataModel.Tables[pEntityName];
487
- for (let i = 0; i < tmpEntityTable.Columns.length; i++)
488
- {
489
- if (tmpEntityTable.Columns[i].DataType == 'ID')
490
- tmpRecordIdentityColumn = tmpEntityTable.Columns[i].Column;
491
- }
492
- let tmpValidIdentities = false;
493
- // Now create a map of all the valid IDs for this record
494
- for (let pJoinedData in pJoinedDataSets)
495
- {
496
- let tmpJoinedIdentities = libUnderscore.uniq(libUnderscore.map(pJoinedDataSets[pJoinedData], (pRecord)=>{ return pRecord[tmpRecordIdentityColumn]; }));
497
- if (tmpValidIdentities === false)
498
- {
499
- tmpValidIdentities = tmpJoinedIdentities;
500
- }
501
- else
502
- {
503
- tmpValidIdentities = libUnderscore.intersection(tmpValidIdentities, tmpJoinedIdentities);
504
- }
505
- }
506
-
507
- if (!tmpValidIdentities || tmpValidIdentities.length < 1)
508
- {
509
- this.log.debug(`[${pEntityName}] There were no valid Joinable records found for the identity column ${tmpRecordIdentityColumn}.`);
510
- }
511
- else
512
- {
513
- this.log.debug(`[${pEntityName}] Found ${tmpValidIdentities.length} valid records for the identity column ${tmpRecordIdentityColumn}.`);
514
- }
515
- return fStageComplete(null, pValidFilters, pFinalFilters, pJoinedDataSets, tmpValidIdentities);
516
- },
517
- (pValidFilters, pFinalFilters, pJoinedDataSets, pValidIdentities, fStageComplete)=>
518
- {
519
- let tmpURIFilter = ``;
520
- let tmpRecordIdentityColumn = 'UNKNOWN';
521
- let tmpEntityTable = this._DataModel.Tables[pEntityName];
522
- for (let i = 0; i < tmpEntityTable.Columns.length; i++)
523
- {
524
- if (tmpEntityTable.Columns[i].DataType == 'ID')
525
- tmpRecordIdentityColumn = tmpEntityTable.Columns[i].Column;
526
- }
527
-
528
- // Check if there are joins in the filter; if so add that as an IN list filter
529
- let tmpJoinsInFilter = false;
530
- for (let i = 0; i < pFinalFilters.length; i++)
531
- {
532
- if (pFinalFilters[i].Type == 'Join')
533
- tmpJoinsInFilter = true;
534
- }
535
- if (tmpJoinsInFilter)
536
- {
537
- let tmpJoinFilterString = pValidIdentities.join();
538
- if (tmpJoinFilterString != '')
539
- tmpURIFilter += `FilteredTo/FBL~${tmpRecordIdentityColumn}~INN~${tmpJoinFilterString}`;
540
- else if (tmpExtendedProperties.ForceJoins)
541
- {
542
- this.log.debug(`[${pEntityName}] Force Joins is set to TRUE and there are no valid Join Records mapped in; set is empty.`);
543
- // There are no filterable list of join filters
544
- return fStageComplete(null, [], pValidFilters, pFinalFilters, pJoinedDataSets, pValidIdentities);
545
- }
546
- }
547
-
548
- pFinalFilters.forEach(
549
- (pFilterProperty)=>
550
- {
551
- if (pFilterProperty.Type == 'InRecord')
552
- {
553
- if (tmpURIFilter != '')
554
- tmpURIFilter += '~';
555
- else
556
- tmpURIFilter += `FilteredTo/`;
557
-
558
- if (Array.isArray(pFilterProperty.Value))
559
- tmpURIFilter += `FBL~${pFilterProperty.Filter}~INN~${pFilterProperty.Value}`;
560
- else
561
- tmpURIFilter += `FBV~${pFilterProperty.Filter}~EQ~${pFilterProperty.Value}`;
562
- }
563
- else if (pFilterProperty.Type == 'InRecordString')
564
- {
565
- if (tmpURIFilter != '')
566
- tmpURIFilter += '~';
567
- else
568
- tmpURIFilter += `FilteredTo/`;
569
- tmpURIFilter += `FBV~${pFilterProperty.Filter}~LK~${pFilterProperty.Value}`;
570
- }
571
- });
572
-
573
- if (tmpFilterExtensions.hasOwnProperty(pEntityName))
574
- {
575
- if (tmpURIFilter != '')
576
- tmpURIFilter += '~';
577
- else
578
- tmpURIFilter += `FilteredTo/`;
579
-
580
- tmpURIFilter += tmpFilterExtensions[pEntityName];
581
- }
582
-
583
-
584
- if (tmpURIFilter !== '')
585
- tmpURIFilter += '/';
586
- tmpURIFilter += tmpPagingString;
587
- pCumulation.fetchRecords(pEntityName, tmpURIFilter,
588
- (pError, pData)=>
589
- {
590
- return fStageComplete(pError, pData, pValidFilters, pFinalFilters, pJoinedDataSets, pValidIdentities);
591
- });
592
- }
593
- ],
594
- (pError, pRecords, pValidFilters, pFinalFilters, pJoinedDataSets, pValidIdentities)=>
595
- {
596
- if (pError)
597
- this.log.error(`[${pEntityName}] Graph Filter operation failed due to error: ${pError}`);
598
-
599
- //this.log.debug(`[${pEntityName}] Graph Filter operation completed in ${this.log.getTimeDelta(tmpGraphGetTime)}ms`);
600
- this.log.debug(`[${pEntityName}] Graph Filter operation completed`);
601
-
602
- fCallback(pError, pRecords, pValidFilters, pFinalFilters, pJoinedDataSets, pValidIdentities);
603
- });
604
- };
605
- };
606
-
607
- module.exports = GraphGet;
@@ -1,48 +0,0 @@
1
- // ##### Part of the **[retold](https://stevenvelozo.github.io/retold/)** system
2
- /**
3
- * @license MIT
4
- * @author <steven@velozo.com>
5
- */
6
- const libALASQL = require('alasql');
7
- const libRetoldProviderHelperBase = require('./Meadow-Provider-Helper-Base');
8
- /**
9
- * Retold MySQL Helper
10
- *
11
- * @class RetoldProviderHelperMySQL
12
- */
13
- class RetoldProviderHelperALASQL extends libRetoldProviderHelperBase
14
- {
15
- constructor(pFable)
16
- {
17
- super(pFable);
18
- }
19
-
20
- // Connect to the server
21
- connect()
22
- {
23
- this._Fable.log.info(`...Initializing the ALASQL in-memory database...`,_Fable.settings.MySQL);
24
- // Mapping in the provider is simple for our in-memory data store!
25
- this._Fable.ALASQL = libALASQL;
26
- }
27
-
28
- // Create database (this deals with its own connections and closes them)
29
- createDatabase()
30
- {
31
-
32
- }
33
-
34
- // Create tables if they don't exist (this deals with its own connections and closes them)
35
- createTables()
36
- {
37
-
38
- }
39
-
40
- // Update tables to match schemas (this deals with its own connections and closes them)
41
- // TODO: This requires some additional features in stricture.
42
- updateTables()
43
- {
44
-
45
- }
46
- }
47
-
48
- module.exports = RetoldProviderHelperALASQL;
@@ -1,46 +0,0 @@
1
- // ##### Part of the **[retold](https://stevenvelozo.github.io/retold/)** system
2
- /**
3
- * @license MIT
4
- * @author <steven@velozo.com>
5
- */
6
- /**
7
- * Retold Base Helper
8
- *
9
- * @class RetoldProviderHelperBase
10
- */
11
- class RetoldProviderHelperBase
12
- {
13
- constructor(pFable)
14
- {
15
- this._Fable = pFable;
16
- }
17
-
18
- // Connect to the server
19
- connect()
20
- {
21
- this._Fable.log.info(`...no connection operation on base Meadow Provider Helper`);
22
-
23
- return true;
24
- }
25
-
26
- // Create database (this deals with its own connections and closes them)
27
- createDatabase()
28
- {
29
- this._Fable.log.info(`...no database creation operation on base Meadow Provider Helper`);
30
- }
31
-
32
- // Create tables if they don't exist (this deals with its own connections and closes them)
33
- createTables()
34
- {
35
- this._Fable.log.info(`...no table creation operation on base Meadow Provider Helper`);
36
- }
37
-
38
- // Update tables to match schemas (this deals with its own connections and closes them)
39
- // TODO: This requires some additional features in stricture.
40
- updateTables()
41
- {
42
- this._Fable.log.info(`...no table update operation on base Meadow Provider Helper`);
43
- }
44
- }
45
-
46
- module.exports = RetoldProviderHelperBase;