jinaga-server 1.0.0 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +103 -0
- package/dist/authentication/authentication-device.d.ts +3 -1
- package/dist/authentication/authentication-device.js +3 -0
- package/dist/authentication/authentication-device.js.map +1 -1
- package/dist/authentication/authentication-impl.d.ts +3 -2
- package/dist/authentication/authentication-impl.js +3 -0
- package/dist/authentication/authentication-impl.js.map +1 -1
- package/dist/authentication/authentication-session.d.ts +4 -2
- package/dist/authentication/authentication-session.js +7 -2
- package/dist/authentication/authentication-session.js.map +1 -1
- package/dist/authentication.d.ts +5 -4
- package/dist/authentication.js +3 -0
- package/dist/authentication.js.map +1 -1
- package/dist/authorization/authorization-keystore.d.ts +5 -3
- package/dist/authorization/authorization-keystore.js +12 -9
- package/dist/authorization/authorization-keystore.js.map +1 -1
- package/dist/http/feed-cache.d.ts +5 -0
- package/dist/http/feed-cache.js +3 -0
- package/dist/http/feed-cache.js.map +1 -0
- package/dist/http/node-http.js +4 -1
- package/dist/http/node-http.js.map +1 -1
- package/dist/http/router.d.ts +5 -1
- package/dist/http/router.js +157 -24
- package/dist/http/router.js.map +1 -1
- package/dist/jinaga-server.js +6 -4
- package/dist/jinaga-server.js.map +1 -1
- package/dist/memory/memory-feed-cache.d.ts +7 -0
- package/dist/memory/memory-feed-cache.js +17 -0
- package/dist/memory/memory-feed-cache.js.map +1 -0
- package/dist/postgres/postgres-store.d.ts +5 -2
- package/dist/postgres/postgres-store.js +53 -28
- package/dist/postgres/postgres-store.js.map +1 -1
- package/dist/postgres/specification-result-sql.d.ts +11 -4
- package/dist/postgres/specification-result-sql.js +302 -5
- package/dist/postgres/specification-result-sql.js.map +1 -1
- package/dist/postgres/specification-sql.d.ts +14 -3
- package/dist/postgres/specification-sql.js +233 -100
- package/dist/postgres/specification-sql.js.map +1 -1
- package/package.json +2 -2
- package/src/authentication/authentication-device.ts +6 -0
- package/src/authentication/authentication-impl.ts +6 -3
- package/src/authentication/authentication-session.ts +11 -3
- package/src/authentication.ts +18 -5
- package/src/authorization/authorization-keystore.ts +14 -8
- package/src/http/feed-cache.ts +6 -0
- package/src/http/node-http.ts +5 -2
- package/src/http/router.ts +179 -31
- package/src/jinaga-server.ts +11 -9
- package/src/memory/memory-feed-cache.ts +15 -0
- package/src/postgres/postgres-store.ts +59 -31
- package/src/postgres/specification-result-sql.ts +450 -10
- package/src/postgres/specification-sql.ts +335 -115
- package/test/authorization/authorizationSpec.ts +11 -2
- package/test/postgres/postgresSpec.ts +31 -25
- package/test/postgres/postgresSpecificationSpec.ts +40 -68
- package/dist/postgres/query-description-builder.d.ts +0 -13
- package/dist/postgres/query-description-builder.js +0 -104
- package/dist/postgres/query-description-builder.js.map +0 -1
- package/dist/postgres/query-description.d.ts +0 -71
- package/dist/postgres/query-description.js +0 -256
- package/dist/postgres/query-description.js.map +0 -1
- package/src/postgres/query-description-builder.ts +0 -116
- package/src/postgres/query-description.ts +0 -385
|
@@ -1,385 +0,0 @@
|
|
|
1
|
-
import { FactBookmark } from "jinaga";
|
|
2
|
-
|
|
3
|
-
export interface SpecificationLabel {
|
|
4
|
-
name: string;
|
|
5
|
-
type: string;
|
|
6
|
-
index: number;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
export type SpecificationSqlQuery = {
|
|
10
|
-
sql: string;
|
|
11
|
-
parameters: (string | number | number[])[];
|
|
12
|
-
labels: SpecificationLabel[];
|
|
13
|
-
bookmark: string;
|
|
14
|
-
};
|
|
15
|
-
export interface InputDescription {
|
|
16
|
-
label: string;
|
|
17
|
-
factIndex: number;
|
|
18
|
-
factTypeId: number;
|
|
19
|
-
factHash: string;
|
|
20
|
-
factTypeParameter: number;
|
|
21
|
-
factHashParameter: number;
|
|
22
|
-
}
|
|
23
|
-
interface OutputDescription {
|
|
24
|
-
label: string;
|
|
25
|
-
type: string;
|
|
26
|
-
factIndex: number;
|
|
27
|
-
}
|
|
28
|
-
export interface FactDescription {
|
|
29
|
-
type: string;
|
|
30
|
-
factIndex: number;
|
|
31
|
-
}
|
|
32
|
-
interface EdgeDescription {
|
|
33
|
-
edgeIndex: number;
|
|
34
|
-
predecessorFactIndex: number;
|
|
35
|
-
successorFactIndex: number;
|
|
36
|
-
roleParameter: number;
|
|
37
|
-
}
|
|
38
|
-
interface NotExistsConditionDescription {
|
|
39
|
-
edges: EdgeDescription[];
|
|
40
|
-
notExistsConditions: NotExistsConditionDescription[];
|
|
41
|
-
}
|
|
42
|
-
function notExistsWithEdge(notExistsConditions: NotExistsConditionDescription[], edge: { edgeIndex: number; predecessorFactIndex: number; successorFactIndex: number; roleParameter: number; }, path: number[]): NotExistsConditionDescription[] {
|
|
43
|
-
if (path.length === 1) {
|
|
44
|
-
return notExistsConditions.map((c, i) => i === path[0] ?
|
|
45
|
-
{
|
|
46
|
-
edges: [...c.edges, edge],
|
|
47
|
-
notExistsConditions: c.notExistsConditions
|
|
48
|
-
} :
|
|
49
|
-
c
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
else {
|
|
53
|
-
return notExistsConditions.map((c, i) => i === path[0] ?
|
|
54
|
-
{
|
|
55
|
-
edges: c.edges,
|
|
56
|
-
notExistsConditions: notExistsWithEdge(c.notExistsConditions, edge, path.slice(1))
|
|
57
|
-
} :
|
|
58
|
-
c
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
function notExistsWithCondition(notExistsConditions: NotExistsConditionDescription[], path: number[]): { notExistsConditions: NotExistsConditionDescription[]; path: number[]; } {
|
|
63
|
-
if (path.length === 0) {
|
|
64
|
-
path = [notExistsConditions.length];
|
|
65
|
-
notExistsConditions = [
|
|
66
|
-
...notExistsConditions,
|
|
67
|
-
{
|
|
68
|
-
edges: [],
|
|
69
|
-
notExistsConditions: []
|
|
70
|
-
}
|
|
71
|
-
];
|
|
72
|
-
return { notExistsConditions, path };
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
const { notExistsConditions: newNotExistsConditions, path: newPath } = notExistsWithCondition(notExistsConditions[path[0]].notExistsConditions, path.slice(1));
|
|
76
|
-
notExistsConditions = notExistsConditions.map((c, i) => i === path[0] ?
|
|
77
|
-
{
|
|
78
|
-
edges: c.edges,
|
|
79
|
-
notExistsConditions: newNotExistsConditions
|
|
80
|
-
} :
|
|
81
|
-
c
|
|
82
|
-
);
|
|
83
|
-
path = [path[0], ...newPath];
|
|
84
|
-
return { notExistsConditions, path };
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
function countEdges(notExistsConditions: NotExistsConditionDescription[]): number {
|
|
88
|
-
return notExistsConditions.reduce((count, c) => count + c.edges.length + countEdges(c.notExistsConditions),
|
|
89
|
-
0);
|
|
90
|
-
}
|
|
91
|
-
export class QueryDescription {
|
|
92
|
-
// An unsatisfiable query description will produce no results.
|
|
93
|
-
static unsatisfiable: QueryDescription = new QueryDescription(
|
|
94
|
-
[], [], [], [], [], []
|
|
95
|
-
);
|
|
96
|
-
|
|
97
|
-
constructor(
|
|
98
|
-
private readonly inputs: InputDescription[],
|
|
99
|
-
private readonly parameters: (string | number)[],
|
|
100
|
-
private readonly outputs: OutputDescription[],
|
|
101
|
-
private readonly facts: FactDescription[],
|
|
102
|
-
private readonly edges: EdgeDescription[],
|
|
103
|
-
private readonly notExistsConditions: NotExistsConditionDescription[] = []
|
|
104
|
-
) {}
|
|
105
|
-
|
|
106
|
-
public withParameter(parameter: string | number): { query: QueryDescription; parameterIndex: number; } {
|
|
107
|
-
const parameterIndex = this.parameters.length + 1;
|
|
108
|
-
const query = new QueryDescription(
|
|
109
|
-
this.inputs,
|
|
110
|
-
this.parameters.concat(parameter),
|
|
111
|
-
this.outputs,
|
|
112
|
-
this.facts,
|
|
113
|
-
this.edges,
|
|
114
|
-
this.notExistsConditions
|
|
115
|
-
);
|
|
116
|
-
return { query, parameterIndex };
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
public withInputParameter(label: string): QueryDescription {
|
|
120
|
-
const factTypeParameter = this.parameters.length + 1;
|
|
121
|
-
const factHashParameter = factTypeParameter + 1;
|
|
122
|
-
const input = this.inputs.find(i => i.label === label);
|
|
123
|
-
const inputs = this.inputs.map(input => input.label === label
|
|
124
|
-
? { ...input, factTypeParameter, factHashParameter }
|
|
125
|
-
: input
|
|
126
|
-
);
|
|
127
|
-
return new QueryDescription(
|
|
128
|
-
inputs,
|
|
129
|
-
this.parameters.concat(input.factTypeId, input.factHash),
|
|
130
|
-
this.outputs,
|
|
131
|
-
this.facts,
|
|
132
|
-
this.edges,
|
|
133
|
-
this.notExistsConditions
|
|
134
|
-
);
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
public withFact(type: string): { query: QueryDescription; factIndex: number; } {
|
|
138
|
-
const factIndex = this.facts.length + 1;
|
|
139
|
-
const fact = { factIndex, type };
|
|
140
|
-
const query = new QueryDescription(
|
|
141
|
-
this.inputs,
|
|
142
|
-
this.parameters,
|
|
143
|
-
this.outputs,
|
|
144
|
-
this.facts.concat(fact),
|
|
145
|
-
this.edges,
|
|
146
|
-
this.notExistsConditions
|
|
147
|
-
);
|
|
148
|
-
return { query, factIndex };
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
public withOutput(label: string, type: string, factIndex: number): QueryDescription {
|
|
152
|
-
const output = { label, type, factIndex };
|
|
153
|
-
const query = new QueryDescription(
|
|
154
|
-
this.inputs,
|
|
155
|
-
this.parameters,
|
|
156
|
-
this.outputs.concat(output),
|
|
157
|
-
this.facts,
|
|
158
|
-
this.edges,
|
|
159
|
-
this.notExistsConditions
|
|
160
|
-
);
|
|
161
|
-
return query;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
public withEdge(predecessorFactIndex: number, successorFactIndex: number, roleParameter: number, path: number[]) {
|
|
165
|
-
const edge = {
|
|
166
|
-
edgeIndex: this.edges.length + countEdges(this.notExistsConditions) + 1,
|
|
167
|
-
predecessorFactIndex,
|
|
168
|
-
successorFactIndex,
|
|
169
|
-
roleParameter
|
|
170
|
-
};
|
|
171
|
-
const query = (path.length === 0)
|
|
172
|
-
? new QueryDescription(
|
|
173
|
-
this.inputs,
|
|
174
|
-
this.parameters,
|
|
175
|
-
this.outputs,
|
|
176
|
-
this.facts,
|
|
177
|
-
this.edges.concat(edge),
|
|
178
|
-
this.notExistsConditions
|
|
179
|
-
)
|
|
180
|
-
: new QueryDescription(
|
|
181
|
-
this.inputs,
|
|
182
|
-
this.parameters,
|
|
183
|
-
this.outputs,
|
|
184
|
-
this.facts,
|
|
185
|
-
this.edges,
|
|
186
|
-
notExistsWithEdge(this.notExistsConditions, edge, path)
|
|
187
|
-
);
|
|
188
|
-
return query;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
public withNotExistsCondition(path: number[]): { query: QueryDescription; path: number[]; } {
|
|
192
|
-
const { notExistsConditions: newNotExistsConditions, path: newPath } = notExistsWithCondition(this.notExistsConditions, path);
|
|
193
|
-
const query = new QueryDescription(
|
|
194
|
-
this.inputs,
|
|
195
|
-
this.parameters,
|
|
196
|
-
this.outputs,
|
|
197
|
-
this.facts,
|
|
198
|
-
this.edges,
|
|
199
|
-
newNotExistsConditions
|
|
200
|
-
);
|
|
201
|
-
return { query, path: newPath };
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
isSatisfiable() {
|
|
205
|
-
return this.inputs.length > 0;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
hasOutput(label: string) {
|
|
209
|
-
return this.outputs.some(o => o.label === label);
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
inputByLabel(label: string): InputDescription | undefined {
|
|
213
|
-
return this.inputs.find(i => i.label === label);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
outputLength(): number {
|
|
217
|
-
return this.outputs.length;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
generateSqlQuery(bookmarks: FactBookmark[], limit: number): SpecificationSqlQuery {
|
|
221
|
-
const hashes = this.outputs
|
|
222
|
-
.map(output => `f${output.factIndex}.hash as hash${output.factIndex}`)
|
|
223
|
-
.join(", ");
|
|
224
|
-
const factIds = this.outputs
|
|
225
|
-
.map(output => `f${output.factIndex}.fact_id`)
|
|
226
|
-
.join(", ");
|
|
227
|
-
const firstEdge = this.edges[0];
|
|
228
|
-
const predecessorFact = this.inputs.find(i => i.factIndex === firstEdge.predecessorFactIndex);
|
|
229
|
-
const successorFact = this.inputs.find(i => i.factIndex === firstEdge.successorFactIndex);
|
|
230
|
-
const firstFactIndex = predecessorFact ? predecessorFact.factIndex : successorFact.factIndex;
|
|
231
|
-
const writtenFactIndexes = new Set<number>().add(firstFactIndex);
|
|
232
|
-
const joins: string[] = generateJoins(this.edges, writtenFactIndexes);
|
|
233
|
-
const inputWhereClauses = this.inputs
|
|
234
|
-
.filter(input => input.factTypeParameter !== 0)
|
|
235
|
-
.map(input => `f${input.factIndex}.fact_type_id = $${input.factTypeParameter} AND f${input.factIndex}.hash = $${input.factHashParameter}`)
|
|
236
|
-
.join(" AND ");
|
|
237
|
-
const notExistsWhereClauses = this.notExistsConditions
|
|
238
|
-
.map(notExistsWhereClause => ` AND NOT EXISTS (${generateNotExistsWhereClause(notExistsWhereClause, writtenFactIndexes)})`)
|
|
239
|
-
.join("");
|
|
240
|
-
const bookmarkParameter = this.parameters.length + 1;
|
|
241
|
-
const limitParameter = bookmarkParameter + 1;
|
|
242
|
-
const bookmark = bookmarks.find(bookmark =>
|
|
243
|
-
bookmark.labels.length === this.outputs.length &&
|
|
244
|
-
bookmark.labels.every((label, index) => label === this.outputs[index].label)
|
|
245
|
-
);
|
|
246
|
-
const sql = `SELECT ${hashes}, sort(array[${factIds}], 'desc') as bookmark FROM public.fact f${firstFactIndex}${joins.join("")} WHERE ${inputWhereClauses}${notExistsWhereClauses} AND sort(array[${factIds}], 'desc') > $${bookmarkParameter} ORDER BY bookmark ASC LIMIT $${limitParameter}`;
|
|
247
|
-
const bookmarkValue: number[] = parseBookmark(bookmark);
|
|
248
|
-
return {
|
|
249
|
-
sql,
|
|
250
|
-
parameters: [...this.parameters, bookmarkValue, limit],
|
|
251
|
-
labels: this.outputs.map(output => ({
|
|
252
|
-
name: output.label,
|
|
253
|
-
type: output.type,
|
|
254
|
-
index: output.factIndex
|
|
255
|
-
})),
|
|
256
|
-
bookmark: "[]"
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
generateResultSqlQuery(): SpecificationSqlQuery {
|
|
261
|
-
const columns = this.outputs
|
|
262
|
-
.map(output => `f${output.factIndex}.hash as hash${output.factIndex}, f${output.factIndex}.fact_id as id${output.factIndex}, f${output.factIndex}.data as data${output.factIndex}`)
|
|
263
|
-
.join(", ");
|
|
264
|
-
const firstEdge = this.edges[0];
|
|
265
|
-
const predecessorFact = this.inputs.find(i => i.factIndex === firstEdge.predecessorFactIndex);
|
|
266
|
-
const successorFact = this.inputs.find(i => i.factIndex === firstEdge.successorFactIndex);
|
|
267
|
-
const firstFactIndex = predecessorFact ? predecessorFact.factIndex : successorFact.factIndex;
|
|
268
|
-
const writtenFactIndexes = new Set<number>().add(firstFactIndex);
|
|
269
|
-
const joins: string[] = generateJoins(this.edges, writtenFactIndexes);
|
|
270
|
-
const inputWhereClauses = this.inputs
|
|
271
|
-
.filter(input => input.factTypeParameter !== 0)
|
|
272
|
-
.map(input => `f${input.factIndex}.fact_type_id = $${input.factTypeParameter} AND f${input.factIndex}.hash = $${input.factHashParameter}`)
|
|
273
|
-
.join(" AND ");
|
|
274
|
-
const notExistsWhereClauses = this.notExistsConditions
|
|
275
|
-
.map(notExistsWhereClause => ` AND NOT EXISTS (${generateNotExistsWhereClause(notExistsWhereClause, writtenFactIndexes)})`)
|
|
276
|
-
.join("");
|
|
277
|
-
const orderByClause = this.outputs
|
|
278
|
-
.map(output => `f${output.factIndex}.fact_id ASC`)
|
|
279
|
-
.join(", ");
|
|
280
|
-
const sql = `SELECT ${columns} FROM public.fact f${firstFactIndex}${joins.join("")} WHERE ${inputWhereClauses}${notExistsWhereClauses} ORDER BY ${orderByClause}`;
|
|
281
|
-
return {
|
|
282
|
-
sql,
|
|
283
|
-
parameters: this.parameters,
|
|
284
|
-
labels: this.outputs.map(output => ({
|
|
285
|
-
name: output.label,
|
|
286
|
-
type: output.type,
|
|
287
|
-
index: output.factIndex
|
|
288
|
-
})),
|
|
289
|
-
bookmark: "[]"
|
|
290
|
-
};
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
function generateJoins(edges: EdgeDescription[], writtenFactIndexes: Set<number>) {
|
|
295
|
-
const joins: string[] = [];
|
|
296
|
-
edges.forEach(edge => {
|
|
297
|
-
if (writtenFactIndexes.has(edge.predecessorFactIndex)) {
|
|
298
|
-
if (writtenFactIndexes.has(edge.successorFactIndex)) {
|
|
299
|
-
joins.push(
|
|
300
|
-
` JOIN public.edge e${edge.edgeIndex}` +
|
|
301
|
-
` ON e${edge.edgeIndex}.predecessor_fact_id = f${edge.predecessorFactIndex}.fact_id` +
|
|
302
|
-
` AND e${edge.edgeIndex}.successor_fact_id = f${edge.successorFactIndex}.fact_id` +
|
|
303
|
-
` AND e${edge.edgeIndex}.role_id = $${edge.roleParameter}`
|
|
304
|
-
);
|
|
305
|
-
}
|
|
306
|
-
else {
|
|
307
|
-
joins.push(
|
|
308
|
-
` JOIN public.edge e${edge.edgeIndex}` +
|
|
309
|
-
` ON e${edge.edgeIndex}.predecessor_fact_id = f${edge.predecessorFactIndex}.fact_id` +
|
|
310
|
-
` AND e${edge.edgeIndex}.role_id = $${edge.roleParameter}`
|
|
311
|
-
);
|
|
312
|
-
joins.push(
|
|
313
|
-
` JOIN public.fact f${edge.successorFactIndex}` +
|
|
314
|
-
` ON f${edge.successorFactIndex}.fact_id = e${edge.edgeIndex}.successor_fact_id`
|
|
315
|
-
);
|
|
316
|
-
writtenFactIndexes.add(edge.successorFactIndex);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
else if (writtenFactIndexes.has(edge.successorFactIndex)) {
|
|
320
|
-
joins.push(
|
|
321
|
-
` JOIN public.edge e${edge.edgeIndex}` +
|
|
322
|
-
` ON e${edge.edgeIndex}.successor_fact_id = f${edge.successorFactIndex}.fact_id` +
|
|
323
|
-
` AND e${edge.edgeIndex}.role_id = $${edge.roleParameter}`
|
|
324
|
-
);
|
|
325
|
-
joins.push(
|
|
326
|
-
` JOIN public.fact f${edge.predecessorFactIndex}` +
|
|
327
|
-
` ON f${edge.predecessorFactIndex}.fact_id = e${edge.edgeIndex}.predecessor_fact_id`
|
|
328
|
-
);
|
|
329
|
-
writtenFactIndexes.add(edge.predecessorFactIndex);
|
|
330
|
-
}
|
|
331
|
-
else {
|
|
332
|
-
throw new Error("Neither predecessor nor successor fact has been written");
|
|
333
|
-
}
|
|
334
|
-
});
|
|
335
|
-
return joins;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
function generateNotExistsWhereClause(notExistsWhereClause: NotExistsConditionDescription, outerFactIndexes: Set<number>): string {
|
|
339
|
-
const firstEdge = notExistsWhereClause.edges[0];
|
|
340
|
-
const writtenFactIndexes = new Set<number>(outerFactIndexes);
|
|
341
|
-
const firstJoin: string[] = [];
|
|
342
|
-
const whereClause: string[] = [];
|
|
343
|
-
if (writtenFactIndexes.has(firstEdge.predecessorFactIndex)) {
|
|
344
|
-
if (writtenFactIndexes.has(firstEdge.successorFactIndex)) {
|
|
345
|
-
throw new Error("Not yet implemented");
|
|
346
|
-
}
|
|
347
|
-
else {
|
|
348
|
-
whereClause.push(
|
|
349
|
-
`e${firstEdge.edgeIndex}.predecessor_fact_id = f${firstEdge.predecessorFactIndex}.fact_id` +
|
|
350
|
-
` AND e${firstEdge.edgeIndex}.role_id = $${firstEdge.roleParameter}`
|
|
351
|
-
);
|
|
352
|
-
firstJoin.push(
|
|
353
|
-
` JOIN public.fact f${firstEdge.successorFactIndex}` +
|
|
354
|
-
` ON f${firstEdge.successorFactIndex}.fact_id = e${firstEdge.edgeIndex}.successor_fact_id`
|
|
355
|
-
);
|
|
356
|
-
writtenFactIndexes.add(firstEdge.successorFactIndex);
|
|
357
|
-
}
|
|
358
|
-
}
|
|
359
|
-
else if (writtenFactIndexes.has(firstEdge.successorFactIndex)) {
|
|
360
|
-
whereClause.push(
|
|
361
|
-
`e${firstEdge.edgeIndex}.successor_fact_id = f${firstEdge.successorFactIndex}.fact_id` +
|
|
362
|
-
` AND e${firstEdge.edgeIndex}.role_id = $${firstEdge.roleParameter}`
|
|
363
|
-
);
|
|
364
|
-
firstJoin.push(
|
|
365
|
-
` JOIN public.fact f${firstEdge.predecessorFactIndex}` +
|
|
366
|
-
` ON f${firstEdge.predecessorFactIndex}.fact_id = e${firstEdge.edgeIndex}.predecessor_fact_id`
|
|
367
|
-
);
|
|
368
|
-
writtenFactIndexes.add(firstEdge.predecessorFactIndex);
|
|
369
|
-
}
|
|
370
|
-
else {
|
|
371
|
-
throw new Error("Neither predecessor nor successor fact has been written");
|
|
372
|
-
}
|
|
373
|
-
const tailJoins: string[] = generateJoins(notExistsWhereClause.edges.slice(1), writtenFactIndexes);
|
|
374
|
-
const joins = firstJoin.concat(tailJoins);
|
|
375
|
-
return `SELECT 1 FROM public.edge e${firstEdge.edgeIndex}${joins.join("")} WHERE ${whereClause.join(" AND ")}`;
|
|
376
|
-
}
|
|
377
|
-
|
|
378
|
-
function parseBookmark(bookmark: FactBookmark): number[] {
|
|
379
|
-
if (bookmark === undefined || bookmark === null || bookmark.bookmark === "") {
|
|
380
|
-
return [];
|
|
381
|
-
}
|
|
382
|
-
else {
|
|
383
|
-
return bookmark.bookmark.split(".").map(str => parseInt(str));
|
|
384
|
-
}
|
|
385
|
-
}
|