@memberjunction/codegen-lib 6.1.0-edge.3 → 6.1.0-edge.5
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 +50 -21
- package/dist/Config/config.d.ts +290 -11
- package/dist/Config/config.d.ts.map +1 -1
- package/dist/Config/config.js +259 -9
- package/dist/Config/config.js.map +1 -1
- package/dist/Config/schema-output.d.ts +33 -0
- package/dist/Config/schema-output.d.ts.map +1 -0
- package/dist/Config/schema-output.js +52 -0
- package/dist/Config/schema-output.js.map +1 -0
- package/dist/Database/__tests__/exclude-schema-permissions.test.d.ts +2 -0
- package/dist/Database/__tests__/exclude-schema-permissions.test.d.ts.map +1 -0
- package/dist/Database/__tests__/exclude-schema-permissions.test.js +32 -0
- package/dist/Database/__tests__/exclude-schema-permissions.test.js.map +1 -0
- package/dist/Database/codeGenDatabaseProvider.d.ts +126 -2
- package/dist/Database/codeGenDatabaseProvider.d.ts.map +1 -1
- package/dist/Database/codeGenDatabaseProvider.js +203 -0
- package/dist/Database/codeGenDatabaseProvider.js.map +1 -1
- package/dist/Database/exclude-tables.d.ts +26 -0
- package/dist/Database/exclude-tables.d.ts.map +1 -0
- package/dist/Database/exclude-tables.js +38 -0
- package/dist/Database/exclude-tables.js.map +1 -0
- package/dist/Database/heal-schema-params.d.ts +33 -0
- package/dist/Database/heal-schema-params.d.ts.map +1 -0
- package/dist/Database/heal-schema-params.js +51 -0
- package/dist/Database/heal-schema-params.js.map +1 -0
- package/dist/Database/manage-metadata.d.ts +59 -0
- package/dist/Database/manage-metadata.d.ts.map +1 -1
- package/dist/Database/manage-metadata.js +157 -61
- package/dist/Database/manage-metadata.js.map +1 -1
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.d.ts +25 -35
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.d.ts.map +1 -1
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js +97 -51
- package/dist/Database/providers/postgresql/PostgreSQLCodeGenProvider.js.map +1 -1
- package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.d.ts +2 -0
- package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.d.ts.map +1 -0
- package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.js +110 -0
- package/dist/Database/providers/postgresql/__tests__/SoftPrimaryKeyIndex.test.js.map +1 -0
- package/dist/Database/providers/postgresql/metadataSupportObjects.js +78 -10
- package/dist/Database/providers/postgresql/metadataSupportObjects.js.map +1 -1
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.d.ts +14 -0
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.d.ts.map +1 -1
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js +38 -0
- package/dist/Database/providers/sqlserver/SQLServerCodeGenProvider.js.map +1 -1
- package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.test.js +17 -0
- package/dist/Database/providers/sqlserver/__tests__/SQLServerCodeGenProvider.test.js.map +1 -1
- package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.d.ts +2 -0
- package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.d.ts.map +1 -0
- package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.js +195 -0
- package/dist/Database/providers/sqlserver/__tests__/SoftPrimaryKeyIndex.test.js.map +1 -0
- package/dist/Database/schema-filters.d.ts +23 -0
- package/dist/Database/schema-filters.d.ts.map +1 -0
- package/dist/Database/schema-filters.js +42 -0
- package/dist/Database/schema-filters.js.map +1 -0
- package/dist/Database/schema-scope.d.ts.map +1 -1
- package/dist/Database/schema-scope.js +4 -0
- package/dist/Database/schema-scope.js.map +1 -1
- package/dist/Database/sql_codegen.d.ts +33 -0
- package/dist/Database/sql_codegen.d.ts.map +1 -1
- package/dist/Database/sql_codegen.js +147 -56
- package/dist/Database/sql_codegen.js.map +1 -1
- package/dist/EntityNameScanner/EntityNameScanner.d.ts.map +1 -1
- package/dist/EntityNameScanner/EntityNameScanner.js +33 -2
- package/dist/EntityNameScanner/EntityNameScanner.js.map +1 -1
- package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts +30 -4
- package/dist/Manifest/GenerateClassRegistrationsManifest.d.ts.map +1 -1
- package/dist/Manifest/GenerateClassRegistrationsManifest.js +175 -25
- package/dist/Manifest/GenerateClassRegistrationsManifest.js.map +1 -1
- package/dist/Misc/codegen-reporter.d.ts +3 -0
- package/dist/Misc/codegen-reporter.d.ts.map +1 -1
- package/dist/Misc/codegen-reporter.js +3 -0
- package/dist/Misc/codegen-reporter.js.map +1 -1
- package/dist/Misc/emit-stats.d.ts +28 -0
- package/dist/Misc/emit-stats.d.ts.map +1 -0
- package/dist/Misc/emit-stats.js +43 -0
- package/dist/Misc/emit-stats.js.map +1 -0
- package/dist/Misc/entity_subclasses_codegen.d.ts +42 -7
- package/dist/Misc/entity_subclasses_codegen.d.ts.map +1 -1
- package/dist/Misc/entity_subclasses_codegen.js +177 -52
- package/dist/Misc/entity_subclasses_codegen.js.map +1 -1
- package/dist/Misc/file-write.d.ts +15 -0
- package/dist/Misc/file-write.d.ts.map +1 -0
- package/dist/Misc/file-write.js +33 -0
- package/dist/Misc/file-write.js.map +1 -0
- package/dist/Misc/graphql_server_codegen.d.ts +12 -2
- package/dist/Misc/graphql_server_codegen.d.ts.map +1 -1
- package/dist/Misc/graphql_server_codegen.js +61 -12
- package/dist/Misc/graphql_server_codegen.js.map +1 -1
- package/dist/Misc/runCommand.d.ts +5 -0
- package/dist/Misc/runCommand.d.ts.map +1 -1
- package/dist/Misc/runCommand.js +43 -17
- package/dist/Misc/runCommand.js.map +1 -1
- package/dist/Misc/schema-emit.d.ts +123 -0
- package/dist/Misc/schema-emit.d.ts.map +1 -0
- package/dist/Misc/schema-emit.js +220 -0
- package/dist/Misc/schema-emit.js.map +1 -0
- package/dist/Misc/system_integrity.d.ts.map +1 -1
- package/dist/Misc/system_integrity.js +5 -0
- package/dist/Misc/system_integrity.js.map +1 -1
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/runCodeGen.d.ts +20 -2
- package/dist/runCodeGen.d.ts.map +1 -1
- package/dist/runCodeGen.js +147 -21
- package/dist/runCodeGen.js.map +1 -1
- package/package.json +29 -29
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-filters.d.ts","sourceRoot":"","sources":["../../src/Database/schema-filters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,kEAAkE;AAClE,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAM3F;AAED;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAC7C,YAAY,EAAE,MAAM,EACpB,aAAa,EAAE,MAAM,EACrB,8BAA8B,EAAE,OAAO,GACxC,OAAO,CAKT;AAED;;;;;;;GAOG;AACH,wBAAgB,kCAAkC,CAC9C,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EAAE,EACxB,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GACjC,OAAO,CAQT"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure schema-scope predicates used by CodeGen SQL generation.
|
|
3
|
+
* Kept out of sql_codegen.ts so unit tests do not load the full generator.
|
|
4
|
+
*/
|
|
5
|
+
/** Case-insensitive, trimmed membership in a schema-name list. */
|
|
6
|
+
export function schemaNameInList(schema, list) {
|
|
7
|
+
if (!list || list.length === 0) {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
const key = schema.trim().toLowerCase();
|
|
11
|
+
return list.some((s) => s.trim().toLowerCase() === key);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Cascade SQL for a related entity whose FK points at `parentSchema`.
|
|
15
|
+
* Default is intra-schema only. `allowCrossSchemaCascadeDeletes` restores the
|
|
16
|
+
* historical walk across every schema in metadata — that is a dangerous
|
|
17
|
+
* escape hatch and must stay off for Open Apps.
|
|
18
|
+
*/
|
|
19
|
+
export function shouldEmitCascadeForRelatedEntity(parentSchema, relatedSchema, allowCrossSchemaCascadeDeletes) {
|
|
20
|
+
if (allowCrossSchemaCascadeDeletes) {
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
return parentSchema.trim().toLowerCase() === relatedSchema.trim().toLowerCase();
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Whether a custom/layered base view for `schemaName` may be `sp_refreshview`'d
|
|
27
|
+
* into the migration log (STEP 4.5).
|
|
28
|
+
*
|
|
29
|
+
* Always drop `excludeSchemas`. When `includeSchemas` is non-empty, keep only
|
|
30
|
+
* that positive list. When it is empty/unset, keep current "all modified
|
|
31
|
+
* custom views" behavior minus excludes.
|
|
32
|
+
*/
|
|
33
|
+
export function entityInCustomBaseViewRefreshScope(schemaName, excludeSchemas, includeSchemas) {
|
|
34
|
+
if (schemaNameInList(schemaName, excludeSchemas)) {
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
if (includeSchemas && includeSchemas.length > 0) {
|
|
38
|
+
return schemaNameInList(schemaName, includeSchemas);
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=schema-filters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-filters.js","sourceRoot":"","sources":["../../src/Database/schema-filters.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,kEAAkE;AAClE,MAAM,UAAU,gBAAgB,CAAC,MAAc,EAAE,IAAiC;IAC9E,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACxC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iCAAiC,CAC7C,YAAoB,EACpB,aAAqB,EACrB,8BAAuC;IAEvC,IAAI,8BAA8B,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,OAAO,YAAY,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,aAAa,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AACpF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kCAAkC,CAC9C,UAAkB,EAClB,cAAwB,EACxB,cAAgC;IAEhC,IAAI,gBAAgB,CAAC,UAAU,EAAE,cAAc,CAAC,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,cAAc,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,OAAO,gBAAgB,CAAC,UAAU,EAAE,cAAc,CAAC,CAAC;IACxD,CAAC;IACD,OAAO,IAAI,CAAC;AAChB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-scope.d.ts","sourceRoot":"","sources":["../../src/Database/schema-scope.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schema-scope.d.ts","sourceRoot":"","sources":["../../src/Database/schema-scope.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qCAAqC,CACnD,UAAU,EAAE,MAAM,EAAE,EACpB,cAAc,EAAE,MAAM,EAAE,EACxB,sBAAsB,EAAE,MAAM,EAAE,GAC/B,MAAM,EAAE,CAYV;AAED,sEAAsE;AACtE,MAAM,WAAW,iBAAiB;IAChC,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAajG"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { snapshotAuthoredExcludeSchemas } from './heal-schema-params.js';
|
|
1
2
|
/**
|
|
2
3
|
* Schema-scope resolution helpers for CodeGen.
|
|
3
4
|
*
|
|
@@ -58,6 +59,9 @@ export function computeSchemasToExcludeForIncludeList(allSchemas, includeSchemas
|
|
|
58
59
|
* @returns the schema names that were newly appended (empty when the scope is unused or already applied)
|
|
59
60
|
*/
|
|
60
61
|
export function applyIncludeSchemaScope(allSchemas, config) {
|
|
62
|
+
// Capture authored excludes before this run mutates excludeSchemas. Heal EXEC
|
|
63
|
+
// statements must serialize that original list, not the sibling snapshot.
|
|
64
|
+
snapshotAuthoredExcludeSchemas(config.excludeSchemas);
|
|
61
65
|
if (!config.includeSchemas || config.includeSchemas.length === 0) {
|
|
62
66
|
return []; // classic exclude-only behavior, unchanged
|
|
63
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-scope.js","sourceRoot":"","sources":["../../src/Database/schema-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qCAAqC,CACnD,UAAoB,EACpB,cAAwB,EACxB,sBAAgC;IAEhC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACxF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,6CAA6C;QACtE,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAQD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAoB,EAAE,MAAyB;IACrF,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,CAAC,CAAC,2CAA2C;IACxD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,CAAC,cAAc,GAAG,EAAE,CAAC;IAC7B,CAAC;IACD,MAAM,SAAS,GAAG,qCAAqC,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAClH,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;IACzC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
1
|
+
{"version":3,"file":"schema-scope.js","sourceRoot":"","sources":["../../src/Database/schema-scope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,8BAA8B,EAAE,MAAM,sBAAsB,CAAC;AAEtE;;;;;;;;;;GAUG;AAEH;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,qCAAqC,CACnD,UAAoB,EACpB,cAAwB,EACxB,sBAAgC;IAEhC,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IAC9E,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;IACxF,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,KAAK,MAAM,MAAM,IAAI,UAAU,EAAE,CAAC;QAChC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QACxC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACnD,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,6CAA6C;QACtE,CAAC;IACH,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAQD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,uBAAuB,CAAC,UAAoB,EAAE,MAAyB;IACrF,8EAA8E;IAC9E,0EAA0E;IAC1E,8BAA8B,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IACtD,IAAI,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACjE,OAAO,EAAE,CAAC,CAAC,2CAA2C;IACxD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC;QAC3B,MAAM,CAAC,cAAc,GAAG,EAAE,CAAC;IAC7B,CAAC;IACD,MAAM,SAAS,GAAG,qCAAqC,CAAC,UAAU,EAAE,MAAM,CAAC,cAAc,EAAE,MAAM,CAAC,cAAc,CAAC,CAAC;IAClH,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC;IACzC,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
|
@@ -8,6 +8,14 @@ export declare const SPType: {
|
|
|
8
8
|
readonly Delete: "Delete";
|
|
9
9
|
};
|
|
10
10
|
export type SPType = typeof SPType[keyof typeof SPType];
|
|
11
|
+
/**
|
|
12
|
+
* Entities whose SchemaName is not in excludeSchemas (case-insensitive).
|
|
13
|
+
* This is the CodeGen run's in-scope set: SQL objects and GRANTs are
|
|
14
|
+
* generated and executed only for these. excludeSchemas means "not this run".
|
|
15
|
+
*/
|
|
16
|
+
export declare function entitiesNotInExcludedSchemas<T extends {
|
|
17
|
+
SchemaName: string;
|
|
18
|
+
}>(entities: T[], excludeSchemas: string[]): T[];
|
|
11
19
|
/**
|
|
12
20
|
* This class is responsible for generating database level objects like views, stored procedures, permissions, etc. You can sub-class this class to create your own SQL generation logic or implement support for other
|
|
13
21
|
* databases. The base class implements support for SQL Server. In future versions of MJ, we will break out an abstract base class that has the skeleton of the logic and then the SQL Server version will be a sub-class
|
|
@@ -51,6 +59,13 @@ export declare class SQLCodeGenBase {
|
|
|
51
59
|
* Ordered list of entity IDs for delete SP regeneration (dependency order)
|
|
52
60
|
*/
|
|
53
61
|
protected orderedEntitiesForDeleteSPRegeneration: string[];
|
|
62
|
+
/**
|
|
63
|
+
* `schema.routine` keys (lowercased) present in the database at the start of
|
|
64
|
+
* this SQL-generation pass. Used to force-log CREATE PROC for routines that
|
|
65
|
+
* were dropped out-of-band (BigSchemaDemo recreate, a failed prior batch)
|
|
66
|
+
* while the entity itself is not in newEntityList/modifiedEntityList.
|
|
67
|
+
*/
|
|
68
|
+
protected existingRoutines: Set<string> | null;
|
|
54
69
|
manageSQLScriptsAndExecution(pool: CodeGenConnection, entities: EntityInfo[], directory: string, currentUser: UserInfo): Promise<boolean>;
|
|
55
70
|
/**
|
|
56
71
|
* Apply reason-specific fixups after late-phase view regeneration.
|
|
@@ -205,6 +220,14 @@ export declare class SQLCodeGenBase {
|
|
|
205
220
|
files: string[];
|
|
206
221
|
}>;
|
|
207
222
|
getSPName(entity: EntityInfo, type: SPType): string;
|
|
223
|
+
/**
|
|
224
|
+
* Snapshot every CRUD routine currently in the database (one query) so
|
|
225
|
+
* generate-and-log can force-emit CREATE PROC for objects that vanished
|
|
226
|
+
* without the entity landing on newEntityList/modifiedEntityList.
|
|
227
|
+
*/
|
|
228
|
+
protected loadExistingRoutines(pool: CodeGenConnection, entities: EntityInfo[]): Promise<void>;
|
|
229
|
+
protected isRoutineMissing(schema: string, routineName: string): boolean;
|
|
230
|
+
protected forceLogForRoutine(entity: EntityInfo, routineName: string, baseViewChanged: boolean): boolean;
|
|
208
231
|
getEntityPermissionFileNames(entity: EntityInfo): string[];
|
|
209
232
|
/**
|
|
210
233
|
* Deprecated - do not use
|
|
@@ -226,6 +249,16 @@ export declare class SQLCodeGenBase {
|
|
|
226
249
|
* Delegates to the database provider for platform-specific index DDL.
|
|
227
250
|
*/
|
|
228
251
|
generateIndexesForForeignKeys(pool: CodeGenConnection, entity: EntityInfo): string;
|
|
252
|
+
/**
|
|
253
|
+
* Generates the composite index covering the entity's SOFT primary key. Empty for every
|
|
254
|
+
* entity with a real `PRIMARY KEY` constraint, which is nearly all of them.
|
|
255
|
+
*
|
|
256
|
+
* Kept separate from {@link generateIndexesForForeignKeys} and gated by its own setting: a
|
|
257
|
+
* soft-PK index serves MJ's own per-record existence check on the create path, which is a
|
|
258
|
+
* different concern from indexing foreign keys for joins and filters, and an operator's
|
|
259
|
+
* opinion about one is not an opinion about the other.
|
|
260
|
+
*/
|
|
261
|
+
generateIndexForSoftPrimaryKey(entity: EntityInfo): string;
|
|
229
262
|
/**
|
|
230
263
|
* Detects self-referential foreign keys in an entity (e.g., ParentTaskID pointing back to Task table)
|
|
231
264
|
* Returns array of field info objects representing recursive relationships
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sql_codegen.d.ts","sourceRoot":"","sources":["../../src/Database/sql_codegen.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,eAAe,EAAkC,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAK7G,OAAO,EAAE,cAAc,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAE,uBAAuB,EAAmD,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"sql_codegen.d.ts","sourceRoot":"","sources":["../../src/Database/sql_codegen.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,18 +4,29 @@ import * as fs from 'fs';
|
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { SQLUtilityBase } from './sql.js';
|
|
6
6
|
import { CodeGenDatabaseProvider } from './codeGenDatabaseProvider.js';
|
|
7
|
-
import { autoIndexForeignKeys, configInfo, customSqlScripts, mjCoreSchema } from '../Config/config.js';
|
|
7
|
+
import { autoIndexForeignKeys, autoIndexSoftPrimaryKeys, configInfo, customSqlScripts, mjCoreSchema } from '../Config/config.js';
|
|
8
|
+
import { entityInCustomBaseViewRefreshScope, shouldEmitCascadeForRelatedEntity } from './schema-filters.js';
|
|
8
9
|
import { ManageMetadataBase } from './manage-metadata.js';
|
|
9
10
|
import { UserCache } from '@memberjunction/generic-database-provider';
|
|
10
11
|
import { combineFiles, logIf } from '../Misc/util.js';
|
|
11
12
|
import { MJGlobal, UUIDsEqual } from '@memberjunction/global';
|
|
12
13
|
import { SQLLogging } from '../Misc/sql_logging.js';
|
|
13
14
|
import { TempBatchFile } from '../Misc/temp_batch_file.js';
|
|
15
|
+
import { writeFileIfChanged as writeFileIfChangedShared } from '../Misc/file-write.js';
|
|
14
16
|
export const SPType = {
|
|
15
17
|
Create: 'Create',
|
|
16
18
|
Update: 'Update',
|
|
17
19
|
Delete: 'Delete',
|
|
18
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Entities whose SchemaName is not in excludeSchemas (case-insensitive).
|
|
23
|
+
* This is the CodeGen run's in-scope set: SQL objects and GRANTs are
|
|
24
|
+
* generated and executed only for these. excludeSchemas means "not this run".
|
|
25
|
+
*/
|
|
26
|
+
export function entitiesNotInExcludedSchemas(entities, excludeSchemas) {
|
|
27
|
+
const exclude = new Set(excludeSchemas.map((s) => s.toLowerCase()));
|
|
28
|
+
return entities.filter((e) => !exclude.has(e.SchemaName.toLowerCase()));
|
|
29
|
+
}
|
|
19
30
|
/**
|
|
20
31
|
* This class is responsible for generating database level objects like views, stored procedures, permissions, etc. You can sub-class this class to create your own SQL generation logic or implement support for other
|
|
21
32
|
* databases. The base class implements support for SQL Server. In future versions of MJ, we will break out an abstract base class that has the skeleton of the logic and then the SQL Server version will be a sub-class
|
|
@@ -57,6 +68,13 @@ export class SQLCodeGenBase {
|
|
|
57
68
|
* Ordered list of entity IDs for delete SP regeneration (dependency order)
|
|
58
69
|
*/
|
|
59
70
|
this.orderedEntitiesForDeleteSPRegeneration = [];
|
|
71
|
+
/**
|
|
72
|
+
* `schema.routine` keys (lowercased) present in the database at the start of
|
|
73
|
+
* this SQL-generation pass. Used to force-log CREATE PROC for routines that
|
|
74
|
+
* were dropped out-of-band (BigSchemaDemo recreate, a failed prior batch)
|
|
75
|
+
* while the entity itself is not in newEntityList/modifiedEntityList.
|
|
76
|
+
*/
|
|
77
|
+
this.existingRoutines = null;
|
|
60
78
|
}
|
|
61
79
|
get SQLUtilityObject() {
|
|
62
80
|
return this._sqlUtilityObject;
|
|
@@ -69,6 +87,7 @@ export class SQLCodeGenBase {
|
|
|
69
87
|
}
|
|
70
88
|
async manageSQLScriptsAndExecution(pool, entities, directory, currentUser) {
|
|
71
89
|
try {
|
|
90
|
+
this.existingRoutines = null;
|
|
72
91
|
// Build list of entities qualified for forced regeneration if entityWhereClause is provided
|
|
73
92
|
if (configInfo.forceRegeneration?.enabled && configInfo.forceRegeneration?.entityWhereClause) {
|
|
74
93
|
this.filterEntitiesQualifiedForRegeneration = true; // Enable filtering
|
|
@@ -104,13 +123,12 @@ export class SQLCodeGenBase {
|
|
|
104
123
|
return false;
|
|
105
124
|
}
|
|
106
125
|
succeedSpinner(`Custom SQL scripts completed (${(new Date().getTime() - startTime.getTime()) / 1000}s)`);
|
|
126
|
+
await this.loadExistingRoutines(pool, entities);
|
|
107
127
|
// ALWAYS use the first filter where we only include entities that have IncludeInAPI = 1
|
|
108
128
|
// Entities are already sorted by name in PostProcessEntityMetadata (see providerBase.ts)
|
|
109
129
|
const baselineEntities = entities.filter(e => e.IncludeInAPI);
|
|
110
130
|
// OPTIMIZATION: Use a Set for O(1) lookups instead of O(n) array finds to improve performance
|
|
111
|
-
const
|
|
112
|
-
const includedEntities = baselineEntities.filter(e => !excludeSchemasSet.has(e.SchemaName.toLowerCase())); //only include entities that are NOT in the excludeSchemas list
|
|
113
|
-
const excludedEntities = baselineEntities.filter(e => excludeSchemasSet.has(e.SchemaName.toLowerCase())); //only include entities that ARE in the excludeSchemas list in this array
|
|
131
|
+
const includedEntities = entitiesNotInExcludedSchemas(baselineEntities, configInfo.excludeSchemas);
|
|
114
132
|
// Initialize temp batch files for each schema
|
|
115
133
|
// These will be populated as SQL is generated and will be used for actual execution
|
|
116
134
|
const schemas = Array.from(new Set(baselineEntities.map(e => e.SchemaName))).sort();
|
|
@@ -140,17 +158,17 @@ export class SQLCodeGenBase {
|
|
|
140
158
|
.filter(e => e !== undefined);
|
|
141
159
|
// Track per-batch success without short-circuiting. Historically,
|
|
142
160
|
// any single batch failure here returned `false` immediately, which
|
|
143
|
-
// skipped the cascade-regen and
|
|
144
|
-
//
|
|
145
|
-
//
|
|
146
|
-
//
|
|
147
|
-
//
|
|
148
|
-
//
|
|
161
|
+
// skipped the cascade-regen batch and left those entities with no
|
|
162
|
+
// SQL emitted at all. The post-run CRUD validator (in runCodeGen.ts)
|
|
163
|
+
// is the authoritative ship-gate now, so we want every in-scope
|
|
164
|
+
// batch to attempt its work and surface the complete picture of
|
|
165
|
+
// what's missing — partial generation is strictly more useful than
|
|
166
|
+
// nothing.
|
|
149
167
|
let entityGenSuccess = true;
|
|
150
168
|
// Build a UNION will-regenerate set across every batch we're about
|
|
151
|
-
// to launch (main + cascade-regen
|
|
152
|
-
//
|
|
153
|
-
//
|
|
169
|
+
// to launch (main + cascade-regen). The PG view fallback's
|
|
170
|
+
// restoreDependents path uses this to skip restoring captured
|
|
171
|
+
// dependents that codegen will recreate later in the run.
|
|
154
172
|
// Without the union, batch 1's fallback only sees batch 1's
|
|
155
173
|
// entities — so a dependent like vwAIAgentRuns (which lives in
|
|
156
174
|
// batch 2 cascade-regen) is "missing from willRegenerate", the
|
|
@@ -162,7 +180,6 @@ export class SQLCodeGenBase {
|
|
|
162
180
|
const allBatchEntities = [
|
|
163
181
|
...entitiesWithoutCascadeRegeneration,
|
|
164
182
|
...entitiesForCascadeRegeneration,
|
|
165
|
-
...excludedEntities,
|
|
166
183
|
];
|
|
167
184
|
const globalWillRegenerate = new Set(allBatchEntities
|
|
168
185
|
.filter(e => !!e.BaseView)
|
|
@@ -180,7 +197,8 @@ export class SQLCodeGenBase {
|
|
|
180
197
|
// AI Engine init because vwAIModels is gone. SQL Server doesn't
|
|
181
198
|
// hit this because its execution path is bulk-monolithic, not
|
|
182
199
|
// phased per-entity.
|
|
183
|
-
const
|
|
200
|
+
const configuredBatch = configInfo.fileEmit?.sqlEntityBatchSize ?? 8;
|
|
201
|
+
const perEntityBatchSize = configInfo.dbPlatform === 'postgresql' ? 1 : configuredBatch;
|
|
184
202
|
// Generate SQL for entities that don't need cascade delete regeneration
|
|
185
203
|
const genResult = await this.generateAndExecuteEntitySQLToSeparateFiles({
|
|
186
204
|
pool,
|
|
@@ -196,7 +214,7 @@ export class SQLCodeGenBase {
|
|
|
196
214
|
willRegenerate: globalWillRegenerate
|
|
197
215
|
}); // enable sql logging for NEW entities....
|
|
198
216
|
if (!genResult.Success) {
|
|
199
|
-
logError('Main entity SQL generation batch had failures — continuing with cascade-regen
|
|
217
|
+
logError('Main entity SQL generation batch had failures — continuing with cascade-regen; validator will report any missing routines.');
|
|
200
218
|
entityGenSuccess = false;
|
|
201
219
|
}
|
|
202
220
|
// Generate SQL for cascade delete regenerations in dependency order (sequentially)
|
|
@@ -219,23 +237,19 @@ export class SQLCodeGenBase {
|
|
|
219
237
|
}
|
|
220
238
|
genResult.Files.push(...cascadeGenResult.Files);
|
|
221
239
|
}
|
|
222
|
-
// STEP 2(c)
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
if (!genResult2.Success) {
|
|
236
|
-
logError('Excluded-entities permissions batch had failures — continuing; validator will report any missing routines.');
|
|
237
|
-
entityGenSuccess = false;
|
|
238
|
-
}
|
|
240
|
+
// STEP 2(c) used to generate+apply GRANT files for excludeSchemas entities
|
|
241
|
+
// ("we don't want to generate SQL, we do want to generate the permissions").
|
|
242
|
+
// That is wrong once excludeSchemas means "not this CodeGen run":
|
|
243
|
+
//
|
|
244
|
+
// - Open Apps exclude sibling schemas (__mj_BizAppsCommon, …) and __mj.
|
|
245
|
+
// GRANT SELECT ON [__mj_BizAppsCommon].[vwContactMethods] then runs from
|
|
246
|
+
// the orders (or other) repo, pollutes SQL Scripts/generated/<sibling>/,
|
|
247
|
+
// and fails the whole run (exit 1) when that object is missing or lives
|
|
248
|
+
// in a schema the executing login does not resolve.
|
|
249
|
+
// - Core (__mj) permissions already ship in MJ migrations. Refreshing them
|
|
250
|
+
// from an app CodeGen is not this app's job.
|
|
251
|
+
//
|
|
252
|
+
// Permissions are applied in STEP 4 for includedEntities only.
|
|
239
253
|
if (entityGenSuccess) {
|
|
240
254
|
succeedSpinner(`Entity generation completed (${(new Date().getTime() - step2StartTime.getTime()) / 1000}s)`);
|
|
241
255
|
}
|
|
@@ -244,15 +258,15 @@ export class SQLCodeGenBase {
|
|
|
244
258
|
}
|
|
245
259
|
// STEP 2(d) now that we've generated the SQL, let's create a combined file in each schema sub-directory for convenience for a DBA
|
|
246
260
|
startSpinner('Creating combined SQL files...');
|
|
247
|
-
const allEntityFiles = this.createCombinedEntitySQLFiles(directory,
|
|
248
|
-
succeedSpinner(`Created combined SQL files for ${allEntityFiles.length}
|
|
261
|
+
const allEntityFiles = this.createCombinedEntitySQLFiles(directory, includedEntities);
|
|
262
|
+
succeedSpinner(`Created combined SQL files for ${allEntityFiles.length} file(s)`);
|
|
249
263
|
// STEP 2(e) ---- FINALLY, we execute SQL in proper dependency order
|
|
250
264
|
// Use temp batch files (which maintain CodeGen log order) if available, otherwise fall back to combined files
|
|
251
265
|
startSpinner('Executing entity SQL files...');
|
|
252
266
|
const step2eStartTime = new Date();
|
|
253
267
|
let executionSuccess = false;
|
|
254
268
|
if (useProviderPhasedExecution) {
|
|
255
|
-
// Per-entity phased execution already ran during
|
|
269
|
+
// Per-entity phased execution already ran during step 2(b).
|
|
256
270
|
// Skip the bulk file re-execution — replaying the same SQL here
|
|
257
271
|
// would re-trigger 42P16 without the phased recovery wrapper and
|
|
258
272
|
// undo the work the phased executor just did.
|
|
@@ -363,10 +377,13 @@ export class SQLCodeGenBase {
|
|
|
363
377
|
succeedSpinner('No valid entities to regenerate');
|
|
364
378
|
}
|
|
365
379
|
}
|
|
366
|
-
// STEP 4- Apply permissions
|
|
380
|
+
// STEP 4- Apply permissions for THIS run's schemas only. Excluded-schema
|
|
381
|
+
// GRANT files are not generated (see STEP 2(c) note) and must not be
|
|
382
|
+
// executed: a missing sibling object would fail CodeGen with
|
|
383
|
+
// "Cannot find the object 'vw…'" even though this app's work succeeded.
|
|
367
384
|
startSpinner('Applying permissions...');
|
|
368
385
|
const step4StartTime = new Date();
|
|
369
|
-
if (!await this.applyPermissions(pool, directory,
|
|
386
|
+
if (!await this.applyPermissions(pool, directory, includedEntities)) {
|
|
370
387
|
failSpinner('Failed to apply permissions');
|
|
371
388
|
overallSuccess = false;
|
|
372
389
|
}
|
|
@@ -713,14 +730,7 @@ export class SQLCodeGenBase {
|
|
|
713
730
|
* This avoids false timestamp updates and unnecessary I/O.
|
|
714
731
|
*/
|
|
715
732
|
writeFileIfChanged(filePath, newContent) {
|
|
716
|
-
|
|
717
|
-
const existing = fs.readFileSync(filePath, 'utf-8');
|
|
718
|
-
if (existing === newContent) {
|
|
719
|
-
return false;
|
|
720
|
-
}
|
|
721
|
-
}
|
|
722
|
-
fs.writeFileSync(filePath, newContent);
|
|
723
|
-
return true;
|
|
733
|
+
return writeFileIfChangedShared(filePath, newContent);
|
|
724
734
|
}
|
|
725
735
|
/**
|
|
726
736
|
* Fetches the current base view definition from SQL Server and compares it against newly generated SQL.
|
|
@@ -925,7 +935,8 @@ export class SQLCodeGenBase {
|
|
|
925
935
|
return md.Entities.filter(e => modifiedOrNewNames.includes(e.Name) &&
|
|
926
936
|
!e.BaseViewGenerated &&
|
|
927
937
|
e.IncludeInAPI &&
|
|
928
|
-
!e.VirtualEntity
|
|
938
|
+
!e.VirtualEntity &&
|
|
939
|
+
entityInCustomBaseViewRefreshScope(e.SchemaName, configInfo.excludeSchemas ?? [], configInfo.includeSchemas));
|
|
929
940
|
}
|
|
930
941
|
/**
|
|
931
942
|
* Builds a combined SQL string of sp_refreshview statements for the given entities.
|
|
@@ -951,7 +962,14 @@ export class SQLCodeGenBase {
|
|
|
951
962
|
return outer; // fully custom — one view, and it is a standing prerequisite
|
|
952
963
|
}
|
|
953
964
|
const inner = this._dbProvider.generateViewRefreshSQL(e.SchemaName, e.GeneratedViewName);
|
|
954
|
-
|
|
965
|
+
const rebind = this._dbProvider.generateLayeredOuterRebindSQL(e);
|
|
966
|
+
const outerSql = outer.trim().length > 0
|
|
967
|
+
? this.guardOnApplicationOwnedView(e, outer)
|
|
968
|
+
: '';
|
|
969
|
+
const rebindSql = rebind.trim().length > 0
|
|
970
|
+
? this.guardOnApplicationOwnedView(e, rebind.trim())
|
|
971
|
+
: '';
|
|
972
|
+
return [inner, outerSql, rebindSql].filter((s) => s && s.trim().length > 0).join('\n');
|
|
955
973
|
})
|
|
956
974
|
.join('\n');
|
|
957
975
|
}
|
|
@@ -981,9 +999,21 @@ export class SQLCodeGenBase {
|
|
|
981
999
|
let baseViewChanged = false;
|
|
982
1000
|
// Indexes for Fkeys for the table (skip for virtual entities — views can't have indexes)
|
|
983
1001
|
if (!options.onlyPermissions && !options.entity.VirtualEntity) {
|
|
984
|
-
const
|
|
1002
|
+
const forceIndexes = !!(configInfo.forceRegeneration?.enabled && configInfo.forceRegeneration?.indexes);
|
|
1003
|
+
const shouldGenerateIndexes = autoIndexForeignKeys() || forceIndexes;
|
|
985
1004
|
const indexSQL = shouldGenerateIndexes ? this.generateIndexesForForeignKeys(options.pool, options.entity) : ''; // generate indexes if auto-indexing is on OR force regeneration is enabled
|
|
986
|
-
|
|
1005
|
+
// The soft-PK index rides in the same generated file (and therefore the same
|
|
1006
|
+
// migration log), but on its own setting — see generateIndexForSoftPrimaryKey.
|
|
1007
|
+
// Appended rather than prepended so the file's existing content stays
|
|
1008
|
+
// byte-identical for every entity that has no soft PK, which is nearly all of
|
|
1009
|
+
// them: writeFileIfChanged compares content, and reordering would rewrite the
|
|
1010
|
+
// whole tree for no functional gain.
|
|
1011
|
+
const softPKSQL = (autoIndexSoftPrimaryKeys() || forceIndexes)
|
|
1012
|
+
? this.generateIndexForSoftPrimaryKey(options.entity)
|
|
1013
|
+
: '';
|
|
1014
|
+
const s = this.generateSingleEntitySQLFileHeader(options.entity, 'Index for Foreign Keys')
|
|
1015
|
+
+ indexSQL
|
|
1016
|
+
+ (softPKSQL ? (indexSQL ? '\n\n' : '') + softPKSQL : '');
|
|
987
1017
|
if (options.writeFiles) {
|
|
988
1018
|
const filePath = path.join(options.directory, this.SQLUtilityObject.getDBObjectFileName('index', options.entity.SchemaName, options.entity.BaseTable, false, true));
|
|
989
1019
|
this.writeFileIfChanged(filePath, s);
|
|
@@ -1080,7 +1110,7 @@ export class SQLCodeGenBase {
|
|
|
1080
1110
|
if (options.writeFiles) {
|
|
1081
1111
|
const filePath = path.join(options.directory, this.SQLUtilityObject.getDBObjectFileName('sp', options.entity.SchemaName, spName, false, true));
|
|
1082
1112
|
this.writeFileIfChanged(filePath, s);
|
|
1083
|
-
this.logSQLForNewOrModifiedEntity(options.entity, s, `spCreate SQL for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, baseViewChanged);
|
|
1113
|
+
this.logSQLForNewOrModifiedEntity(options.entity, s, `spCreate SQL for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, this.forceLogForRoutine(options.entity, spName, baseViewChanged));
|
|
1084
1114
|
files.push(filePath);
|
|
1085
1115
|
}
|
|
1086
1116
|
sRet += s + '\n' + this._dbProvider.BatchSeparator + '\n';
|
|
@@ -1091,7 +1121,7 @@ export class SQLCodeGenBase {
|
|
|
1091
1121
|
if (options.writeFiles) {
|
|
1092
1122
|
const filePath = path.join(options.directory, this.SQLUtilityObject.getDBObjectFileName('sp', options.entity.SchemaName, spName, true, true));
|
|
1093
1123
|
this.writeFileIfChanged(filePath, s);
|
|
1094
|
-
this.logSQLForNewOrModifiedEntity(options.entity, s, `spCreate Permissions for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, baseViewChanged);
|
|
1124
|
+
this.logSQLForNewOrModifiedEntity(options.entity, s, `spCreate Permissions for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, this.forceLogForRoutine(options.entity, spName, baseViewChanged));
|
|
1095
1125
|
files.push(filePath);
|
|
1096
1126
|
}
|
|
1097
1127
|
// now, append the permissions to the return string IF we did NOT generate the proc - because if we generated the proc, that
|
|
@@ -1110,7 +1140,7 @@ export class SQLCodeGenBase {
|
|
|
1110
1140
|
if (options.writeFiles) {
|
|
1111
1141
|
const filePath = path.join(options.directory, this.SQLUtilityObject.getDBObjectFileName('sp', options.entity.SchemaName, spName, false, true));
|
|
1112
1142
|
this.writeFileIfChanged(filePath, s);
|
|
1113
|
-
this.logSQLForNewOrModifiedEntity(options.entity, s, `spUpdate SQL for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, baseViewChanged);
|
|
1143
|
+
this.logSQLForNewOrModifiedEntity(options.entity, s, `spUpdate SQL for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, this.forceLogForRoutine(options.entity, spName, baseViewChanged));
|
|
1114
1144
|
files.push(filePath);
|
|
1115
1145
|
}
|
|
1116
1146
|
sRet += s + '\n' + this._dbProvider.BatchSeparator + '\n';
|
|
@@ -1121,7 +1151,7 @@ export class SQLCodeGenBase {
|
|
|
1121
1151
|
if (options.writeFiles) {
|
|
1122
1152
|
const filePath = path.join(options.directory, this.SQLUtilityObject.getDBObjectFileName('sp', options.entity.SchemaName, spName, true, true));
|
|
1123
1153
|
this.writeFileIfChanged(filePath, s);
|
|
1124
|
-
this.logSQLForNewOrModifiedEntity(options.entity, s, `spUpdate Permissions for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, baseViewChanged);
|
|
1154
|
+
this.logSQLForNewOrModifiedEntity(options.entity, s, `spUpdate Permissions for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, this.forceLogForRoutine(options.entity, spName, baseViewChanged));
|
|
1125
1155
|
files.push(filePath);
|
|
1126
1156
|
}
|
|
1127
1157
|
// now, append the permissions to the return string IF we did NOT generate the proc - because if we generated the proc, that
|
|
@@ -1146,7 +1176,7 @@ export class SQLCodeGenBase {
|
|
|
1146
1176
|
if (options.writeFiles) {
|
|
1147
1177
|
const filePath = path.join(options.directory, this.SQLUtilityObject.getDBObjectFileName('sp', options.entity.SchemaName, spName, false, true));
|
|
1148
1178
|
this.writeFileIfChanged(filePath, s);
|
|
1149
|
-
this.logSQLForNewOrModifiedEntity(options.entity, s, `spDelete SQL for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, baseViewChanged);
|
|
1179
|
+
this.logSQLForNewOrModifiedEntity(options.entity, s, `spDelete SQL for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, this.forceLogForRoutine(options.entity, spName, baseViewChanged));
|
|
1150
1180
|
files.push(filePath);
|
|
1151
1181
|
}
|
|
1152
1182
|
sRet += s + '\n' + this._dbProvider.BatchSeparator + '\n';
|
|
@@ -1157,7 +1187,7 @@ export class SQLCodeGenBase {
|
|
|
1157
1187
|
if (options.writeFiles) {
|
|
1158
1188
|
const filePath = path.join(options.directory, this.SQLUtilityObject.getDBObjectFileName('sp', options.entity.SchemaName, spName, true, true));
|
|
1159
1189
|
this.writeFileIfChanged(filePath, s);
|
|
1160
|
-
this.logSQLForNewOrModifiedEntity(options.entity, s, `spDelete Permissions for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, baseViewChanged);
|
|
1190
|
+
this.logSQLForNewOrModifiedEntity(options.entity, s, `spDelete Permissions for ${options.entity.Name}`, options.enableSQLLoggingForNewOrModifiedEntities, this.forceLogForRoutine(options.entity, spName, baseViewChanged));
|
|
1161
1191
|
files.push(filePath);
|
|
1162
1192
|
}
|
|
1163
1193
|
// now, append the permissions to the return string IF we did NOT generate the proc - because if we generated the proc, that
|
|
@@ -1203,6 +1233,42 @@ export class SQLCodeGenBase {
|
|
|
1203
1233
|
getSPName(entity, type) {
|
|
1204
1234
|
return this._dbProvider.getCRUDRoutineName(entity, type);
|
|
1205
1235
|
}
|
|
1236
|
+
/**
|
|
1237
|
+
* Snapshot every CRUD routine currently in the database (one query) so
|
|
1238
|
+
* generate-and-log can force-emit CREATE PROC for objects that vanished
|
|
1239
|
+
* without the entity landing on newEntityList/modifiedEntityList.
|
|
1240
|
+
*/
|
|
1241
|
+
async loadExistingRoutines(pool, entities) {
|
|
1242
|
+
this.existingRoutines = new Set();
|
|
1243
|
+
const schemas = [...new Set(entities.map((e) => e.SchemaName).filter((s) => !!s))];
|
|
1244
|
+
const sql = this._dbProvider.getRoutineNamesBySchemaSQL(schemas);
|
|
1245
|
+
if (!sql || !sql.trim()) {
|
|
1246
|
+
return;
|
|
1247
|
+
}
|
|
1248
|
+
try {
|
|
1249
|
+
const result = await pool.query(sql);
|
|
1250
|
+
for (const row of result.recordset ?? []) {
|
|
1251
|
+
const schemaName = String(row.schema_name ?? '').toLowerCase();
|
|
1252
|
+
const routineName = String(row.routine_name ?? '').toLowerCase();
|
|
1253
|
+
if (schemaName && routineName) {
|
|
1254
|
+
this.existingRoutines.add(`${schemaName}.${routineName}`);
|
|
1255
|
+
}
|
|
1256
|
+
}
|
|
1257
|
+
}
|
|
1258
|
+
catch (e) {
|
|
1259
|
+
logWarning(`Could not load existing CRUD routines (missing-proc self-heal disabled this run): ${e instanceof Error ? e.message : String(e)}`);
|
|
1260
|
+
this.existingRoutines = null;
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
isRoutineMissing(schema, routineName) {
|
|
1264
|
+
if (!this.existingRoutines) {
|
|
1265
|
+
return false;
|
|
1266
|
+
}
|
|
1267
|
+
return !this.existingRoutines.has(`${schema}.${routineName}`.toLowerCase());
|
|
1268
|
+
}
|
|
1269
|
+
forceLogForRoutine(entity, routineName, baseViewChanged) {
|
|
1270
|
+
return baseViewChanged || this.isRoutineMissing(entity.SchemaName, routineName);
|
|
1271
|
+
}
|
|
1206
1272
|
getEntityPermissionFileNames(entity) {
|
|
1207
1273
|
const files = [];
|
|
1208
1274
|
// all entities have a base view - and we always generate permissions for the base view even if not generated base view
|
|
@@ -1324,6 +1390,19 @@ export class SQLCodeGenBase {
|
|
|
1324
1390
|
const indexStatements = this._dbProvider.generateForeignKeyIndexes(entity);
|
|
1325
1391
|
return indexStatements.join('\n\n');
|
|
1326
1392
|
}
|
|
1393
|
+
/**
|
|
1394
|
+
* Generates the composite index covering the entity's SOFT primary key. Empty for every
|
|
1395
|
+
* entity with a real `PRIMARY KEY` constraint, which is nearly all of them.
|
|
1396
|
+
*
|
|
1397
|
+
* Kept separate from {@link generateIndexesForForeignKeys} and gated by its own setting: a
|
|
1398
|
+
* soft-PK index serves MJ's own per-record existence check on the create path, which is a
|
|
1399
|
+
* different concern from indexing foreign keys for joins and filters, and an operator's
|
|
1400
|
+
* opinion about one is not an opinion about the other.
|
|
1401
|
+
*/
|
|
1402
|
+
generateIndexForSoftPrimaryKey(entity) {
|
|
1403
|
+
const indexStatements = this._dbProvider.generateSoftPrimaryKeyIndex(entity);
|
|
1404
|
+
return indexStatements.join('\n\n');
|
|
1405
|
+
}
|
|
1327
1406
|
/**
|
|
1328
1407
|
* Detects self-referential foreign keys in an entity (e.g., ParentTaskID pointing back to Task table)
|
|
1329
1408
|
* Returns array of field info objects representing recursive relationships
|
|
@@ -1597,6 +1676,12 @@ export class SQLCodeGenBase {
|
|
|
1597
1676
|
const refreshSQL = this._dbProvider.generateViewRefreshSQL(entity.SchemaName, entity.BaseView);
|
|
1598
1677
|
sOutput += this.guardOnApplicationOwnedView(entity, refreshSQL) + separator;
|
|
1599
1678
|
}
|
|
1679
|
+
if (entity.HasLayeredBaseView && !entity.VirtualEntity) {
|
|
1680
|
+
const rebindSQL = this._dbProvider.generateLayeredOuterRebindSQL(entity);
|
|
1681
|
+
if (rebindSQL.trim().length > 0) {
|
|
1682
|
+
sOutput += this.guardOnApplicationOwnedView(entity, rebindSQL.trim()) + separator;
|
|
1683
|
+
}
|
|
1684
|
+
}
|
|
1600
1685
|
return sOutput + permissionsHeader + this.guardOnApplicationOwnedView(entity, permissionsBody) + separator;
|
|
1601
1686
|
}
|
|
1602
1687
|
/**
|
|
@@ -1949,6 +2034,9 @@ export class SQLCodeGenBase {
|
|
|
1949
2034
|
const md = new Metadata(); // global-provider-ok: codegen runs offline against a single provider
|
|
1950
2035
|
// Find all fields in other entities that are foreign keys to this entity
|
|
1951
2036
|
for (const e of md.Entities) {
|
|
2037
|
+
if (!shouldEmitCascadeForRelatedEntity(entity.SchemaName, e.SchemaName, configInfo.allowCrossSchemaCascadeDeletes === true)) {
|
|
2038
|
+
continue;
|
|
2039
|
+
}
|
|
1952
2040
|
for (const ef of e.Fields) {
|
|
1953
2041
|
if (UUIDsEqual(ef.RelatedEntityID, entity.ID) && ef.IsVirtual === false) {
|
|
1954
2042
|
const cascadeSql = await this.generateSingleCascadeOperation(entity, e, ef, pool);
|
|
@@ -2059,6 +2147,9 @@ export class SQLCodeGenBase {
|
|
|
2059
2147
|
const md = new Metadata(); // global-provider-ok: codegen runs offline against a single provider
|
|
2060
2148
|
// Find all fields in other entities that are foreign keys to this entity
|
|
2061
2149
|
for (const e of md.Entities) {
|
|
2150
|
+
if (!shouldEmitCascadeForRelatedEntity(entity.SchemaName, e.SchemaName, configInfo.allowCrossSchemaCascadeDeletes === true)) {
|
|
2151
|
+
continue;
|
|
2152
|
+
}
|
|
2062
2153
|
for (const ef of e.Fields) {
|
|
2063
2154
|
if (UUIDsEqual(ef.RelatedEntityID, entity.ID) && ef.IsVirtual === false) {
|
|
2064
2155
|
// Skip self-referential foreign keys (e.g., ParentID pointing to same entity)
|