@memberjunction/core-entities-server 5.47.0 → 5.49.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/dist/custom/MJConversationDetailEntityServer.server.d.ts +20 -1
- package/dist/custom/MJConversationDetailEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJConversationDetailEntityServer.server.js +38 -9
- package/dist/custom/MJConversationDetailEntityServer.server.js.map +1 -1
- package/dist/custom/MJMLTrainingPipelineEntityServer.server.d.ts +62 -0
- package/dist/custom/MJMLTrainingPipelineEntityServer.server.d.ts.map +1 -0
- package/dist/custom/MJMLTrainingPipelineEntityServer.server.js +174 -0
- package/dist/custom/MJMLTrainingPipelineEntityServer.server.js.map +1 -0
- package/dist/custom/MJQueryEntityServer.server.d.ts +35 -0
- package/dist/custom/MJQueryEntityServer.server.d.ts.map +1 -1
- package/dist/custom/MJQueryEntityServer.server.js +69 -1
- package/dist/custom/MJQueryEntityServer.server.js.map +1 -1
- package/dist/custom/MJQuerySQLEntityServer.server.d.ts +32 -0
- package/dist/custom/MJQuerySQLEntityServer.server.d.ts.map +1 -0
- package/dist/custom/MJQuerySQLEntityServer.server.js +93 -0
- package/dist/custom/MJQuerySQLEntityServer.server.js.map +1 -0
- package/dist/custom/query-extraction/parse.d.ts +3 -3
- package/dist/custom/query-extraction/parse.d.ts.map +1 -1
- package/dist/custom/query-extraction/parse.js +4 -5
- package/dist/custom/query-extraction/parse.js.map +1 -1
- package/dist/custom/query-extraction/pipeline.js +2 -2
- package/dist/custom/query-extraction/pipeline.js.map +1 -1
- package/dist/custom/query-extraction/resolve.d.ts.map +1 -1
- package/dist/custom/query-extraction/resolve.js +1 -1
- package/dist/custom/query-extraction/resolve.js.map +1 -1
- package/dist/custom/query-extraction/sync.d.ts +2 -2
- package/dist/custom/query-extraction/sync.d.ts.map +1 -1
- package/dist/custom/query-extraction/sync.js +26 -6
- package/dist/custom/query-extraction/sync.js.map +1 -1
- package/dist/custom/query-extraction/types.d.ts +5 -1
- package/dist/custom/query-extraction/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/package.json +25 -24
|
@@ -5,7 +5,13 @@ import { MJConversationDetailEntity } from "@memberjunction/core-entities";
|
|
|
5
5
|
* when the original message content has been modified.
|
|
6
6
|
*
|
|
7
7
|
* When a user edits their message after initial creation, the OriginalMessageChanged
|
|
8
|
-
* flag is set to true, allowing the UI to display an "(Edited)" indicator.
|
|
8
|
+
* flag is set to true, allowing the UI to display an "(Edited)" indicator. This is
|
|
9
|
+
* also the edit signal for cross-turn conversation compaction
|
|
10
|
+
* (plans/agent-conversation-compaction.md §6): a row edited after it was folded into
|
|
11
|
+
* a persisted summary keeps the flag, Record Changes already holds the diff, and the
|
|
12
|
+
* UI can derive "edited after summarization" from the flag plus the row's Sequence
|
|
13
|
+
* being below the current summary boundary — no summary regeneration required (the
|
|
14
|
+
* summary is explicitly lossy; agents page in exact rows via the retrieval tools).
|
|
9
15
|
*/
|
|
10
16
|
export declare class MJConversationDetailEntityServer extends MJConversationDetailEntity {
|
|
11
17
|
/**
|
|
@@ -13,5 +19,18 @@ export declare class MJConversationDetailEntityServer extends MJConversationDeta
|
|
|
13
19
|
* This is done as pre-processing before calling super.Save() to ensure it's a single DB round trip.
|
|
14
20
|
*/
|
|
15
21
|
Save(options?: EntitySaveOptions): Promise<boolean>;
|
|
22
|
+
/**
|
|
23
|
+
* True when this save is a genuine Message EDIT on an existing record — not one of
|
|
24
|
+
* the framework's own Message rewrites:
|
|
25
|
+
* - New records never qualify (also covers the agent-response placeholder INSERT).
|
|
26
|
+
* - Agent progress updates rewrite Message while the row's Status is 'In-Progress' — skipped.
|
|
27
|
+
* - The run's finalization save rewrites Message together with a Status transition — a
|
|
28
|
+
* dirty Status marks the save as lifecycle, not an edit — skipped.
|
|
29
|
+
*
|
|
30
|
+
* Note: the original implementation inverted the IsSaved check (`!this.IsSaved`
|
|
31
|
+
* selects NEW records), which combined with the OldValue guard meant the flag could
|
|
32
|
+
* never be set — fixed as part of the compaction edit-handling work.
|
|
33
|
+
*/
|
|
34
|
+
ShouldFlagOriginalMessageChanged(): boolean;
|
|
16
35
|
}
|
|
17
36
|
//# sourceMappingURL=MJConversationDetailEntityServer.server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJConversationDetailEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAE3E
|
|
1
|
+
{"version":3,"file":"MJConversationDetailEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAErE,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAE3E;;;;;;;;;;;;GAYG;AACH,qBACa,gCAAiC,SAAQ,0BAA0B;IAC5E;;;OAGG;IACY,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAQlE;;;;;;;;;;;OAWG;IACI,gCAAgC,IAAI,OAAO;CAiBrD"}
|
|
@@ -12,7 +12,13 @@ import { MJConversationDetailEntity } from "@memberjunction/core-entities";
|
|
|
12
12
|
* when the original message content has been modified.
|
|
13
13
|
*
|
|
14
14
|
* When a user edits their message after initial creation, the OriginalMessageChanged
|
|
15
|
-
* flag is set to true, allowing the UI to display an "(Edited)" indicator.
|
|
15
|
+
* flag is set to true, allowing the UI to display an "(Edited)" indicator. This is
|
|
16
|
+
* also the edit signal for cross-turn conversation compaction
|
|
17
|
+
* (plans/agent-conversation-compaction.md §6): a row edited after it was folded into
|
|
18
|
+
* a persisted summary keeps the flag, Record Changes already holds the diff, and the
|
|
19
|
+
* UI can derive "edited after summarization" from the flag plus the row's Sequence
|
|
20
|
+
* being below the current summary boundary — no summary regeneration required (the
|
|
21
|
+
* summary is explicitly lossy; agents page in exact rows via the retrieval tools).
|
|
16
22
|
*/
|
|
17
23
|
let MJConversationDetailEntityServer = class MJConversationDetailEntityServer extends MJConversationDetailEntity {
|
|
18
24
|
/**
|
|
@@ -20,17 +26,40 @@ let MJConversationDetailEntityServer = class MJConversationDetailEntityServer ex
|
|
|
20
26
|
* This is done as pre-processing before calling super.Save() to ensure it's a single DB round trip.
|
|
21
27
|
*/
|
|
22
28
|
async Save(options) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
// Check if the Message field is dirty (has been modified)
|
|
26
|
-
const messageField = this.GetFieldByName('Message');
|
|
27
|
-
if (messageField && messageField.Dirty && messageField.OldValue !== undefined) {
|
|
28
|
-
// Message has been changed on an existing record - set the flag
|
|
29
|
-
this.OriginalMessageChanged = true;
|
|
30
|
-
}
|
|
29
|
+
if (this.ShouldFlagOriginalMessageChanged()) {
|
|
30
|
+
this.OriginalMessageChanged = true;
|
|
31
31
|
}
|
|
32
32
|
return super.Save(options);
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* True when this save is a genuine Message EDIT on an existing record — not one of
|
|
36
|
+
* the framework's own Message rewrites:
|
|
37
|
+
* - New records never qualify (also covers the agent-response placeholder INSERT).
|
|
38
|
+
* - Agent progress updates rewrite Message while the row's Status is 'In-Progress' — skipped.
|
|
39
|
+
* - The run's finalization save rewrites Message together with a Status transition — a
|
|
40
|
+
* dirty Status marks the save as lifecycle, not an edit — skipped.
|
|
41
|
+
*
|
|
42
|
+
* Note: the original implementation inverted the IsSaved check (`!this.IsSaved`
|
|
43
|
+
* selects NEW records), which combined with the OldValue guard meant the flag could
|
|
44
|
+
* never be set — fixed as part of the compaction edit-handling work.
|
|
45
|
+
*/
|
|
46
|
+
ShouldFlagOriginalMessageChanged() {
|
|
47
|
+
if (!this.IsSaved) {
|
|
48
|
+
return false;
|
|
49
|
+
}
|
|
50
|
+
const messageField = this.GetFieldByName('Message');
|
|
51
|
+
if (!messageField || !messageField.Dirty || messageField.OldValue === undefined) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
if (this.Status === 'In-Progress') {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
const statusField = this.GetFieldByName('Status');
|
|
58
|
+
if (statusField?.Dirty) {
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
return true;
|
|
62
|
+
}
|
|
34
63
|
};
|
|
35
64
|
MJConversationDetailEntityServer = __decorate([
|
|
36
65
|
RegisterClass(BaseEntity, "MJ: Conversation Details")
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJConversationDetailEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityServer.server.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAqB,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAE3E
|
|
1
|
+
{"version":3,"file":"MJConversationDetailEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJConversationDetailEntityServer.server.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAqB,MAAM,sBAAsB,CAAC;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAE3E;;;;;;;;;;;;GAYG;AAEI,IAAM,gCAAgC,GAAtC,MAAM,gCAAiC,SAAQ,0BAA0B;IAC5E;;;OAGG;IACM,KAAK,CAAC,IAAI,CAAC,OAA2B;QAC3C,IAAI,IAAI,CAAC,gCAAgC,EAAE,EAAE,CAAC;YAC1C,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC;QACvC,CAAC;QAED,OAAO,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;;;;;;;OAWG;IACI,gCAAgC;QACnC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAChB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;QACpD,IAAI,CAAC,YAAY,IAAI,CAAC,YAAY,CAAC,KAAK,IAAI,YAAY,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC9E,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAChC,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,WAAW,EAAE,KAAK,EAAE,CAAC;YACrB,OAAO,KAAK,CAAC;QACjB,CAAC;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;CACJ,CAAA;AA1CY,gCAAgC;IAD5C,aAAa,CAAC,UAAU,EAAE,0BAA0B,CAAC;GACzC,gCAAgC,CA0C5C"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { ValidationResult } from '@memberjunction/core';
|
|
2
|
+
import { MJMLTrainingPipelineEntity } from '@memberjunction/core-entities';
|
|
3
|
+
/**
|
|
4
|
+
* Server-side ML Training Pipeline entity. Its job is to make the leakage guard
|
|
5
|
+
* impossible to disarm by accident.
|
|
6
|
+
*
|
|
7
|
+
* The guard's `DenyFields` list keeps target-leaking columns out of the feature
|
|
8
|
+
* matrix. Its worst failure mode is silent: a deny entry that matches no column
|
|
9
|
+
* looks exactly like a deny entry that is armed, so training "succeeds" on leaked
|
|
10
|
+
* features and the model looks brilliant. That is precisely what happened when a
|
|
11
|
+
* user pasted a bracketed list into the editor and got
|
|
12
|
+
* `DenyFields: ["[CheckInTime", ..., "Status]"]` — the two most dangerous columns
|
|
13
|
+
* were left completely unguarded, and the save was accepted.
|
|
14
|
+
*
|
|
15
|
+
* So this is the authoritative gate: nothing malformed, and nothing that matches
|
|
16
|
+
* no real column, reaches the database. The rules themselves live in
|
|
17
|
+
* `@memberjunction/predictive-studio-core` so the editor can apply the identical
|
|
18
|
+
* checks at input time without the two ever drifting apart.
|
|
19
|
+
*/
|
|
20
|
+
export declare class MJMLTrainingPipelineEntityServer extends MJMLTrainingPipelineEntity {
|
|
21
|
+
get DefaultSkipAsyncValidation(): boolean;
|
|
22
|
+
ValidateAsync(): Promise<ValidationResult>;
|
|
23
|
+
/**
|
|
24
|
+
* Whether the leakage guard needs re-checking on this save. It does on insert,
|
|
25
|
+
* and whenever the guard or the source bindings it is validated against change.
|
|
26
|
+
*/
|
|
27
|
+
private needsLeakageGuardCheck;
|
|
28
|
+
/**
|
|
29
|
+
* Parse the `LeakageGuard` JSON column. A null/blank guard is legitimate (no
|
|
30
|
+
* deny-list configured) and yields an empty guard rather than an error;
|
|
31
|
+
* malformed JSON is a hard failure, because a guard we cannot read is a guard
|
|
32
|
+
* we cannot enforce.
|
|
33
|
+
*
|
|
34
|
+
* @returns the parsed guard, or `null` when a parse error was recorded on `result`
|
|
35
|
+
*/
|
|
36
|
+
private parseLeakageGuard;
|
|
37
|
+
/**
|
|
38
|
+
* Collect the columns a deny entry could legitimately name, across the target
|
|
39
|
+
* entity and every bound source.
|
|
40
|
+
*
|
|
41
|
+
* `ColumnsFullyResolved` is the important part. Only `Entity` sources expose an
|
|
42
|
+
* enumerable column list; a Query, external entity, vector set, or upstream
|
|
43
|
+
* feature pipeline does not. If any such source is bound we cannot prove a deny
|
|
44
|
+
* entry matches nothing, so the semantic check must stand down — otherwise a
|
|
45
|
+
* perfectly valid entry naming a column on that source would be wrongly rejected.
|
|
46
|
+
* The structural check still runs either way, and that is what catches the
|
|
47
|
+
* pasted-list bug.
|
|
48
|
+
*/
|
|
49
|
+
private buildValidationContext;
|
|
50
|
+
/** Field names of an entity, which are the column names a deny entry may name. */
|
|
51
|
+
private columnsOf;
|
|
52
|
+
/** Parse the `SourceBindings` JSON column, tolerating null/blank/garbage. */
|
|
53
|
+
private parseSourceBindings;
|
|
54
|
+
/** Fold guard issues into the entity's ValidationResult. */
|
|
55
|
+
private applyIssues;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Tree-shaking guard — dynamic ClassFactory instantiation is invisible to the
|
|
59
|
+
* bundler, so this keeps the registration alive.
|
|
60
|
+
*/
|
|
61
|
+
export declare function LoadMJMLTrainingPipelineEntityServer(): void;
|
|
62
|
+
//# sourceMappingURL=MJMLTrainingPipelineEntityServer.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MJMLTrainingPipelineEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJMLTrainingPipelineEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuF,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7I,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAU3E;;;;;;;;;;;;;;;;GAgBG;AACH,qBACa,gCAAiC,SAAQ,0BAA0B;IAE5E,IAAoB,0BAA0B,IAAI,OAAO,CAExD;IAEqB,aAAa,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAkBhE;;;OAGG;IACH,OAAO,CAAC,sBAAsB;IAQ9B;;;;;;;OAOG;IACH,OAAO,CAAC,iBAAiB;IA4BzB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,sBAAsB;IAkC9B,kFAAkF;IAClF,OAAO,CAAC,SAAS;IAIjB,6EAA6E;IAC7E,OAAO,CAAC,mBAAmB;IAe3B,4DAA4D;IAC5D,OAAO,CAAC,WAAW;CAStB;AAED;;;GAGG;AACH,wBAAgB,oCAAoC,IAAI,IAAI,CAE3D"}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
|
2
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
4
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
5
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
6
|
+
};
|
|
7
|
+
import { BaseEntity, ValidationErrorInfo, ValidationErrorType } from '@memberjunction/core';
|
|
8
|
+
import { RegisterClass } from '@memberjunction/global';
|
|
9
|
+
import { MJMLTrainingPipelineEntity } from '@memberjunction/core-entities';
|
|
10
|
+
import { validateLeakageGuard, DOMINANCE_THRESHOLD_DEFAULT, } from '@memberjunction/predictive-studio-core';
|
|
11
|
+
/**
|
|
12
|
+
* Server-side ML Training Pipeline entity. Its job is to make the leakage guard
|
|
13
|
+
* impossible to disarm by accident.
|
|
14
|
+
*
|
|
15
|
+
* The guard's `DenyFields` list keeps target-leaking columns out of the feature
|
|
16
|
+
* matrix. Its worst failure mode is silent: a deny entry that matches no column
|
|
17
|
+
* looks exactly like a deny entry that is armed, so training "succeeds" on leaked
|
|
18
|
+
* features and the model looks brilliant. That is precisely what happened when a
|
|
19
|
+
* user pasted a bracketed list into the editor and got
|
|
20
|
+
* `DenyFields: ["[CheckInTime", ..., "Status]"]` — the two most dangerous columns
|
|
21
|
+
* were left completely unguarded, and the save was accepted.
|
|
22
|
+
*
|
|
23
|
+
* So this is the authoritative gate: nothing malformed, and nothing that matches
|
|
24
|
+
* no real column, reaches the database. The rules themselves live in
|
|
25
|
+
* `@memberjunction/predictive-studio-core` so the editor can apply the identical
|
|
26
|
+
* checks at input time without the two ever drifting apart.
|
|
27
|
+
*/
|
|
28
|
+
let MJMLTrainingPipelineEntityServer = class MJMLTrainingPipelineEntityServer extends MJMLTrainingPipelineEntity {
|
|
29
|
+
get DefaultSkipAsyncValidation() {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
async ValidateAsync() {
|
|
33
|
+
const result = await super.ValidateAsync();
|
|
34
|
+
if (!result.Success)
|
|
35
|
+
return result;
|
|
36
|
+
// Fast-path: the guard can only become newly unsound when the guard itself,
|
|
37
|
+
// or the sources its entries are checked against, are being changed.
|
|
38
|
+
if (!this.needsLeakageGuardCheck())
|
|
39
|
+
return result;
|
|
40
|
+
const guard = this.parseLeakageGuard(result);
|
|
41
|
+
if (guard === null)
|
|
42
|
+
return result; // parse failure already recorded
|
|
43
|
+
const context = this.buildValidationContext();
|
|
44
|
+
const issues = validateLeakageGuard(guard, context);
|
|
45
|
+
this.applyIssues(result, issues);
|
|
46
|
+
return result;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Whether the leakage guard needs re-checking on this save. It does on insert,
|
|
50
|
+
* and whenever the guard or the source bindings it is validated against change.
|
|
51
|
+
*/
|
|
52
|
+
needsLeakageGuardCheck() {
|
|
53
|
+
if (!this.IsSaved)
|
|
54
|
+
return true;
|
|
55
|
+
const guardDirty = this.GetFieldByName('LeakageGuard')?.Dirty ?? false;
|
|
56
|
+
const bindingsDirty = this.GetFieldByName('SourceBindings')?.Dirty ?? false;
|
|
57
|
+
const targetDirty = this.GetFieldByName('TargetEntityID')?.Dirty ?? false;
|
|
58
|
+
return guardDirty || bindingsDirty || targetDirty;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Parse the `LeakageGuard` JSON column. A null/blank guard is legitimate (no
|
|
62
|
+
* deny-list configured) and yields an empty guard rather than an error;
|
|
63
|
+
* malformed JSON is a hard failure, because a guard we cannot read is a guard
|
|
64
|
+
* we cannot enforce.
|
|
65
|
+
*
|
|
66
|
+
* @returns the parsed guard, or `null` when a parse error was recorded on `result`
|
|
67
|
+
*/
|
|
68
|
+
parseLeakageGuard(result) {
|
|
69
|
+
const raw = this.LeakageGuard;
|
|
70
|
+
if (raw == null || raw.trim().length === 0) {
|
|
71
|
+
return { DenyFields: [], SingleFeatureDominanceThreshold: DOMINANCE_THRESHOLD_DEFAULT };
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const parsed = JSON.parse(raw);
|
|
75
|
+
return {
|
|
76
|
+
DenyFields: parsed.DenyFields ?? [],
|
|
77
|
+
DenySources: parsed.DenySources,
|
|
78
|
+
SingleFeatureDominanceThreshold: parsed.SingleFeatureDominanceThreshold ?? DOMINANCE_THRESHOLD_DEFAULT,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
catch (e) {
|
|
82
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
83
|
+
result.Errors.push(new ValidationErrorInfo('LeakageGuard', `LeakageGuard is not valid JSON (${message}). A guard that cannot be read cannot be enforced, ` +
|
|
84
|
+
`so the pipeline would train with no leakage protection at all.`, raw, ValidationErrorType.Failure));
|
|
85
|
+
result.Success = false;
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Collect the columns a deny entry could legitimately name, across the target
|
|
91
|
+
* entity and every bound source.
|
|
92
|
+
*
|
|
93
|
+
* `ColumnsFullyResolved` is the important part. Only `Entity` sources expose an
|
|
94
|
+
* enumerable column list; a Query, external entity, vector set, or upstream
|
|
95
|
+
* feature pipeline does not. If any such source is bound we cannot prove a deny
|
|
96
|
+
* entry matches nothing, so the semantic check must stand down — otherwise a
|
|
97
|
+
* perfectly valid entry naming a column on that source would be wrongly rejected.
|
|
98
|
+
* The structural check still runs either way, and that is what catches the
|
|
99
|
+
* pasted-list bug.
|
|
100
|
+
*/
|
|
101
|
+
buildValidationContext() {
|
|
102
|
+
const bindings = this.parseSourceBindings();
|
|
103
|
+
const provider = this.ProviderToUse;
|
|
104
|
+
const columns = [];
|
|
105
|
+
let fullyResolved = true;
|
|
106
|
+
const targetEntity = this.TargetEntityID ? provider?.EntityByID(this.TargetEntityID) : undefined;
|
|
107
|
+
if (targetEntity) {
|
|
108
|
+
columns.push(...this.columnsOf(targetEntity));
|
|
109
|
+
}
|
|
110
|
+
else if (this.TargetEntityID) {
|
|
111
|
+
fullyResolved = false; // target entity is set but unresolvable
|
|
112
|
+
}
|
|
113
|
+
for (const binding of bindings) {
|
|
114
|
+
if (binding.Kind !== 'Entity') {
|
|
115
|
+
fullyResolved = false; // columns of non-entity sources aren't enumerable here
|
|
116
|
+
continue;
|
|
117
|
+
}
|
|
118
|
+
const entity = provider?.EntityByName(binding.Ref);
|
|
119
|
+
if (!entity) {
|
|
120
|
+
fullyResolved = false;
|
|
121
|
+
continue;
|
|
122
|
+
}
|
|
123
|
+
columns.push(...this.columnsOf(entity));
|
|
124
|
+
}
|
|
125
|
+
return {
|
|
126
|
+
KnownColumns: columns,
|
|
127
|
+
KnownSources: bindings.map((b) => b.Ref),
|
|
128
|
+
ColumnsFullyResolved: fullyResolved,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** Field names of an entity, which are the column names a deny entry may name. */
|
|
132
|
+
columnsOf(entity) {
|
|
133
|
+
return entity.Fields.map((f) => f.Name);
|
|
134
|
+
}
|
|
135
|
+
/** Parse the `SourceBindings` JSON column, tolerating null/blank/garbage. */
|
|
136
|
+
parseSourceBindings() {
|
|
137
|
+
const raw = this.SourceBindings;
|
|
138
|
+
if (raw == null || raw.trim().length === 0)
|
|
139
|
+
return [];
|
|
140
|
+
try {
|
|
141
|
+
const parsed = JSON.parse(raw);
|
|
142
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
143
|
+
}
|
|
144
|
+
catch {
|
|
145
|
+
// A malformed SourceBindings column is not this validator's problem to
|
|
146
|
+
// report, but it does mean we cannot enumerate columns — treat as none,
|
|
147
|
+
// which makes the context not-fully-resolved and stands the semantic
|
|
148
|
+
// check down rather than producing bogus "matches no column" errors.
|
|
149
|
+
return [];
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/** Fold guard issues into the entity's ValidationResult. */
|
|
153
|
+
applyIssues(result, issues) {
|
|
154
|
+
for (const issue of issues) {
|
|
155
|
+
const type = issue.Severity === 'Failure' ? ValidationErrorType.Failure : ValidationErrorType.Warning;
|
|
156
|
+
result.Errors.push(new ValidationErrorInfo('LeakageGuard', issue.Message, issue.Value, type));
|
|
157
|
+
if (issue.Severity === 'Failure') {
|
|
158
|
+
result.Success = false;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
MJMLTrainingPipelineEntityServer = __decorate([
|
|
164
|
+
RegisterClass(BaseEntity, 'MJ: ML Training Pipelines')
|
|
165
|
+
], MJMLTrainingPipelineEntityServer);
|
|
166
|
+
export { MJMLTrainingPipelineEntityServer };
|
|
167
|
+
/**
|
|
168
|
+
* Tree-shaking guard — dynamic ClassFactory instantiation is invisible to the
|
|
169
|
+
* bundler, so this keeps the registration alive.
|
|
170
|
+
*/
|
|
171
|
+
export function LoadMJMLTrainingPipelineEntityServer() {
|
|
172
|
+
// no-op
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=MJMLTrainingPipelineEntityServer.server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MJMLTrainingPipelineEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJMLTrainingPipelineEntityServer.server.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EAAE,UAAU,EAAiC,mBAAmB,EAAE,mBAAmB,EAAoB,MAAM,sBAAsB,CAAC;AAC7I,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,0BAA0B,EAAE,MAAM,+BAA+B,CAAC;AAC3E,OAAO,EACH,oBAAoB,EACpB,2BAA2B,GAK9B,MAAM,wCAAwC,CAAC;AAEhD;;;;;;;;;;;;;;;;GAgBG;AAEI,IAAM,gCAAgC,GAAtC,MAAM,gCAAiC,SAAQ,0BAA0B;IAE5E,IAAoB,0BAA0B;QAC1C,OAAO,KAAK,CAAC;IACjB,CAAC;IAEe,KAAK,CAAC,aAAa;QAC/B,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,aAAa,EAAE,CAAC;QAC3C,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC;QAEnC,4EAA4E;QAC5E,qEAAqE;QACrE,IAAI,CAAC,IAAI,CAAC,sBAAsB,EAAE;YAAE,OAAO,MAAM,CAAC;QAElD,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,MAAM,CAAC,CAAG,iCAAiC;QAEtE,MAAM,OAAO,GAAG,IAAI,CAAC,sBAAsB,EAAE,CAAC;QAC9C,MAAM,MAAM,GAAG,oBAAoB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QACpD,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAEjC,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;OAGG;IACK,sBAAsB;QAC1B,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,KAAK,CAAC;QACvE,MAAM,aAAa,GAAG,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,KAAK,IAAI,KAAK,CAAC;QAC5E,MAAM,WAAW,GAAG,IAAI,CAAC,cAAc,CAAC,gBAAgB,CAAC,EAAE,KAAK,IAAI,KAAK,CAAC;QAC1E,OAAO,UAAU,IAAI,aAAa,IAAI,WAAW,CAAC;IACtD,CAAC;IAED;;;;;;;OAOG;IACK,iBAAiB,CAAC,MAAwB;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC;QAC9B,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzC,OAAO,EAAE,UAAU,EAAE,EAAE,EAAE,+BAA+B,EAAE,2BAA2B,EAAE,CAAC;QAC5F,CAAC;QAED,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA0B,CAAC;YACxD,OAAO;gBACH,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,EAAE;gBACnC,WAAW,EAAE,MAAM,CAAC,WAAW;gBAC/B,+BAA+B,EAC3B,MAAM,CAAC,+BAA+B,IAAI,2BAA2B;aAC5E,CAAC;QACN,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC3D,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,mBAAmB,CACtC,cAAc,EACd,mCAAmC,OAAO,qDAAqD;gBAC/F,gEAAgE,EAChE,GAAG,EACH,mBAAmB,CAAC,OAAO,CAC9B,CAAC,CAAC;YACH,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;YACvB,OAAO,IAAI,CAAC;QAChB,CAAC;IACL,CAAC;IAED;;;;;;;;;;;OAWG;IACK,sBAAsB;QAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,mBAAmB,EAAE,CAAC;QAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,aAA6C,CAAC;QAEpE,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,IAAI,aAAa,GAAG,IAAI,CAAC;QAEzB,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACjG,IAAI,YAAY,EAAE,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC;QAClD,CAAC;aAAM,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YAC7B,aAAa,GAAG,KAAK,CAAC,CAAG,wCAAwC;QACrE,CAAC;QAED,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC7B,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,aAAa,GAAG,KAAK,CAAC,CAAG,uDAAuD;gBAChF,SAAS;YACb,CAAC;YACD,MAAM,MAAM,GAAG,QAAQ,EAAE,YAAY,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;YACnD,IAAI,CAAC,MAAM,EAAE,CAAC;gBACV,aAAa,GAAG,KAAK,CAAC;gBACtB,SAAS;YACb,CAAC;YACD,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;QAC5C,CAAC;QAED,OAAO;YACH,YAAY,EAAE,OAAO;YACrB,YAAY,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;YACxC,oBAAoB,EAAE,aAAa;SACtC,CAAC;IACN,CAAC;IAED,kFAAkF;IAC1E,SAAS,CAAC,MAAkB;QAChC,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC;IAED,6EAA6E;IACrE,mBAAmB;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,cAAc,CAAC;QAChC,IAAI,GAAG,IAAI,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,EAAE,CAAC;QACtD,IAAI,CAAC;YACD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAoB,CAAC;YAClD,OAAO,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/C,CAAC;QAAC,MAAM,CAAC;YACL,uEAAuE;YACvE,wEAAwE;YACxE,qEAAqE;YACrE,qEAAqE;YACrE,OAAO,EAAE,CAAC;QACd,CAAC;IACL,CAAC;IAED,4DAA4D;IACpD,WAAW,CAAC,MAAwB,EAAE,MAA2B;QACrE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YACzB,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,OAAO,CAAC;YACtG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,mBAAmB,CAAC,cAAc,EAAE,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;YAC9F,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC/B,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;YAC3B,CAAC;QACL,CAAC;IACL,CAAC;CACJ,CAAA;AArJY,gCAAgC;IAD5C,aAAa,CAAC,UAAU,EAAE,2BAA2B,CAAC;GAC1C,gCAAgC,CAqJ5C;;AAED;;;GAGG;AACH,MAAM,UAAU,oCAAoC;IAChD,QAAQ;AACZ,CAAC"}
|
|
@@ -22,10 +22,45 @@ export declare class MJQueryEntityServer extends MJQueryEntityExtended {
|
|
|
22
22
|
protected GenerateCompositeEmbedding(): Promise<void>;
|
|
23
23
|
Save(options?: EntitySaveOptions): Promise<boolean>;
|
|
24
24
|
Delete(options?: EntitySaveOptions): Promise<boolean>;
|
|
25
|
+
/**
|
|
26
|
+
* Returns the database platform of the connected database.
|
|
27
|
+
* Uses the DB_PLATFORM env var (same source as MJServer's provider selection).
|
|
28
|
+
*/
|
|
29
|
+
private get CurrentPlatform();
|
|
30
|
+
/**
|
|
31
|
+
* Resolves the SQL to use for extraction based on the current database platform.
|
|
32
|
+
*
|
|
33
|
+
* Resolution order:
|
|
34
|
+
* 1. MJ: Query SQLs record matching the current platform's dialect → use that SQL
|
|
35
|
+
* 2. Base Query.SQL field → fall back if no dialect variant exists
|
|
36
|
+
*
|
|
37
|
+
* After resolution, validates the SQL is compatible with the current platform's
|
|
38
|
+
* dialect by attempting a parse. Logs a warning if the SQL appears to be for a
|
|
39
|
+
* different dialect (e.g., T-SQL bracket identifiers on a PostgreSQL database).
|
|
40
|
+
*/
|
|
41
|
+
private resolveExtractionSQL;
|
|
42
|
+
/**
|
|
43
|
+
* Best-effort dialect validation: attempts to parse the SQL with the current platform's
|
|
44
|
+
* dialect. If parsing throws, logs a warning — the SQL may be for a different dialect.
|
|
45
|
+
*
|
|
46
|
+
* This is a heuristic, not a guarantee: node-sql-parser is permissive on many
|
|
47
|
+
* dialect-specific functions (ISNULL, GETDATE pass in both dialects), so a passing
|
|
48
|
+
* parse does not prove the SQL is correct for this dialect. But a failing parse is a
|
|
49
|
+
* strong signal of incompatibility.
|
|
50
|
+
*/
|
|
51
|
+
private validateDialectCompatibility;
|
|
25
52
|
/**
|
|
26
53
|
* Builds the QuerySyncContext from this entity instance for use by the extraction pipeline.
|
|
54
|
+
* Resolves the SQL to the appropriate dialect variant for the connected database.
|
|
27
55
|
*/
|
|
28
56
|
private buildSyncContext;
|
|
57
|
+
/**
|
|
58
|
+
* Re-runs the extraction pipeline on this query. Called by MJQuerySQLEntityServer
|
|
59
|
+
* when a dialect variant matching the current platform is saved — this handles
|
|
60
|
+
* the timing issue where the parent Query is saved before its QuerySQL children
|
|
61
|
+
* exist in the cache.
|
|
62
|
+
*/
|
|
63
|
+
RerunExtraction(): Promise<void>;
|
|
29
64
|
/**
|
|
30
65
|
* Runs the extraction pipeline and saves the UsesTemplate flag.
|
|
31
66
|
* On error, sets UsesTemplate=false and attempts to save so the query remains usable.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJQueryEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJQueryEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,iBAAiB,EAGjB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"MJQueryEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJQueryEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,iBAAiB,EAGjB,qBAAqB,EAExB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAoB,qBAAqB,EAAmC,MAAM,+BAA+B,CAAC;AAazH;;;;GAIG;AACH,qBACa,mBAAoB,SAAQ,qBAAqB;IAC1D;;;yEAGqE;IAC9D,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAI5C;;OAEG;cACsB,cAAc,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAI5F;;;OAGG;cACa,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5C,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAwCnD,MAAM,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAgBpE;;;OAGG;IACH,OAAO,KAAK,eAAe,GAE1B;IAED;;;;;;;;;;OAUG;IACH,OAAO,CAAC,oBAAoB;IAmB5B;;;;;;;;OAQG;IACH,OAAO,CAAC,4BAA4B;IAgBpC;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;;;;OAKG;IACU,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7C;;;OAGG;YACW,uBAAuB;IAsBrC;;OAEG;YACW,sBAAsB;IAmBpC;;;OAGG;YACW,wBAAwB;IAiCtC;;OAEG;YACW,sBAAsB;IA4BpC;;OAEG;YACW,oBAAoB;IA4BlC;;OAEG;YACW,6BAA6B;CAgB9C"}
|
|
@@ -9,6 +9,9 @@ import { MJQueryEntityExtended, QueryEngine } from "@memberjunction/core-entitie
|
|
|
9
9
|
import { RegisterClass, MJGlobal, UUIDsEqual } from "@memberjunction/global";
|
|
10
10
|
import { EmbedTextLocalHelper } from "./util.js";
|
|
11
11
|
import { RunExtractionPipeline, CleanupQueryData, ConvertTSQLToPostgreSQL, } from "./query-extraction/index.js";
|
|
12
|
+
import { SQLParser } from "@memberjunction/sql-parser";
|
|
13
|
+
import { GetDialect } from "@memberjunction/sql-dialect";
|
|
14
|
+
import { resolveDbPlatformFromEnv } from "@memberjunction/generic-database-provider";
|
|
12
15
|
/**
|
|
13
16
|
* Server-side query entity with embedding generation, SQL extraction pipeline,
|
|
14
17
|
* and dialect auto-conversion. Extends `MJQueryEntityExtended` which provides
|
|
@@ -98,21 +101,86 @@ let MJQueryEntityServer = class MJQueryEntityServer extends MJQueryEntityExtende
|
|
|
98
101
|
}
|
|
99
102
|
}
|
|
100
103
|
// ─── Pipeline Delegation ─────────────────────────────────────────────────────
|
|
104
|
+
/**
|
|
105
|
+
* Returns the database platform of the connected database.
|
|
106
|
+
* Uses the DB_PLATFORM env var (same source as MJServer's provider selection).
|
|
107
|
+
*/
|
|
108
|
+
get CurrentPlatform() {
|
|
109
|
+
return resolveDbPlatformFromEnv() ?? 'sqlserver';
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Resolves the SQL to use for extraction based on the current database platform.
|
|
113
|
+
*
|
|
114
|
+
* Resolution order:
|
|
115
|
+
* 1. MJ: Query SQLs record matching the current platform's dialect → use that SQL
|
|
116
|
+
* 2. Base Query.SQL field → fall back if no dialect variant exists
|
|
117
|
+
*
|
|
118
|
+
* After resolution, validates the SQL is compatible with the current platform's
|
|
119
|
+
* dialect by attempting a parse. Logs a warning if the SQL appears to be for a
|
|
120
|
+
* different dialect (e.g., T-SQL bracket identifiers on a PostgreSQL database).
|
|
121
|
+
*/
|
|
122
|
+
resolveExtractionSQL() {
|
|
123
|
+
const platform = this.CurrentPlatform;
|
|
124
|
+
// 1. Check for a dialect-specific QuerySQL record
|
|
125
|
+
const platformSQL = this.GetPlatformSQL(platform);
|
|
126
|
+
// If GetPlatformSQL returned something different from the base SQL, use it
|
|
127
|
+
const resolvedSQL = platformSQL || this.SQL;
|
|
128
|
+
if (!resolvedSQL || resolvedSQL.trim().length === 0) {
|
|
129
|
+
return '';
|
|
130
|
+
}
|
|
131
|
+
// Validate dialect compatibility
|
|
132
|
+
this.validateDialectCompatibility(resolvedSQL, platform);
|
|
133
|
+
return resolvedSQL;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Best-effort dialect validation: attempts to parse the SQL with the current platform's
|
|
137
|
+
* dialect. If parsing throws, logs a warning — the SQL may be for a different dialect.
|
|
138
|
+
*
|
|
139
|
+
* This is a heuristic, not a guarantee: node-sql-parser is permissive on many
|
|
140
|
+
* dialect-specific functions (ISNULL, GETDATE pass in both dialects), so a passing
|
|
141
|
+
* parse does not prove the SQL is correct for this dialect. But a failing parse is a
|
|
142
|
+
* strong signal of incompatibility.
|
|
143
|
+
*/
|
|
144
|
+
validateDialectCompatibility(sql, platform) {
|
|
145
|
+
try {
|
|
146
|
+
const dialect = GetDialect(platform);
|
|
147
|
+
// Attempt to parse — will throw on strong dialect markers
|
|
148
|
+
// (e.g., [bracket] identifiers fail on PG, :: casts fail on T-SQL)
|
|
149
|
+
SQLParser.ExtractSelectColumns(sql, dialect);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
const otherDialect = platform === 'postgresql' ? 'T-SQL (SQL Server)' : 'PostgreSQL';
|
|
153
|
+
console.warn(`[MJQueryEntityServer] Query "${this.Name}" — SQL may be incompatible with the ` +
|
|
154
|
+
`current database platform "${platform}". The SQL appears to use ${otherDialect} syntax. ` +
|
|
155
|
+
`Consider adding a dialect-specific variant via MJ: Query SQLs.`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
101
158
|
/**
|
|
102
159
|
* Builds the QuerySyncContext from this entity instance for use by the extraction pipeline.
|
|
160
|
+
* Resolves the SQL to the appropriate dialect variant for the connected database.
|
|
103
161
|
*/
|
|
104
162
|
buildSyncContext() {
|
|
105
163
|
return {
|
|
106
164
|
queryID: this.ID,
|
|
107
165
|
queryName: this.Name,
|
|
108
|
-
sql: this.
|
|
166
|
+
sql: this.resolveExtractionSQL(),
|
|
109
167
|
isSaved: this.IsSaved,
|
|
110
168
|
contextUser: this.ContextCurrentUser,
|
|
111
169
|
metadataProvider: this.ProviderToUse,
|
|
112
170
|
runViewProvider: this.RunViewProviderToUse,
|
|
171
|
+
platform: this.CurrentPlatform,
|
|
113
172
|
parameterHints: this.ParameterHints,
|
|
114
173
|
};
|
|
115
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Re-runs the extraction pipeline on this query. Called by MJQuerySQLEntityServer
|
|
177
|
+
* when a dialect variant matching the current platform is saved — this handles
|
|
178
|
+
* the timing issue where the parent Query is saved before its QuerySQL children
|
|
179
|
+
* exist in the cache.
|
|
180
|
+
*/
|
|
181
|
+
async RerunExtraction() {
|
|
182
|
+
await this.extractAndSyncDataAsync();
|
|
183
|
+
}
|
|
116
184
|
/**
|
|
117
185
|
* Runs the extraction pipeline and saves the UsesTemplate flag.
|
|
118
186
|
* On error, sets UsesTemplate=false and attempts to save so the query remains usable.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MJQueryEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJQueryEntityServer.server.ts"],"names":[],"mappings":";;;;;;AAAA,OAAO,EACH,UAAU,EAGV,QAAQ,
|
|
1
|
+
{"version":3,"file":"MJQueryEntityServer.server.js","sourceRoot":"","sources":["../../src/custom/MJQueryEntityServer.server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { EntitySaveOptions } from '@memberjunction/core';
|
|
2
|
+
import { MJQuerySQLEntity } from '@memberjunction/core-entities';
|
|
3
|
+
/**
|
|
4
|
+
* Server-side subclass for MJ: Query SQLs.
|
|
5
|
+
*
|
|
6
|
+
* After a QuerySQL record is saved, if its dialect matches the current database
|
|
7
|
+
* platform, triggers re-extraction on the parent Query. This handles the timing
|
|
8
|
+
* issue where metadata sync creates the parent Query first (extraction runs but
|
|
9
|
+
* the dialect variant doesn't exist yet), then creates QuerySQL child records.
|
|
10
|
+
*
|
|
11
|
+
* The QueryEngine cache uses BaseEngine's `CacheLocal: true`, so by the time
|
|
12
|
+
* Save() returns the `_querySQLs` array already contains the new record —
|
|
13
|
+
* no force refresh needed.
|
|
14
|
+
*/
|
|
15
|
+
export declare class MJQuerySQLEntityServer extends MJQuerySQLEntity {
|
|
16
|
+
Save(options?: EntitySaveOptions): Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Ensures QueryEngine is loaded. In CLI/sync contexts, Config() may not
|
|
19
|
+
* have been called yet. This is a no-op if already loaded (BaseEngine
|
|
20
|
+
* skips reloading when data is already cached and forceRefresh is false).
|
|
21
|
+
*/
|
|
22
|
+
private ensureQueryEngineLoaded;
|
|
23
|
+
private triggerParentExtractionIfDialectMatches;
|
|
24
|
+
/**
|
|
25
|
+
* Checks whether this QuerySQL record's SQLDialectID corresponds to the
|
|
26
|
+
* given database platform by looking up the dialect's PlatformKey in
|
|
27
|
+
* QueryEngine's cached SQLDialects.
|
|
28
|
+
*/
|
|
29
|
+
private isDialectForPlatform;
|
|
30
|
+
private loadParentQuery;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=MJQuerySQLEntityServer.server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MJQuerySQLEntityServer.server.d.ts","sourceRoot":"","sources":["../../src/custom/MJQuerySQLEntityServer.server.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,iBAAiB,EAGpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAe,MAAM,+BAA+B,CAAC;AAK9E;;;;;;;;;;;GAWG;AACH,qBACa,sBAAuB,SAAQ,gBAAgB;IACzC,IAAI,CAAC,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC;IAoBlE;;;;OAIG;YACW,uBAAuB;YAMvB,uCAAuC;IAwBrD;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAO5B,OAAO,CAAC,eAAe;CAU1B"}
|