@comake/skl-js-engine 1.3.7 → 1.3.9

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.
@@ -14,6 +14,7 @@ exports.SparqlQueryBuilder = void 0;
14
14
  /* eslint-disable indent */
15
15
  const data_model_1 = __importDefault(require("@rdfjs/data-model"));
16
16
  const constants_1 = require("../../../constants");
17
+ const PerformanceLogger_1 = require("../../../util/PerformanceLogger");
17
18
  const SparqlUtil_1 = require("../../../util/SparqlUtil");
18
19
  const TripleUtil_1 = require("../../../util/TripleUtil");
19
20
  const Util_1 = require("../../../util/Util");
@@ -25,81 +26,96 @@ class SparqlQueryBuilder {
25
26
  this.variableGenerator = new VariableGenerator_1.VariableGenerator();
26
27
  }
27
28
  buildEntitySelectPatternsFromOptions(subject, options) {
28
- const relations = options?.select ? undefined : options?.relations;
29
- const whereQueryData = this.createWhereQueryData(subject, options?.where, true);
30
- const orderQueryData = this.createOrderQueryData(subject, options?.order);
31
- const relationsQueryData = this.createRelationsQueryData(subject, relations);
32
- // Handle subqueries
33
- if (options?.subQueries && options.subQueries.length > 0) {
34
- const subQueryPatterns = this.createSubQueryPatterns(options.subQueries);
35
- whereQueryData.values.unshift(...subQueryPatterns);
36
- }
37
- const patterns = whereQueryData.values;
38
- if (whereQueryData.triples.length === 0 &&
39
- (whereQueryData.filters.length > 0 ||
40
- orderQueryData.triples.length > 0 ||
41
- (whereQueryData.values.length === 0 &&
42
- whereQueryData.graphValues.length === 0 &&
43
- whereQueryData.graphTriples.length === 0))) {
44
- if (relationsQueryData.unionPatterns.length > 0) {
45
- /* relationsQueryData.unionPatterns.push(
46
- createSparqlGraphPattern(subject, [ createSparqlBasicGraphPattern([ entityGraphTriple ]) ])
47
- ); */
29
+ const span = PerformanceLogger_1.PerformanceLogger.startSpan('QueryBuilder.buildSelect', {
30
+ hasWhere: !!options?.where,
31
+ hasRelations: !!options?.relations
32
+ });
33
+ try {
34
+ const relations = options?.select ? undefined : options?.relations;
35
+ const whereQueryData = this.createWhereQueryData(subject, options?.where, true);
36
+ const orderQueryData = this.createOrderQueryData(subject, options?.order);
37
+ const relationsQueryData = this.createRelationsQueryData(subject, relations);
38
+ // Handle subqueries
39
+ if (options?.subQueries && options.subQueries.length > 0) {
40
+ const subQueryPatterns = this.createSubQueryPatterns(options.subQueries);
41
+ whereQueryData.values.unshift(...subQueryPatterns);
48
42
  }
49
- else {
43
+ const patterns = whereQueryData.values;
44
+ if (whereQueryData.triples.length === 0 &&
45
+ (whereQueryData.filters.length > 0 ||
46
+ orderQueryData.triples.length > 0 ||
47
+ (whereQueryData.values.length === 0 &&
48
+ whereQueryData.graphValues.length === 0 &&
49
+ whereQueryData.graphTriples.length === 0))) {
50
+ if (relationsQueryData.unionPatterns.length > 0) {
51
+ /* relationsQueryData.unionPatterns.push(
52
+ createSparqlGraphPattern(subject, [ createSparqlBasicGraphPattern([ entityGraphTriple ]) ])
53
+ ); */
54
+ }
55
+ else {
56
+ const entityGraphFilterPattern = this.createEntityGraphFilterPattern(subject);
57
+ // patterns.push(createSparqlGraphPattern(subject, [ createSparqlBasicGraphPattern([ entityGraphTriple ]) ]));
58
+ patterns.push(entityGraphFilterPattern);
59
+ }
60
+ }
61
+ else if (!options?.where?.id) {
50
62
  const entityGraphFilterPattern = this.createEntityGraphFilterPattern(subject);
51
- // patterns.push(createSparqlGraphPattern(subject, [ createSparqlBasicGraphPattern([ entityGraphTriple ]) ]));
52
- patterns.push(entityGraphFilterPattern);
63
+ const entityIsGraphFilter = (0, SparqlUtil_1.createSparqlExistsOperation)([entityGraphFilterPattern]);
64
+ whereQueryData.filters.push(entityIsGraphFilter);
53
65
  }
54
- }
55
- else if (!options?.where?.id) {
56
- const entityGraphFilterPattern = this.createEntityGraphFilterPattern(subject);
57
- const entityIsGraphFilter = (0, SparqlUtil_1.createSparqlExistsOperation)([entityGraphFilterPattern]);
58
- whereQueryData.filters.push(entityIsGraphFilter);
59
- }
60
- // Add union patterns to the patterns
61
- if (relationsQueryData.unionPatterns.length > 0) {
62
- patterns.push((0, SparqlUtil_1.createSparqlUnion)(relationsQueryData.unionPatterns));
63
- }
64
- const wherePatterns = this.createWherePatternsFromQueryData(patterns, whereQueryData.triples, whereQueryData.filters, orderQueryData.triples, orderQueryData.filters, whereQueryData.patterns ?? [], undefined, whereQueryData.binds);
65
- // For ID-only queries, we need to include union patterns in graphWhere
66
- // because that's what gets used in the CONSTRUCT query
67
- const graphWhereRelationsPatterns = relationsQueryData.unionPatterns.length > 0
68
- ? [(0, SparqlUtil_1.createSparqlUnion)(relationsQueryData.unionPatterns), ...relationsQueryData.patterns]
69
- : relationsQueryData.patterns;
70
- const graphWherePatterns = this.createWherePatternsFromQueryData(whereQueryData.graphValues, whereQueryData.graphTriples, whereQueryData.graphFilters, undefined, undefined, graphWhereRelationsPatterns);
71
- // Create variables for each order expression and update the orders to use them
72
- const selectVariables = orderQueryData.orders.map(order => {
73
- const variable = this.createVariable();
74
- return {
75
- variable,
76
- expression: order.expression
66
+ // Add union patterns to the patterns
67
+ if (relationsQueryData.unionPatterns.length > 0) {
68
+ patterns.push((0, SparqlUtil_1.createSparqlUnion)(relationsQueryData.unionPatterns));
69
+ }
70
+ const wherePatterns = this.createWherePatternsFromQueryData(patterns, whereQueryData.triples, whereQueryData.filters, orderQueryData.triples, orderQueryData.filters, whereQueryData.patterns ?? [], undefined, whereQueryData.binds);
71
+ // For ID-only queries, we need to include union patterns in graphWhere
72
+ // because that's what gets used in the CONSTRUCT query
73
+ const graphWhereRelationsPatterns = relationsQueryData.unionPatterns.length > 0
74
+ ? [(0, SparqlUtil_1.createSparqlUnion)(relationsQueryData.unionPatterns), ...relationsQueryData.patterns]
75
+ : relationsQueryData.patterns;
76
+ const graphWherePatterns = this.createWherePatternsFromQueryData(whereQueryData.graphValues, whereQueryData.graphTriples, whereQueryData.graphFilters, undefined, undefined, graphWhereRelationsPatterns);
77
+ // Create variables for each order expression and update the orders to use them
78
+ const selectVariables = orderQueryData.orders.map(order => {
79
+ const variable = this.createVariable();
80
+ return {
81
+ variable,
82
+ expression: order.expression
83
+ };
84
+ });
85
+ const orders = selectVariables.map((selectVar, index) => ({
86
+ expression: selectVar.variable,
87
+ descending: orderQueryData.orders[index].descending
88
+ }));
89
+ if (orders.length > 0) {
90
+ orders.push({
91
+ expression: SparqlUtil_1.entityVariable
92
+ });
93
+ }
94
+ selectVariables.push(...(whereQueryData.selectVariables ?? []));
95
+ const isRelationsQueryDataEmpty = relationsQueryData.unionPatterns.length === 0 && relationsQueryData.patterns.length === 0 && relationsQueryData.selectionTriples.length === 0;
96
+ const returnData = {
97
+ where: wherePatterns,
98
+ orders,
99
+ ...orderQueryData.groupByParent ? { group: subject } : {},
100
+ graphWhere: graphWherePatterns,
101
+ graphSelectionTriples: relationsQueryData.selectionTriples,
102
+ ...isRelationsQueryDataEmpty ? {} : { relationsQueryData }
77
103
  };
78
- });
79
- const orders = selectVariables.map((selectVar, index) => ({
80
- expression: selectVar.variable,
81
- descending: orderQueryData.orders[index].descending
82
- }));
83
- if (orders.length > 0) {
84
- orders.push({
85
- expression: SparqlUtil_1.entityVariable
104
+ if (selectVariables.length > 0) {
105
+ returnData.selectVariables = selectVariables;
106
+ }
107
+ PerformanceLogger_1.PerformanceLogger.endSpan(span, {
108
+ patternCount: wherePatterns.length,
109
+ tripleCount: whereQueryData.triples.length,
110
+ hasFilters: whereQueryData.filters.length > 0,
111
+ hasOrders: orders.length > 0
86
112
  });
113
+ return returnData;
87
114
  }
88
- selectVariables.push(...(whereQueryData.selectVariables ?? []));
89
- // eslint-disable-next-line max-len
90
- const isRelationsQueryDataEmpty = relationsQueryData.unionPatterns.length === 0 && relationsQueryData.patterns.length === 0 && relationsQueryData.selectionTriples.length === 0;
91
- const returnData = {
92
- where: wherePatterns,
93
- orders,
94
- ...orderQueryData.groupByParent ? { group: subject } : {},
95
- graphWhere: graphWherePatterns,
96
- graphSelectionTriples: relationsQueryData.selectionTriples,
97
- ...isRelationsQueryDataEmpty ? {} : { relationsQueryData }
98
- };
99
- if (selectVariables.length > 0) {
100
- returnData.selectVariables = selectVariables;
115
+ catch (error) {
116
+ PerformanceLogger_1.PerformanceLogger.endSpan(span, { error: true });
117
+ throw error;
101
118
  }
102
- return returnData;
103
119
  }
104
120
  createSubQueryPatterns(subQueries) {
105
121
  return subQueries.map((subQuery) => {
@@ -129,37 +145,46 @@ class SparqlQueryBuilder {
129
145
  return (0, SparqlUtil_1.createSparqlGraphPattern)(subject, [(0, SparqlUtil_1.createSparqlBasicGraphPattern)([entityFilterTriple])]);
130
146
  }
131
147
  buildConstructFromEntitySelectQuery(graphWhere, graphSelectionTriples, select, selectVariables) {
132
- let triples;
133
- let where = [];
134
- if (select) {
135
- triples = this.createSelectPattern(select, SparqlUtil_1.entityVariable);
136
- where = [(0, SparqlUtil_1.createSparqlOptional)([(0, SparqlUtil_1.createSparqlBasicGraphPattern)(triples)]), ...graphWhere];
137
- }
138
- else {
139
- triples = [SparqlUtil_1.entityGraphTriple, ...graphSelectionTriples];
140
- /* Skip if the where contains a union pattern */
141
- if (graphWhere.some(pattern => pattern.type === 'union')) {
142
- where = graphWhere;
148
+ const span = PerformanceLogger_1.PerformanceLogger.startSpan('QueryBuilder.buildConstruct', { hasSelect: !!select });
149
+ try {
150
+ let triples;
151
+ let where = [];
152
+ if (select) {
153
+ triples = this.createSelectPattern(select, SparqlUtil_1.entityVariable);
154
+ where = [(0, SparqlUtil_1.createSparqlOptional)([(0, SparqlUtil_1.createSparqlBasicGraphPattern)(triples)]), ...graphWhere];
143
155
  }
144
156
  else {
145
- where = [
146
- ...graphWhere,
147
- (0, SparqlUtil_1.createSparqlGraphPattern)(SparqlUtil_1.entityVariable, [(0, SparqlUtil_1.createSparqlBasicGraphPattern)([SparqlUtil_1.entityGraphTriple])])
148
- ];
157
+ triples = [SparqlUtil_1.entityGraphTriple, ...graphSelectionTriples];
158
+ /* Skip if the where contains a union pattern */
159
+ if (graphWhere.some(pattern => pattern.type === 'union')) {
160
+ where = graphWhere;
161
+ }
162
+ else {
163
+ where = [
164
+ ...graphWhere,
165
+ (0, SparqlUtil_1.createSparqlGraphPattern)(SparqlUtil_1.entityVariable, [(0, SparqlUtil_1.createSparqlBasicGraphPattern)([SparqlUtil_1.entityGraphTriple])])
166
+ ];
167
+ }
149
168
  }
169
+ // // Add select variables to the query
170
+ // if (selectVariables?.length) {
171
+ // where = [
172
+ // ...where,
173
+ // ...selectVariables.map(({ variable, expression }) => ({
174
+ // type: 'bind' as const,
175
+ // expression,
176
+ // variable,
177
+ // })),
178
+ // ];
179
+ // }
180
+ const result = (0, SparqlUtil_1.createSparqlConstructQuery)(triples, where);
181
+ PerformanceLogger_1.PerformanceLogger.endSpan(span, { tripleCount: triples.length, patternCount: where.length });
182
+ return result;
183
+ }
184
+ catch (error) {
185
+ PerformanceLogger_1.PerformanceLogger.endSpan(span, { error: true });
186
+ throw error;
150
187
  }
151
- // // Add select variables to the query
152
- // if (selectVariables?.length) {
153
- // where = [
154
- // ...where,
155
- // ...selectVariables.map(({ variable, expression }) => ({
156
- // type: 'bind' as const,
157
- // expression,
158
- // variable,
159
- // })),
160
- // ];
161
- // }
162
- return (0, SparqlUtil_1.createSparqlConstructQuery)(triples, where);
163
188
  }
164
189
  createWhereQueryData(subject, where, isTopLevel = false) {
165
190
  if (isTopLevel && Object.keys(where ?? {}).length === 1 && 'id' in where) {
@@ -655,7 +680,8 @@ class SparqlQueryBuilder {
655
680
  }
656
681
  createOrderQueryData(subject, order, isNested = false) {
657
682
  if (!order) {
658
- return { triples: [], orders: [], filters: [] };
683
+ // Default is descending by id
684
+ return { triples: [], orders: [{ expression: subject, descending: true }], filters: [] };
659
685
  }
660
686
  return Object.entries(order).reduce((obj, [property, orderValue]) => {
661
687
  const orderQueryData = this.createOrderQueryDataForProperty(subject, property, orderValue, isNested);
@@ -924,97 +950,112 @@ class SparqlQueryBuilder {
924
950
  };
925
951
  }
926
952
  async buildGroupByQuery(options) {
927
- const entityVariable = data_model_1.default.variable('entity');
928
- const queryData = this.buildEntitySelectPatternsFromOptions(entityVariable, {
929
- where: options.where || {}
953
+ const span = PerformanceLogger_1.PerformanceLogger.startSpan('QueryBuilder.buildGroupBy', {
954
+ hasGroupBy: !!options.groupBy,
955
+ hasDateRange: !!options.dateRange
930
956
  });
931
- // Add group variables and patterns with mapping
932
- const groupVariables = [];
933
- const groupPatterns = [];
934
- const variableMapping = {};
935
- if (options.groupBy) {
936
- options.groupBy.forEach(path => {
937
- const { variable: groupVar, patterns } = this.createGroupPatternForPath(entityVariable, path);
938
- groupVariables.push(groupVar);
939
- variableMapping[groupVar.value] = path;
940
- groupPatterns.push(...patterns);
957
+ try {
958
+ const entityVariable = data_model_1.default.variable('entity');
959
+ const queryData = this.buildEntitySelectPatternsFromOptions(entityVariable, {
960
+ where: options.where || {}
941
961
  });
942
- }
943
- // Add date handling if specified
944
- if (options.dateRange) {
945
- const dateVar = this.createVariable();
946
- variableMapping[dateVar.value] = 'date';
947
- const datePattern = {
948
- type: 'bgp',
949
- triples: [
950
- {
951
- subject: entityVariable,
952
- predicate: data_model_1.default.namedNode(constants_1.EngineConstants.prop.dateCreated),
953
- object: dateVar
954
- }
955
- ]
956
- };
957
- const dateFilter = {
958
- type: 'filter',
959
- expression: {
960
- type: 'operation',
961
- operator: '&&',
962
- args: [
963
- {
964
- type: 'operation',
965
- operator: '>=',
966
- args: [dateVar, data_model_1.default.literal(options.dateRange.start, constants_1.XSD.dateTime)]
967
- },
962
+ // Add group variables and patterns with mapping
963
+ const groupVariables = [];
964
+ const groupPatterns = [];
965
+ const variableMapping = {};
966
+ if (options.groupBy) {
967
+ options.groupBy.forEach(path => {
968
+ const { variable: groupVar, patterns } = this.createGroupPatternForPath(entityVariable, path);
969
+ groupVariables.push(groupVar);
970
+ variableMapping[groupVar.value] = path;
971
+ groupPatterns.push(...patterns);
972
+ });
973
+ }
974
+ // Add date handling if specified
975
+ if (options.dateRange) {
976
+ const dateVar = this.createVariable();
977
+ variableMapping[dateVar.value] = 'date';
978
+ const datePattern = {
979
+ type: 'bgp',
980
+ triples: [
968
981
  {
969
- type: 'operation',
970
- operator: '<=',
971
- args: [dateVar, data_model_1.default.literal(options.dateRange.end, constants_1.XSD.dateTime)]
982
+ subject: entityVariable,
983
+ predicate: data_model_1.default.namedNode(constants_1.EngineConstants.prop.dateCreated),
984
+ object: dateVar
972
985
  }
973
986
  ]
987
+ };
988
+ const dateFilter = {
989
+ type: 'filter',
990
+ expression: {
991
+ type: 'operation',
992
+ operator: '&&',
993
+ args: [
994
+ {
995
+ type: 'operation',
996
+ operator: '>=',
997
+ args: [dateVar, data_model_1.default.literal(options.dateRange.start, constants_1.XSD.dateTime)]
998
+ },
999
+ {
1000
+ type: 'operation',
1001
+ operator: '<=',
1002
+ args: [dateVar, data_model_1.default.literal(options.dateRange.end, constants_1.XSD.dateTime)]
1003
+ }
1004
+ ]
1005
+ }
1006
+ };
1007
+ groupPatterns.push(datePattern, dateFilter);
1008
+ if (options.dateGrouping) {
1009
+ const dateGroupVar = this.createVariable();
1010
+ groupVariables.push(dateGroupVar);
1011
+ variableMapping[dateGroupVar.value] = 'dateGroup';
1012
+ const dateGroupBind = this.createDateGroupingBind(dateVar, dateGroupVar, options.dateGrouping);
1013
+ groupPatterns.push(dateGroupBind);
974
1014
  }
975
- };
976
- groupPatterns.push(datePattern, dateFilter);
977
- if (options.dateGrouping) {
978
- const dateGroupVar = this.createVariable();
979
- groupVariables.push(dateGroupVar);
980
- variableMapping[dateGroupVar.value] = 'dateGroup';
981
- const dateGroupBind = this.createDateGroupingBind(dateVar, dateGroupVar, options.dateGrouping);
982
- groupPatterns.push(dateGroupBind);
983
1015
  }
984
- }
985
- // Create count and entityIds variables
986
- const countVar = this.createVariable();
987
- const entityIdsVar = this.createVariable();
988
- variableMapping[countVar.value] = 'count';
989
- variableMapping[entityIdsVar.value] = 'entityIds';
990
- // Combine all patterns
991
- const combinedWhere = [...queryData.where, ...groupPatterns];
992
- // Create select query with aggregations
993
- const selectQuery = (0, SparqlUtil_1.createSparqlSelectQuery)([
994
- ...groupVariables,
995
- {
996
- expression: {
997
- type: 'aggregate',
998
- aggregation: 'count',
999
- distinct: true,
1000
- expression: entityVariable
1001
- },
1002
- variable: countVar
1003
- },
1004
- {
1005
- expression: {
1006
- type: 'aggregate',
1007
- aggregation: 'group_concat',
1008
- distinct: true,
1009
- separator: ' ',
1010
- expression: entityVariable
1016
+ // Create count and entityIds variables
1017
+ const countVar = this.createVariable();
1018
+ const entityIdsVar = this.createVariable();
1019
+ variableMapping[countVar.value] = 'count';
1020
+ variableMapping[entityIdsVar.value] = 'entityIds';
1021
+ // Combine all patterns
1022
+ const combinedWhere = [...queryData.where, ...groupPatterns];
1023
+ // Create select query with aggregations
1024
+ const selectQuery = (0, SparqlUtil_1.createSparqlSelectQuery)([
1025
+ ...groupVariables,
1026
+ {
1027
+ expression: {
1028
+ type: 'aggregate',
1029
+ aggregation: 'count',
1030
+ distinct: true,
1031
+ expression: entityVariable
1032
+ },
1033
+ variable: countVar
1011
1034
  },
1012
- variable: entityIdsVar
1013
- }
1014
- ], combinedWhere, [], // Orders
1015
- groupVariables.length > 0 ? groupVariables : undefined, // Group by
1016
- options.limit, options.offset);
1017
- return { query: selectQuery, variableMapping };
1035
+ {
1036
+ expression: {
1037
+ type: 'aggregate',
1038
+ aggregation: 'group_concat',
1039
+ distinct: true,
1040
+ separator: ' ',
1041
+ expression: entityVariable
1042
+ },
1043
+ variable: entityIdsVar
1044
+ }
1045
+ ], combinedWhere, [], // Orders
1046
+ groupVariables.length > 0 ? groupVariables : undefined, // Group by
1047
+ options.limit, options.offset);
1048
+ const result = { query: selectQuery, variableMapping };
1049
+ PerformanceLogger_1.PerformanceLogger.endSpan(span, {
1050
+ groupCount: groupVariables.length,
1051
+ hasDateGrouping: !!options.dateGrouping
1052
+ });
1053
+ return result;
1054
+ }
1055
+ catch (error) {
1056
+ PerformanceLogger_1.PerformanceLogger.endSpan(span, { error: true });
1057
+ throw error;
1058
+ }
1018
1059
  }
1019
1060
  // Helper function for date grouping
1020
1061
  createDateGroupingBind(dateVar, dateGroupVar, grouping) {