@balena/abstract-sql-compiler 10.2.8-build-lodash-08b051cf4150dfa99f3cfafeb3011244760e9d38-1 → 10.2.8

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,3 +1,6 @@
1
+ import _ from 'lodash';
2
+
3
+ import type { Dictionary } from 'lodash';
1
4
  import type {
2
5
  AbstractSqlQuery,
3
6
  AbstractSqlType,
@@ -123,8 +126,6 @@ type OptimisationMatchFn<T extends AnyTypeNodes> =
123
126
  type MetaMatchFn<T extends AnyTypeNodes> = (args: AbstractSqlQuery) => T;
124
127
  type MatchFn<T extends AnyTypeNodes> = (args: AbstractSqlType[]) => T;
125
128
 
126
- const identity = <T>(x: T): T => x;
127
-
128
129
  let helped = false;
129
130
  let noBinds = false;
130
131
  const Helper = <F extends (...args: any[]) => any>(fn: F) => {
@@ -419,7 +420,7 @@ const ConcatenateWithSeparator: MatchFn<ConcatenateWithSeparatorNode> = (
419
420
  ];
420
421
  };
421
422
 
422
- const Text = matchArgs<TextNode>('Text', identity);
423
+ const Text = matchArgs<TextNode>('Text', _.identity);
423
424
 
424
425
  const Value = (arg: string | AbstractSqlQuery): ValuesNodeTypes => {
425
426
  switch (arg) {
@@ -706,20 +707,20 @@ const typeRules = {
706
707
  },
707
708
  Average: matchArgs('Average', NumericValue),
708
709
  Sum: matchArgs('Sum', NumericValue),
709
- Field: matchArgs<FieldNode>('Field', identity),
710
+ Field: matchArgs<FieldNode>('Field', _.identity),
710
711
  ReferencedField: matchArgs<ReferencedFieldNode>(
711
712
  'ReferencedField',
712
- identity,
713
- identity,
713
+ _.identity,
714
+ _.identity,
714
715
  ),
715
- Cast: matchArgs<CastNode>('Cast', AnyValue, identity),
716
+ Cast: matchArgs<CastNode>('Cast', AnyValue, _.identity),
716
717
  // eslint-disable-next-line id-denylist
717
718
  Number: NumberMatch('Number'),
718
719
  Real: NumberMatch('Real'),
719
720
  Integer: NumberMatch('Integer'),
720
721
  // eslint-disable-next-line id-denylist
721
- Boolean: matchArgs<BooleanNode>('Boolean', identity),
722
- EmbeddedText: matchArgs('EmbeddedText', identity),
722
+ Boolean: matchArgs<BooleanNode>('Boolean', _.identity),
723
+ EmbeddedText: matchArgs('EmbeddedText', _.identity),
723
724
  Null: matchArgs<NullNode>('Null'),
724
725
  CurrentTimestamp: matchArgs<CurrentTimestampNode>('CurrentTimestamp'),
725
726
  CurrentDate: matchArgs<CurrentDateNode>('CurrentDate'),
@@ -902,7 +903,7 @@ const typeRules = {
902
903
  return ['TextArray', ...args.map(TextValue)];
903
904
  },
904
905
  ToJSON: matchArgs<ToJSONNode>('ToJSON', AnyValue),
905
- Any: matchArgs<AnyNode>('Any', AnyValue, identity),
906
+ Any: matchArgs<AnyNode>('Any', AnyValue, _.identity),
906
907
  Coalesce: (args): CoalesceNode => {
907
908
  checkMinArgs('Coalesce', args, 2);
908
909
  return [
@@ -955,7 +956,7 @@ const typeRules = {
955
956
  checkMinArgs('And', args, 2);
956
957
  // Collapse nested ANDs.
957
958
  let maybeHelped = false;
958
- const conditions = args.flatMap((arg) => {
959
+ const conditions = _.flatMap(args, (arg) => {
959
960
  if (!isAbstractSqlQuery(arg)) {
960
961
  throw new SyntaxError(
961
962
  `Expected AbstractSqlQuery array but got ${typeof arg}`,
@@ -1058,7 +1059,7 @@ const typeRules = {
1058
1059
  return [
1059
1060
  'NotIn',
1060
1061
  fieldBucket[0][1],
1061
- ...fieldBucket.flatMap((field) => field.slice(2)),
1062
+ ..._.flatMap(fieldBucket, (field) => field.slice(2)),
1062
1063
  ];
1063
1064
  }
1064
1065
  });
@@ -1090,7 +1091,7 @@ const typeRules = {
1090
1091
  checkMinArgs('Or', args, 2);
1091
1092
  // Collapse nested ORs.
1092
1093
  let maybeHelped = false;
1093
- const conditions = args.flatMap((arg) => {
1094
+ const conditions = _.flatMap(args, (arg) => {
1094
1095
  if (!isAbstractSqlQuery(arg)) {
1095
1096
  throw new SyntaxError(
1096
1097
  `Expected AbstractSqlQuery array but got ${typeof arg}`,
@@ -1193,7 +1194,7 @@ const typeRules = {
1193
1194
  return [
1194
1195
  'In',
1195
1196
  fieldBucket[0][1],
1196
- ...fieldBucket.flatMap((field) => field.slice(2)),
1197
+ ..._.flatMap(fieldBucket, (field) => field.slice(2)),
1197
1198
  ];
1198
1199
  }
1199
1200
  });
@@ -1231,21 +1232,24 @@ const typeRules = {
1231
1232
  ),
1232
1233
  Text,
1233
1234
  Value: Text,
1234
- Date: matchArgs('Date', identity),
1235
+ Date: matchArgs('Date', _.identity),
1235
1236
  Duration: (args): DurationNode => {
1236
1237
  checkArgs('Duration', args, 1);
1237
1238
 
1238
- const duration = args[0] as DurationNode[1];
1239
+ let duration = args[0] as DurationNode[1];
1239
1240
  if (duration == null || typeof duration !== 'object') {
1240
1241
  throw new SyntaxError(
1241
1242
  `Duration must be an object, got ${typeof duration}`,
1242
1243
  );
1243
1244
  }
1244
- const { negative, day, hour, minute, second } = duration;
1245
- if (day == null && hour == null && minute == null && second == null) {
1245
+ duration = _(duration)
1246
+ .pick('negative', 'day', 'hour', 'minute', 'second')
1247
+ .omitBy(_.isNil)
1248
+ .value();
1249
+ if (_(duration).omit('negative').isEmpty()) {
1246
1250
  throw new SyntaxError('Invalid duration');
1247
1251
  }
1248
- return ['Duration', { negative, day, hour, minute, second }];
1252
+ return ['Duration', duration];
1249
1253
  },
1250
1254
  Exists: tryMatches<ExistsNode | BooleanNode>(
1251
1255
  Helper<OptimisationMatchFn<BooleanNode>>((args) => {
@@ -1598,7 +1602,7 @@ const typeRules = {
1598
1602
  ],
1599
1603
  ),
1600
1604
  ),
1601
- } satisfies Record<string, MatchFn<AnyTypeNodes>>;
1605
+ } satisfies Dictionary<MatchFn<AnyTypeNodes>>;
1602
1606
 
1603
1607
  export const AbstractSQLOptimiser = (
1604
1608
  abstractSQL: AbstractSqlQuery,
@@ -1,4 +1,8 @@
1
+ import _ from 'lodash';
2
+
1
3
  import sbvrTypes from '@balena/sbvr-types';
4
+
5
+ import type { Dictionary } from 'lodash';
2
6
  import type {
3
7
  AbstractSqlQuery,
4
8
  AbstractSqlType,
@@ -32,7 +36,7 @@ type MetaMatchFn = (args: AbstractSqlQuery, indent: string) => string;
32
36
  type MatchFn = (args: AbstractSqlType[], indent: string) => string;
33
37
 
34
38
  let fieldOrderings: Binding[] = [];
35
- let fieldOrderingsLookup: Record<string, number> = {};
39
+ let fieldOrderingsLookup: Dictionary<number> = {};
36
40
  let engine: Engines = Engines.postgres;
37
41
  let noBinds = false;
38
42
 
@@ -698,7 +702,7 @@ const AddBind = (bind: Binding): string => {
698
702
  }
699
703
  };
700
704
 
701
- const typeRules: Record<string, MatchFn> = {
705
+ const typeRules: Dictionary<MatchFn> = {
702
706
  UnionQuery: (args, indent) => {
703
707
  checkMinArgs('UnionQuery', args, 2);
704
708
  return args
@@ -1336,28 +1340,31 @@ const typeRules: Record<string, MatchFn> = {
1336
1340
  throw new SyntaxError('Durations not supported on: ' + engine);
1337
1341
  }
1338
1342
  // TODO: The abstract sql type should accommodate this
1339
- const duration = args[0] as DurationNode[1];
1343
+ let duration = args[0] as DurationNode[1];
1340
1344
  if (duration == null || typeof duration !== 'object') {
1341
1345
  throw new SyntaxError(
1342
1346
  `Duration must be an object, got ${typeof duration}`,
1343
1347
  );
1344
1348
  }
1345
- const { negative, day, hour, minute, second } = duration;
1346
- if (day == null && hour == null && minute == null && second == null) {
1349
+ duration = _(duration)
1350
+ .pick('negative', 'day', 'hour', 'minute', 'second')
1351
+ .omitBy(_.isNil)
1352
+ .value() as Dictionary<string>;
1353
+ if (_(duration).omit('negative').isEmpty()) {
1347
1354
  throw new SyntaxError('Invalid duration');
1348
1355
  }
1349
1356
  return (
1350
1357
  "INTERVAL '" +
1351
- (negative ? '-' : '') +
1352
- (day ?? '0') +
1358
+ (duration.negative ? '-' : '') +
1359
+ (duration.day ?? '0') +
1353
1360
  ' ' +
1354
- (negative ? '-' : '') +
1355
- (hour ?? '0') +
1361
+ (duration.negative ? '-' : '') +
1362
+ (duration.hour ?? '0') +
1356
1363
  ':' +
1357
- (minute ?? '0') +
1364
+ (duration.minute ?? '0') +
1358
1365
  ':' +
1359
1366
  // Force seconds to be at least 0.0 - required for mysql
1360
- Number(second ?? 0).toLocaleString('en', {
1367
+ Number(duration.second ?? 0).toLocaleString('en', {
1361
1368
  minimumFractionDigits: 1,
1362
1369
  }) +
1363
1370
  "'" +
@@ -7,6 +7,7 @@ export const enum Engines {
7
7
  import { AbstractSQLOptimiser } from './AbstractSQLOptimiser';
8
8
  export { Binding, SqlResult } from './AbstractSQLRules2SQL';
9
9
  import sbvrTypes from '@balena/sbvr-types';
10
+ import _ from 'lodash';
10
11
  import type {
11
12
  AbstractSqlModel,
12
13
  AbstractSqlQuery,
@@ -79,8 +80,7 @@ export const optimizeSchema = (
79
80
  count === 1 &&
80
81
  (ruleBody[0] === 'NotExists' ||
81
82
  (ruleBody[0] === 'Equals' &&
82
- ruleBody[2][0] === 'Number' &&
83
- ruleBody[2][1] === 0)) &&
83
+ _.isEqual(ruleBody[2], ['Number', 0]))) &&
84
84
  isSelectQueryNode(ruleBody[1])
85
85
  ) {
86
86
  const selectQueryNodes = ruleBody[1].slice(1);
@@ -120,7 +120,8 @@ export const optimizeSchema = (
120
120
  convertReferencedFieldsToFields(whereNode);
121
121
 
122
122
  const tableName = fromNode[1];
123
- const table = Object.values(abstractSqlModel.tables).find(
123
+ const table = _.find(
124
+ abstractSqlModel.tables,
124
125
  (t) => t.name === tableName,
125
126
  );
126
127
  if (table) {
@@ -1,3 +1,4 @@
1
+ import _ from 'lodash';
1
2
  import type {
2
3
  AbstractSqlQuery,
3
4
  AbstractSqlType,
@@ -75,11 +76,7 @@ export const getReferencedFields: EngineInstance['getReferencedFields'] = (
75
76
  ) => {
76
77
  const referencedFields = getRuleReferencedFields(ruleBody);
77
78
 
78
- const result: { [key: string]: string[] } = {};
79
- for (const key of Object.keys(referencedFields)) {
80
- result[key] = [...new Set(referencedFields[key].update)];
81
- }
82
- return result;
79
+ return _.mapValues(referencedFields, ({ update }) => _.uniq(update));
83
80
  };
84
81
 
85
82
  export interface RuleReferencedFields {
@@ -270,8 +267,7 @@ export const getRuleReferencedFields: EngineInstance['getRuleReferencedFields']
270
267
  const referencedFields: RuleReferencedFields = {};
271
268
  if (
272
269
  ruleBody[0] === 'Equals' &&
273
- ruleBody[2][0] === 'Number' &&
274
- ruleBody[2][1] === 0 &&
270
+ _.isEqual(ruleBody[2], ['Number', 0]) &&
275
271
  isSelectQueryNode(ruleBody[1])
276
272
  ) {
277
273
  const select = ruleBody[1].find(isSelectNode)!;
@@ -285,7 +281,7 @@ export const getRuleReferencedFields: EngineInstance['getRuleReferencedFields']
285
281
  for (const method of Object.keys(tableRefs) as Array<
286
282
  keyof typeof tableRefs
287
283
  >) {
288
- tableRefs[method] = [...new Set(tableRefs[method])];
284
+ tableRefs[method] = _.uniq(tableRefs[method]);
289
285
  }
290
286
  }
291
287
 
@@ -325,9 +321,10 @@ const checkQuery = (query: AbstractSqlQuery): ModifiedFields | undefined => {
325
321
  return { table: tableName, action: 'delete' };
326
322
  }
327
323
 
328
- const fields = query
324
+ const fields = _<FieldsNode | AbstractSqlType>(query)
329
325
  .filter((v): v is FieldsNode => v != null && v[0] === 'Fields')
330
- .flatMap((v) => v[1]);
326
+ .flatMap((v) => v[1])
327
+ .value();
331
328
  return { table: tableName, action: 'update', fields };
332
329
  };
333
330
  export const getModifiedFields: EngineInstance['getModifiedFields'] = (