flexdataset 0.4.1

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.
Files changed (39) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +30 -0
  3. package/dist/src/cli.d.ts +9 -0
  4. package/dist/src/cli.js +179 -0
  5. package/dist/src/diagram/dag.d.ts +16 -0
  6. package/dist/src/diagram/dag.js +58 -0
  7. package/dist/src/diagram/er.d.ts +16 -0
  8. package/dist/src/diagram/er.js +62 -0
  9. package/dist/src/diagram/render.d.ts +16 -0
  10. package/dist/src/diagram/render.js +24 -0
  11. package/dist/src/iceberg.d.ts +85 -0
  12. package/dist/src/iceberg.js +221 -0
  13. package/dist/src/index.d.ts +18 -0
  14. package/dist/src/index.js +56 -0
  15. package/dist/src/loader.d.ts +26 -0
  16. package/dist/src/loader.js +239 -0
  17. package/dist/src/model.d.ts +104 -0
  18. package/dist/src/model.js +26 -0
  19. package/dist/src/schema/schema.schema.json +27 -0
  20. package/dist/src/schema/table.schema.json +128 -0
  21. package/dist/src/structural.d.ts +31 -0
  22. package/dist/src/structural.js +54 -0
  23. package/dist/src/table-type.d.ts +115 -0
  24. package/dist/src/table-type.js +275 -0
  25. package/dist/src/table-types/hive-parquet.d.ts +29 -0
  26. package/dist/src/table-types/hive-parquet.js +70 -0
  27. package/dist/src/table-types/iceberg-parquet.d.ts +41 -0
  28. package/dist/src/table-types/iceberg-parquet.js +103 -0
  29. package/dist/src/table-types/postgres-18.d.ts +25 -0
  30. package/dist/src/table-types/postgres-18.js +44 -0
  31. package/dist/src/table-types/registry.d.ts +13 -0
  32. package/dist/src/table-types/registry.js +36 -0
  33. package/dist/src/types.d.ts +11 -0
  34. package/dist/src/types.js +182 -0
  35. package/dist/src/validate.d.ts +13 -0
  36. package/dist/src/validate.js +30 -0
  37. package/dist/src/world.d.ts +39 -0
  38. package/dist/src/world.js +82 -0
  39. package/package.json +69 -0
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ /**
3
+ * Layer 1 (structural) validation, backed by JSON Schema via ajv.
4
+ *
5
+ * The schema files in `./schema` are the portable artifact: any language can
6
+ * validate a file natively against them. This module is the TypeScript core's
7
+ * own use of those same schemas.
8
+ */
9
+ var __importDefault = (this && this.__importDefault) || function (mod) {
10
+ return (mod && mod.__esModule) ? mod : { "default": mod };
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.validateStructure = validateStructure;
14
+ const ajv_1 = __importDefault(require("ajv"));
15
+ const ajv_formats_1 = __importDefault(require("ajv-formats"));
16
+ const table_schema_json_1 = __importDefault(require("./schema/table.schema.json"));
17
+ const schema_schema_json_1 = __importDefault(require("./schema/schema.schema.json"));
18
+ const ajv = new ajv_1.default({
19
+ allErrors: true,
20
+ allowUnionTypes: true,
21
+ });
22
+ (0, ajv_formats_1.default)(ajv);
23
+ const validators = {
24
+ table: ajv.compile(table_schema_json_1.default),
25
+ schema: ajv.compile(schema_schema_json_1.default),
26
+ };
27
+ /**
28
+ * Validate parsed JSON against a structural schema.
29
+ *
30
+ * @param kind Which schema to use.
31
+ * @param data Parsed JSON content.
32
+ * @returns Whether it is valid plus any structural errors.
33
+ */
34
+ function validateStructure(kind, data) {
35
+ const validate = validators[kind];
36
+ const valid = validate(data);
37
+ if (valid) {
38
+ return {
39
+ valid: true,
40
+ errors: [],
41
+ };
42
+ }
43
+ /* istanbul ignore next: ajv always populates `errors` when validation fails */
44
+ const rawErrors = validate.errors ?? [];
45
+ const errors = rawErrors.map((error) => ({
46
+ field: error.instancePath,
47
+ message: `${error.instancePath || '(root)'} ${error.message}`.trim(),
48
+ }));
49
+ return {
50
+ valid: false,
51
+ errors,
52
+ };
53
+ }
54
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RydWN0dXJhbC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9zdHJ1Y3R1cmFsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7O0FBaURILDhDQXFCQztBQXBFRCw4Q0FFYTtBQUNiLDhEQUFxQztBQUVyQyxtRkFBcUQ7QUFDckQscUZBQXVEO0FBdUJ2RCxNQUFNLEdBQUcsR0FBRyxJQUFJLGFBQUcsQ0FBQztJQUNoQixTQUFTLEVBQUUsSUFBSTtJQUNmLGVBQWUsRUFBRSxJQUFJO0NBQ3hCLENBQUMsQ0FBQztBQUNILElBQUEscUJBQVUsRUFBQyxHQUFHLENBQUMsQ0FBQztBQUVoQixNQUFNLFVBQVUsR0FBNkM7SUFDekQsS0FBSyxFQUFFLEdBQUcsQ0FBQyxPQUFPLENBQUMsMkJBQVcsQ0FBQztJQUMvQixNQUFNLEVBQUUsR0FBRyxDQUFDLE9BQU8sQ0FBQyw0QkFBWSxDQUFDO0NBQ3BDLENBQUM7QUFFRjs7Ozs7O0dBTUc7QUFDSCxTQUFnQixpQkFBaUIsQ0FBQyxJQUFvQixFQUFFLElBQWE7SUFDakUsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sS0FBSyxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQVksQ0FBQztJQUN4QyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ1IsT0FBTztZQUNILEtBQUssRUFBRSxJQUFJO1lBQ1gsTUFBTSxFQUFFLEVBQUU7U0FDYixDQUFDO0lBQ04sQ0FBQztJQUVELCtFQUErRTtJQUMvRSxNQUFNLFNBQVMsR0FBRyxRQUFRLENBQUMsTUFBTSxJQUFJLEVBQUUsQ0FBQztJQUN4QyxNQUFNLE1BQU0sR0FBc0IsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsQ0FBQztRQUN4RCxLQUFLLEVBQUUsS0FBSyxDQUFDLFlBQVk7UUFDekIsT0FBTyxFQUFFLEdBQUcsS0FBSyxDQUFDLFlBQVksSUFBSSxRQUFRLElBQUksS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDLElBQUksRUFBRTtLQUN2RSxDQUFDLENBQUMsQ0FBQztJQUVKLE9BQU87UUFDSCxLQUFLLEVBQUUsS0FBSztRQUNaLE1BQU07S0FDVCxDQUFDO0FBQ04sQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGF5ZXIgMSAoc3RydWN0dXJhbCkgdmFsaWRhdGlvbiwgYmFja2VkIGJ5IEpTT04gU2NoZW1hIHZpYSBhanYuXG4gKlxuICogVGhlIHNjaGVtYSBmaWxlcyBpbiBgLi9zY2hlbWFgIGFyZSB0aGUgcG9ydGFibGUgYXJ0aWZhY3Q6IGFueSBsYW5ndWFnZSBjYW5cbiAqIHZhbGlkYXRlIGEgZmlsZSBuYXRpdmVseSBhZ2FpbnN0IHRoZW0uIFRoaXMgbW9kdWxlIGlzIHRoZSBUeXBlU2NyaXB0IGNvcmUnc1xuICogb3duIHVzZSBvZiB0aG9zZSBzYW1lIHNjaGVtYXMuXG4gKi9cblxuaW1wb3J0IEFqdiwge1xuICAgIFZhbGlkYXRlRnVuY3Rpb24sIFxufSBmcm9tICdhanYnO1xuaW1wb3J0IGFkZEZvcm1hdHMgZnJvbSAnYWp2LWZvcm1hdHMnO1xuXG5pbXBvcnQgdGFibGVTY2hlbWEgZnJvbSAnLi9zY2hlbWEvdGFibGUuc2NoZW1hLmpzb24nO1xuaW1wb3J0IHNjaGVtYVNjaGVtYSBmcm9tICcuL3NjaGVtYS9zY2hlbWEuc2NoZW1hLmpzb24nO1xuXG4vKiogV2hpY2ggc3RydWN0dXJhbCBzY2hlbWEgdG8gdmFsaWRhdGUgYWdhaW5zdC4gKi9cbmV4cG9ydCB0eXBlIFN0cnVjdHVyYWxLaW5kID0gJ3RhYmxlJyB8ICdzY2hlbWEnO1xuXG4vKiogQSBzaW5nbGUgc3RydWN0dXJhbCBlcnJvciwgYmVmb3JlIGZpbGUgY29udGV4dCBpcyBhdHRhY2hlZC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RydWN0dXJhbEVycm9yIHtcbiAgICAvKiogSlNPTiBwb2ludGVyIHRvIHRoZSBvZmZlbmRpbmcgZmllbGQgKGVtcHR5IHN0cmluZyBmb3IgdGhlIHJvb3QpLiAqL1xuICAgIHJlYWRvbmx5IGZpZWxkOiBzdHJpbmc7XG5cbiAgICAvKiogSHVtYW4tcmVhZGFibGUgZGVzY3JpcHRpb24uICovXG4gICAgcmVhZG9ubHkgbWVzc2FnZTogc3RyaW5nO1xufVxuXG4vKiogT3V0Y29tZSBvZiB2YWxpZGF0aW5nIG9uZSBmaWxlIHN0cnVjdHVyYWxseS4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3RydWN0dXJhbFJlc3VsdCB7XG4gICAgLyoqIFRydWUgd2hlbiB0aGUgZmlsZSBtYXRjaGVzIGl0cyBzdHJ1Y3R1cmFsIHNjaGVtYS4gKi9cbiAgICByZWFkb25seSB2YWxpZDogYm9vbGVhbjtcblxuICAgIC8qKiBFcnJvcnMgZm91bmQgKGVtcHR5IHdoZW4gdmFsaWQpLiAqL1xuICAgIHJlYWRvbmx5IGVycm9yczogU3RydWN0dXJhbEVycm9yW107XG59XG5cbmNvbnN0IGFqdiA9IG5ldyBBanYoe1xuICAgIGFsbEVycm9yczogdHJ1ZSxcbiAgICBhbGxvd1VuaW9uVHlwZXM6IHRydWUsXG59KTtcbmFkZEZvcm1hdHMoYWp2KTtcblxuY29uc3QgdmFsaWRhdG9yczogUmVjb3JkPFN0cnVjdHVyYWxLaW5kLCBWYWxpZGF0ZUZ1bmN0aW9uPiA9IHtcbiAgICB0YWJsZTogYWp2LmNvbXBpbGUodGFibGVTY2hlbWEpLFxuICAgIHNjaGVtYTogYWp2LmNvbXBpbGUoc2NoZW1hU2NoZW1hKSxcbn07XG5cbi8qKlxuICogVmFsaWRhdGUgcGFyc2VkIEpTT04gYWdhaW5zdCBhIHN0cnVjdHVyYWwgc2NoZW1hLlxuICpcbiAqIEBwYXJhbSBraW5kIFdoaWNoIHNjaGVtYSB0byB1c2UuXG4gKiBAcGFyYW0gZGF0YSBQYXJzZWQgSlNPTiBjb250ZW50LlxuICogQHJldHVybnMgV2hldGhlciBpdCBpcyB2YWxpZCBwbHVzIGFueSBzdHJ1Y3R1cmFsIGVycm9ycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZhbGlkYXRlU3RydWN0dXJlKGtpbmQ6IFN0cnVjdHVyYWxLaW5kLCBkYXRhOiB1bmtub3duKTogU3RydWN0dXJhbFJlc3VsdCB7XG4gICAgY29uc3QgdmFsaWRhdGUgPSB2YWxpZGF0b3JzW2tpbmRdO1xuICAgIGNvbnN0IHZhbGlkID0gdmFsaWRhdGUoZGF0YSkgYXMgYm9vbGVhbjtcbiAgICBpZiAodmFsaWQpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIHZhbGlkOiB0cnVlLFxuICAgICAgICAgICAgZXJyb3JzOiBbXSxcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKiBpc3RhbmJ1bCBpZ25vcmUgbmV4dDogYWp2IGFsd2F5cyBwb3B1bGF0ZXMgYGVycm9yc2Agd2hlbiB2YWxpZGF0aW9uIGZhaWxzICovXG4gICAgY29uc3QgcmF3RXJyb3JzID0gdmFsaWRhdGUuZXJyb3JzID8/IFtdO1xuICAgIGNvbnN0IGVycm9yczogU3RydWN0dXJhbEVycm9yW10gPSByYXdFcnJvcnMubWFwKChlcnJvcikgPT4gKHtcbiAgICAgICAgZmllbGQ6IGVycm9yLmluc3RhbmNlUGF0aCxcbiAgICAgICAgbWVzc2FnZTogYCR7ZXJyb3IuaW5zdGFuY2VQYXRoIHx8ICcocm9vdCknfSAke2Vycm9yLm1lc3NhZ2V9YC50cmltKCksXG4gICAgfSkpO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgICAgdmFsaWQ6IGZhbHNlLFxuICAgICAgICBlcnJvcnMsXG4gICAgfTtcbn1cbiJdfQ==
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Abstract base class for a loaded table. One subclass per engine.
3
+ *
4
+ * Holds the normalized table identity and definition, plus the
5
+ * engine-agnostic Layer 2 rules as concrete methods. Engine-specific rules
6
+ * (column-type validity, partition semantics) are abstract — each subclass
7
+ * implements them, which is the lever that lets new engines plug in without
8
+ * editing scattered switches. The cross-file rules are concrete here too;
9
+ * they take the world by an interface so the cycle between this module and
10
+ * `./world` is kept at type-level only.
11
+ */
12
+ import { TableDefinition, Violation } from './model';
13
+ import type { World } from './world';
14
+ /** Fields required to construct any concrete table subclass. */
15
+ export interface TableTypeFields {
16
+ /** Owning schema name (the folder name). */
17
+ readonly schema: string;
18
+ /** Table name (the file name without `.json`). */
19
+ readonly name: string;
20
+ /** `schema.table` identifier. */
21
+ readonly qualifiedName: string;
22
+ /** Absolute path to the source file. */
23
+ readonly filePath: string;
24
+ /** Whether the file passed Layer 1 structural validation. */
25
+ readonly structurallyValid: boolean;
26
+ /** Normalized definition. */
27
+ readonly definition: TableDefinition;
28
+ }
29
+ /**
30
+ * Base class for all engine-specific table types.
31
+ *
32
+ * Subclasses implement `isValidColumnType` (the engine's type registry) and
33
+ * `partitionViolations` (the engine's partition semantics). Everything else
34
+ * — primary-key checks, dupes, raw consistency, depends-on resolution,
35
+ * foreign-key checks — is identical across engines and lives here.
36
+ */
37
+ export declare abstract class TableTypeBase {
38
+ /** Owning schema name. */
39
+ readonly schema: string;
40
+ /** Table name. */
41
+ readonly name: string;
42
+ /** `schema.table` identifier. */
43
+ readonly qualifiedName: string;
44
+ /** Absolute path to the source file. */
45
+ readonly filePath: string;
46
+ /** Whether the file passed Layer 1 structural validation. */
47
+ readonly structurallyValid: boolean;
48
+ /** Normalized definition. */
49
+ readonly definition: TableDefinition;
50
+ /**
51
+ * Construct a table instance from the normalized fields produced by the
52
+ * loader.
53
+ *
54
+ * @param fields The table identity plus its parsed, normalized definition.
55
+ */
56
+ constructor(fields: TableTypeFields);
57
+ /**
58
+ * Build a violation pre-filled with this table's location fields.
59
+ *
60
+ * @param partial The fields specific to the rule firing (code, level, message, field).
61
+ * @returns A full `Violation` with `schema`, `table`, and `path` set.
62
+ */
63
+ protected violation(partial: Omit<Violation, 'schema' | 'table' | 'path'>): Violation;
64
+ /**
65
+ * Whether this table declares a data column with the given name.
66
+ *
67
+ * @param name Column name to look up.
68
+ * @returns True when `name` matches any column in `definition.columns`.
69
+ */
70
+ protected hasColumn(name: string): boolean;
71
+ /**
72
+ * Find names that appear more than once in a list, preserving the order
73
+ * of first duplication.
74
+ *
75
+ * @param names Names to scan.
76
+ * @returns Duplicated names, each listed once.
77
+ */
78
+ protected findDuplicates(names: string[]): string[];
79
+ /**
80
+ * Whether `type` is a valid column-type string for this engine.
81
+ *
82
+ * @param type Column type string to check.
83
+ * @returns True when the engine accepts the type.
84
+ */
85
+ abstract isValidColumnType(type: string): boolean;
86
+ /**
87
+ * Engine-specific partition rules: duplicate detection, type/transform
88
+ * legality, and the "no partitions allowed" rule for engines that don't
89
+ * support them.
90
+ *
91
+ * @returns Every partition-related violation this table produces.
92
+ */
93
+ abstract partitionViolations(): Violation[];
94
+ private primaryKeyViolations;
95
+ private duplicateColumnViolations;
96
+ private columnTypeViolations;
97
+ private rawConsistencyViolations;
98
+ /**
99
+ * All intra-table violations for this table (engine-agnostic rules plus
100
+ * the engine-specific partition rules).
101
+ *
102
+ * @returns Every intra-table violation this table produces.
103
+ */
104
+ intraTableViolations(): Violation[];
105
+ private dependsOnViolations;
106
+ private foreignKeyViolations;
107
+ /**
108
+ * All cross-file violations for this table (`dependsOn` resolution plus
109
+ * the full foreign-key suite).
110
+ *
111
+ * @param world The loaded dataset root.
112
+ * @returns Every cross-file violation this table produces.
113
+ */
114
+ crossFileViolations(world: World): Violation[];
115
+ }
@@ -0,0 +1,275 @@
1
+ "use strict";
2
+ /**
3
+ * Abstract base class for a loaded table. One subclass per engine.
4
+ *
5
+ * Holds the normalized table identity and definition, plus the
6
+ * engine-agnostic Layer 2 rules as concrete methods. Engine-specific rules
7
+ * (column-type validity, partition semantics) are abstract — each subclass
8
+ * implements them, which is the lever that lets new engines plug in without
9
+ * editing scattered switches. The cross-file rules are concrete here too;
10
+ * they take the world by an interface so the cycle between this module and
11
+ * `./world` is kept at type-level only.
12
+ */
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.TableTypeBase = void 0;
15
+ /**
16
+ * Base class for all engine-specific table types.
17
+ *
18
+ * Subclasses implement `isValidColumnType` (the engine's type registry) and
19
+ * `partitionViolations` (the engine's partition semantics). Everything else
20
+ * — primary-key checks, dupes, raw consistency, depends-on resolution,
21
+ * foreign-key checks — is identical across engines and lives here.
22
+ */
23
+ class TableTypeBase {
24
+ /** Owning schema name. */
25
+ schema;
26
+ /** Table name. */
27
+ name;
28
+ /** `schema.table` identifier. */
29
+ qualifiedName;
30
+ /** Absolute path to the source file. */
31
+ filePath;
32
+ /** Whether the file passed Layer 1 structural validation. */
33
+ structurallyValid;
34
+ /** Normalized definition. */
35
+ definition;
36
+ /**
37
+ * Construct a table instance from the normalized fields produced by the
38
+ * loader.
39
+ *
40
+ * @param fields The table identity plus its parsed, normalized definition.
41
+ */
42
+ constructor(fields) {
43
+ this.schema = fields.schema;
44
+ this.name = fields.name;
45
+ this.qualifiedName = fields.qualifiedName;
46
+ this.filePath = fields.filePath;
47
+ this.structurallyValid = fields.structurallyValid;
48
+ this.definition = fields.definition;
49
+ }
50
+ /// ////////////////////////////////////////////////////////////////////////
51
+ // Helpers shared by intra-table and cross-file rules.
52
+ /**
53
+ * Build a violation pre-filled with this table's location fields.
54
+ *
55
+ * @param partial The fields specific to the rule firing (code, level, message, field).
56
+ * @returns A full `Violation` with `schema`, `table`, and `path` set.
57
+ */
58
+ violation(partial) {
59
+ const location = {
60
+ schema: this.schema,
61
+ table: this.name,
62
+ path: this.filePath,
63
+ };
64
+ return {
65
+ ...partial,
66
+ ...location,
67
+ };
68
+ }
69
+ /**
70
+ * Whether this table declares a data column with the given name.
71
+ *
72
+ * @param name Column name to look up.
73
+ * @returns True when `name` matches any column in `definition.columns`.
74
+ */
75
+ hasColumn(name) {
76
+ return this.definition.columns.some((column) => column.name === name);
77
+ }
78
+ /**
79
+ * Find names that appear more than once in a list, preserving the order
80
+ * of first duplication.
81
+ *
82
+ * @param names Names to scan.
83
+ * @returns Duplicated names, each listed once.
84
+ */
85
+ findDuplicates(names) {
86
+ const seen = new Set();
87
+ const duplicates = new Set();
88
+ for (const name of names) {
89
+ if (seen.has(name)) {
90
+ duplicates.add(name);
91
+ }
92
+ seen.add(name);
93
+ }
94
+ return [
95
+ ...duplicates,
96
+ ];
97
+ }
98
+ /// ////////////////////////////////////////////////////////////////////////
99
+ // Agnostic intra-table rules.
100
+ /// PK_COLUMNS_EXIST — every primary-key column exists in `columns`.
101
+ primaryKeyViolations() {
102
+ const violations = [];
103
+ for (const pkColumn of this.definition.primaryKey) {
104
+ if (!this.hasColumn(pkColumn)) {
105
+ violations.push(this.violation({
106
+ level: 'error',
107
+ code: 'PK_COLUMNS_EXIST',
108
+ field: 'primaryKey',
109
+ message: `primary-key column "${pkColumn}" is not defined in columns`,
110
+ }));
111
+ }
112
+ }
113
+ return violations;
114
+ }
115
+ /// NO_DUPLICATE_COLUMNS — column names are unique within a table.
116
+ duplicateColumnViolations() {
117
+ const names = this.definition.columns.map((column) => column.name);
118
+ return this.findDuplicates(names).map((duplicate) => this.violation({
119
+ level: 'error',
120
+ code: 'NO_DUPLICATE_COLUMNS',
121
+ field: 'columns',
122
+ message: `duplicate column name "${duplicate}"`,
123
+ }));
124
+ }
125
+ /// COLUMN_TYPE_VALID — every column type is valid for the table's engine.
126
+ columnTypeViolations() {
127
+ const violations = [];
128
+ this.definition.columns.forEach((column, index) => {
129
+ if (!this.isValidColumnType(column.type)) {
130
+ violations.push(this.violation({
131
+ level: 'error',
132
+ code: 'COLUMN_TYPE_VALID',
133
+ field: `columns[${index}].type`,
134
+ message: `"${column.type}" is not a valid ${this.definition.tableType} type `
135
+ + `for column "${column.name}"`,
136
+ }));
137
+ }
138
+ });
139
+ return violations;
140
+ }
141
+ /// RAW_NO_DEPENDS_ON / NONRAW_REQUIRES_DEPENDS_ON.
142
+ rawConsistencyViolations() {
143
+ const violations = [];
144
+ const { isRawData, dependsOn, } = this.definition;
145
+ if (isRawData && dependsOn.length > 0) {
146
+ violations.push(this.violation({
147
+ level: 'error',
148
+ code: 'RAW_NO_DEPENDS_ON',
149
+ field: 'dependsOn',
150
+ message: 'raw tables (isRawData=true) must not declare dependsOn',
151
+ }));
152
+ }
153
+ if (!isRawData && dependsOn.length === 0) {
154
+ violations.push(this.violation({
155
+ level: 'error',
156
+ code: 'NONRAW_REQUIRES_DEPENDS_ON',
157
+ field: 'dependsOn',
158
+ message: 'non-raw tables (isRawData=false) must declare at least one dependsOn',
159
+ }));
160
+ }
161
+ return violations;
162
+ }
163
+ /**
164
+ * All intra-table violations for this table (engine-agnostic rules plus
165
+ * the engine-specific partition rules).
166
+ *
167
+ * @returns Every intra-table violation this table produces.
168
+ */
169
+ intraTableViolations() {
170
+ return [
171
+ ...this.primaryKeyViolations(),
172
+ ...this.duplicateColumnViolations(),
173
+ ...this.columnTypeViolations(),
174
+ ...this.partitionViolations(),
175
+ ...this.rawConsistencyViolations(),
176
+ ];
177
+ }
178
+ /// ////////////////////////////////////////////////////////////////////////
179
+ // Cross-file rules.
180
+ /// DEPENDS_ON_RESOLVES — every dependsOn entry resolves to a real table.
181
+ dependsOnViolations(world) {
182
+ const violations = [];
183
+ this.definition.dependsOn.forEach((dependency, index) => {
184
+ if (!world.tables.has(dependency)) {
185
+ violations.push(this.violation({
186
+ level: 'error',
187
+ code: 'DEPENDS_ON_RESOLVES',
188
+ field: `dependsOn[${index}]`,
189
+ message: `dependsOn "${dependency}" does not resolve to a known table`,
190
+ }));
191
+ }
192
+ });
193
+ return violations;
194
+ }
195
+ /// Foreign-key checks for a single FK entry.
196
+ foreignKeyViolations(world, fk, index) {
197
+ const violations = [];
198
+ const field = `foreignKeys[${index}]`;
199
+ if (!this.hasColumn(fk.localColumn)) {
200
+ violations.push(this.violation({
201
+ level: 'error',
202
+ code: 'FK_LOCAL_COLUMN_EXISTS',
203
+ field: `${field}.localColumn`,
204
+ message: `local column "${fk.localColumn}" is not defined in columns`,
205
+ }));
206
+ }
207
+ /// A self-referential foreign key (e.g. a `parent_id` pointing at the same
208
+ /// table's key) does not create a pipeline dependency, so it is exempt from
209
+ /// FK_IMPLIES_DEPENDENCY — requiring a self-`dependsOn` would otherwise force
210
+ /// a spurious dependency cycle.
211
+ const isSelfReference = fk.sourceTable === this.qualifiedName;
212
+ if (!isSelfReference && !this.definition.dependsOn.includes(fk.sourceTable)) {
213
+ violations.push(this.violation({
214
+ level: 'error',
215
+ code: 'FK_IMPLIES_DEPENDENCY',
216
+ field: `${field}.sourceTable`,
217
+ message: `foreign key targets "${fk.sourceTable}" but it is not listed in dependsOn`,
218
+ }));
219
+ }
220
+ const target = world.tables.get(fk.sourceTable);
221
+ if (target === undefined) {
222
+ violations.push(this.violation({
223
+ level: 'error',
224
+ code: 'FK_SOURCE_TABLE_RESOLVES',
225
+ field: `${field}.sourceTable`,
226
+ message: `foreign key source table "${fk.sourceTable}" does not resolve to a known table`,
227
+ }));
228
+ return violations;
229
+ }
230
+ /// The target's own structural errors (reported by Layer 1) already explain
231
+ /// why its columns can't be trusted; skip column-level checks to avoid
232
+ /// piling misleading findings on top.
233
+ if (!target.structurallyValid) {
234
+ return violations;
235
+ }
236
+ const targetHasColumn = target.definition.columns.some((column) => column.name === fk.sourceColumn);
237
+ if (!targetHasColumn) {
238
+ violations.push(this.violation({
239
+ level: 'error',
240
+ code: 'FK_SOURCE_COLUMN_EXISTS',
241
+ field: `${field}.sourceColumn`,
242
+ message: `foreign key source column "${fk.sourceColumn}" is not defined in "${fk.sourceTable}"`,
243
+ }));
244
+ return violations;
245
+ }
246
+ if (!target.definition.primaryKey.includes(fk.sourceColumn)) {
247
+ violations.push(this.violation({
248
+ level: 'warning',
249
+ code: 'FK_SOURCE_IS_KEY',
250
+ field: `${field}.sourceColumn`,
251
+ message: `foreign key source column "${fk.sourceColumn}" is not part of the primary key `
252
+ + `of "${fk.sourceTable}"`,
253
+ }));
254
+ }
255
+ return violations;
256
+ }
257
+ /**
258
+ * All cross-file violations for this table (`dependsOn` resolution plus
259
+ * the full foreign-key suite).
260
+ *
261
+ * @param world The loaded dataset root.
262
+ * @returns Every cross-file violation this table produces.
263
+ */
264
+ crossFileViolations(world) {
265
+ const violations = [
266
+ ...this.dependsOnViolations(world),
267
+ ];
268
+ this.definition.foreignKeys.forEach((fk, index) => {
269
+ violations.push(...this.foreignKeyViolations(world, fk, index));
270
+ });
271
+ return violations;
272
+ }
273
+ }
274
+ exports.TableTypeBase = TableTypeBase;
275
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUtdHlwZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90YWJsZS10eXBlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7Ozs7OztHQVVHOzs7QUFtQ0g7Ozs7Ozs7R0FPRztBQUNILE1BQXNCLGFBQWE7SUFDL0IsMEJBQTBCO0lBQ1YsTUFBTSxDQUFTO0lBRS9CLGtCQUFrQjtJQUNGLElBQUksQ0FBUztJQUU3QixpQ0FBaUM7SUFDakIsYUFBYSxDQUFTO0lBRXRDLHdDQUF3QztJQUN4QixRQUFRLENBQVM7SUFFakMsNkRBQTZEO0lBQzdDLGlCQUFpQixDQUFVO0lBRTNDLDZCQUE2QjtJQUNiLFVBQVUsQ0FBa0I7SUFFNUM7Ozs7O09BS0c7SUFDSCxZQUFZLE1BQXVCO1FBQy9CLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztRQUM1QixJQUFJLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7UUFDeEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxDQUFDO1FBQzFDLElBQUksQ0FBQyxRQUFRLEdBQUcsTUFBTSxDQUFDLFFBQVEsQ0FBQztRQUNoQyxJQUFJLENBQUMsaUJBQWlCLEdBQUcsTUFBTSxDQUFDLGlCQUFpQixDQUFDO1FBQ2xELElBQUksQ0FBQyxVQUFVLEdBQUcsTUFBTSxDQUFDLFVBQVUsQ0FBQztJQUN4QyxDQUFDO0lBRUQsNEVBQTRFO0lBQzVFLHNEQUFzRDtJQUV0RDs7Ozs7T0FLRztJQUNPLFNBQVMsQ0FBQyxPQUFxRDtRQUNyRSxNQUFNLFFBQVEsR0FBbUI7WUFDN0IsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLEtBQUssRUFBRSxJQUFJLENBQUMsSUFBSTtZQUNoQixJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVE7U0FDdEIsQ0FBQztRQUNGLE9BQU87WUFDSCxHQUFHLE9BQU87WUFDVixHQUFHLFFBQVE7U0FDZCxDQUFD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QyxDQUFDLENBQUM7UUFDcEUsQ0FBQyxDQUFDLENBQUM7UUFDSCxPQUFPLFVBQVUsQ0FBQztJQUN0QixDQUFDO0NBQ0o7QUE1U0Qsc0NBNFNDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBBYnN0cmFjdCBiYXNlIGNsYXNzIGZvciBhIGxvYWRlZCB0YWJsZS4gT25lIHN1YmNsYXNzIHBlciBlbmdpbmUuXG4gKlxuICogSG9sZHMgdGhlIG5vcm1hbGl6ZWQgdGFibGUgaWRlbnRpdHkgYW5kIGRlZmluaXRpb24sIHBsdXMgdGhlXG4gKiBlbmdpbmUtYWdub3N0aWMgTGF5ZXIgMiBydWxlcyBhcyBjb25jcmV0ZSBtZXRob2RzLiBFbmdpbmUtc3BlY2lmaWMgcnVsZXNcbiAqIChjb2x1bW4tdHlwZSB2YWxpZGl0eSwgcGFydGl0aW9uIHNlbWFudGljcykgYXJlIGFic3RyYWN0IOKAlCBlYWNoIHN1YmNsYXNzXG4gKiBpbXBsZW1lbnRzIHRoZW0sIHdoaWNoIGlzIHRoZSBsZXZlciB0aGF0IGxldHMgbmV3IGVuZ2luZXMgcGx1ZyBpbiB3aXRob3V0XG4gKiBlZGl0aW5nIHNjYXR0ZXJlZCBzd2l0Y2hlcy4gVGhlIGNyb3NzLWZpbGUgcnVsZXMgYXJlIGNvbmNyZXRlIGhlcmUgdG9vO1xuICogdGhleSB0YWtlIHRoZSB3b3JsZCBieSBhbiBpbnRlcmZhY2Ugc28gdGhlIGN5Y2xlIGJldHdlZW4gdGhpcyBtb2R1bGUgYW5kXG4gKiBgLi93b3JsZGAgaXMga2VwdCBhdCB0eXBlLWxldmVsIG9ubHkuXG4gKi9cblxuaW1wb3J0IHtcbiAgICBGb3JlaWduS2V5LFxuICAgIFRhYmxlRGVmaW5pdGlvbixcbiAgICBWaW9sYXRpb24sXG59IGZyb20gJy4vbW9kZWwnO1xuaW1wb3J0IHR5cGUge1xuICAgIFdvcmxkLFxufSBmcm9tICcuL3dvcmxkJztcblxuLyoqIEZpZWxkcyByZXF1aXJlZCB0byBjb25zdHJ1Y3QgYW55IGNvbmNyZXRlIHRhYmxlIHN1YmNsYXNzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUYWJsZVR5cGVGaWVsZHMge1xuICAgIC8qKiBPd25pbmcgc2NoZW1hIG5hbWUgKHRoZSBmb2xkZXIgbmFtZSkuICovXG4gICAgcmVhZG9ubHkgc2NoZW1hOiBzdHJpbmc7XG5cbiAgICAvKiogVGFibGUgbmFtZSAodGhlIGZpbGUgbmFtZSB3aXRob3V0IGAuanNvbmApLiAqL1xuICAgIHJlYWRvbmx5IG5hbWU6IHN0cmluZztcblxuICAgIC8qKiBgc2NoZW1hLnRhYmxlYCBpZGVudGlmaWVyLiAqL1xuICAgIHJlYWRvbmx5IHF1YWxpZmllZE5hbWU6IHN0cmluZztcblxuICAgIC8qKiBBYnNvbHV0ZSBwYXRoIHRvIHRoZSBzb3VyY2UgZmlsZS4gKi9cbiAgICByZWFkb25seSBmaWxlUGF0aDogc3RyaW5nO1xuXG4gICAgLyoqIFdoZXRoZXIgdGhlIGZpbGUgcGFzc2VkIExheWVyIDEgc3RydWN0dXJhbCB2YWxpZGF0aW9uLiAqL1xuICAgIHJlYWRvbmx5IHN0cnVjdHVyYWxseVZhbGlkOiBib29sZWFuO1xuXG4gICAgLyoqIE5vcm1hbGl6ZWQgZGVmaW5pdGlvbi4gKi9cbiAgICByZWFkb25seSBkZWZpbml0aW9uOiBUYWJsZURlZmluaXRpb247XG59XG5cbi8qKiBQcmUtZmlsbGVkIGxvY2F0aW9uIGZpZWxkcyBhdHRhY2hlZCB0byBldmVyeSB2aW9sYXRpb24gYSB0YWJsZSBlbWl0cy4gKi9cbnR5cGUgTG9jYXRpb25GaWVsZHMgPSBQaWNrPFZpb2xhdGlvbiwgJ3NjaGVtYScgfCAndGFibGUnIHwgJ3BhdGgnPjtcblxuLyoqXG4gKiBCYXNlIGNsYXNzIGZvciBhbGwgZW5naW5lLXNwZWNpZmljIHRhYmxlIHR5cGVzLlxuICpcbiAqIFN1YmNsYXNzZXMgaW1wbGVtZW50IGBpc1ZhbGlkQ29sdW1uVHlwZWAgKHRoZSBlbmdpbmUncyB0eXBlIHJlZ2lzdHJ5KSBhbmRcbiAqIGBwYXJ0aXRpb25WaW9sYXRpb25zYCAodGhlIGVuZ2luZSdzIHBhcnRpdGlvbiBzZW1hbnRpY3MpLiBFdmVyeXRoaW5nIGVsc2VcbiAqIOKAlCBwcmltYXJ5LWtleSBjaGVja3MsIGR1cGVzLCByYXcgY29uc2lzdGVuY3ksIGRlcGVuZHMtb24gcmVzb2x1dGlvbixcbiAqIGZvcmVpZ24ta2V5IGNoZWNrcyDigJQgaXMgaWRlbnRpY2FsIGFjcm9zcyBlbmdpbmVzIGFuZCBsaXZlcyBoZXJlLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVGFibGVUeXBlQmFzZSB7XG4gICAgLyoqIE93bmluZyBzY2hlbWEgbmFtZS4gKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgc2NoZW1hOiBzdHJpbmc7XG5cbiAgICAvKiogVGFibGUgbmFtZS4gKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZTogc3RyaW5nO1xuXG4gICAgLyoqIGBzY2hlbWEudGFibGVgIGlkZW50aWZpZXIuICovXG4gICAgcHVibGljIHJlYWRvbmx5IHF1YWxpZmllZE5hbWU6IHN0cmluZztcblxuICAgIC8qKiBBYnNvbHV0ZSBwYXRoIHRvIHRoZSBzb3VyY2UgZmlsZS4gKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgZmlsZVBhdGg6IHN0cmluZztcblxuICAgIC8qKiBXaGV0aGVyIHRoZSBmaWxlIHBhc3NlZCBMYXllciAxIHN0cnVjdHVyYWwgdmFsaWRhdGlvbi4gKi9cbiAgICBwdWJsaWMgcmVhZG9ubHkgc3RydWN0dXJhbGx5VmFsaWQ6IGJvb2xlYW47XG5cbiAgICAvKiogTm9ybWFsaXplZCBkZWZpbml0aW9uLiAqL1xuICAgIHB1YmxpYyByZWFkb25seSBkZWZpbml0aW9uOiBUYWJsZURlZmluaXRpb247XG5cbiAgICAvKipcbiAgICAgKiBDb25zdHJ1Y3QgYSB0YWJsZSBpbnN0YW5jZSBmcm9tIHRoZSBub3JtYWxpemVkIGZpZWxkcyBwcm9kdWNlZCBieSB0aGVcbiAgICAgKiBsb2FkZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmllbGRzIFRoZSB0YWJsZSBpZGVudGl0eSBwbHVzIGl0cyBwYXJzZWQsIG5vcm1hbGl6ZWQgZGVmaW5pdGlvbi5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihmaWVsZHM6IFRhYmxlVHlwZUZpZWxkcykge1xuICAgICAgICB0aGlzLnNjaGVtYSA9IGZpZWxkcy5zY2hlbWE7XG4gICAgICAgIHRoaXMubmFtZSA9IGZpZWxkcy5uYW1lO1xuICAgICAgICB0aGlzLnF1YWxpZmllZE5hbWUgPSBmaWVsZHMucXVhbGlmaWVkTmFtZTtcbiAgICAgICAgdGhpcy5maWxlUGF0aCA9IGZpZWxkcy5maWxlUGF0aDtcbiAgICAgICAgdGhpcy5zdHJ1Y3R1cmFsbHlWYWxpZCA9IGZpZWxkcy5zdHJ1Y3R1cmFsbHlWYWxpZDtcbiAgICAgICAgdGhpcy5kZWZpbml0aW9uID0gZmllbGRzLmRlZmluaXRpb247XG4gICAgfVxuXG4gICAgLy8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIEhlbHBlcnMgc2hhcmVkIGJ5IGludHJhLXRhYmxlIGFuZCBjcm9zcy1maWxlIHJ1bGVzLlxuXG4gICAgLyoqXG4gICAgICogQnVpbGQgYSB2aW9sYXRpb24gcHJlLWZpbGxlZCB3aXRoIHRoaXMgdGFibGUncyBsb2NhdGlvbiBmaWVsZHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcGFydGlhbCBUaGUgZmllbGRzIHNwZWNpZmljIHRvIHRoZSBydWxlIGZpcmluZyAoY29kZSwgbGV2ZWwsIG1lc3NhZ2UsIGZpZWxkKS5cbiAgICAgKiBAcmV0dXJucyBBIGZ1bGwgYFZpb2xhdGlvbmAgd2l0aCBgc2NoZW1hYCwgYHRhYmxlYCwgYW5kIGBwYXRoYCBzZXQuXG4gICAgICovXG4gICAgcHJvdGVjdGVkIHZpb2xhdGlvbihwYXJ0aWFsOiBPbWl0PFZpb2xhdGlvbiwgJ3NjaGVtYScgfCAndGFibGUnIHwgJ3BhdGgnPik6IFZpb2xhdGlvbiB7XG4gICAgICAgIGNvbnN0IGxvY2F0aW9uOiBMb2NhdGlvbkZpZWxkcyA9IHtcbiAgICAgICAgICAgIHNjaGVtYTogdGhpcy5zY2hlbWEsXG4gICAgICAgICAgICB0YWJsZTogdGhpcy5uYW1lLFxuICAgICAgICAgICAgcGF0aDogdGhpcy5maWxlUGF0aCxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC4uLnBhcnRpYWwsXG4gICAgICAgICAgICAuLi5sb2NhdGlvbixcbiAgICAgICAgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGV0aGVyIHRoaXMgdGFibGUgZGVjbGFyZXMgYSBkYXRhIGNvbHVtbiB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuICAgICAqXG4gICAgICogQHBhcmFtIG5hbWUgQ29sdW1uIG5hbWUgdG8gbG9vayB1cC5cbiAgICAgKiBAcmV0dXJucyBUcnVlIHdoZW4gYG5hbWVgIG1hdGNoZXMgYW55IGNvbHVtbiBpbiBgZGVmaW5pdGlvbi5jb2x1bW5zYC5cbiAgICAgKi9cbiAgICBwcm90ZWN0ZWQgaGFzQ29sdW1uKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gdGhpcy5kZWZpbml0aW9uLmNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiBjb2x1bW4ubmFtZSA9PT0gbmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRmluZCBuYW1lcyB0aGF0IGFwcGVhciBtb3JlIHRoYW4gb25jZSBpbiBhIGxpc3QsIHByZXNlcnZpbmcgdGhlIG9yZGVyXG4gICAgICogb2YgZmlyc3QgZHVwbGljYXRpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gbmFtZXMgTmFtZXMgdG8gc2Nhbi5cbiAgICAgKiBAcmV0dXJucyBEdXBsaWNhdGVkIG5hbWVzLCBlYWNoIGxpc3RlZCBvbmNlLlxuICAgICAqL1xuICAgIHByb3RlY3RlZCBmaW5kRHVwbGljYXRlcyhuYW1lczogc3RyaW5nW10pOiBzdHJpbmdbXSB7XG4gICAgICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgY29uc3QgZHVwbGljYXRlcyA9IG5ldyBTZXQ8c3RyaW5nPigpO1xuICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgbmFtZXMpIHtcbiAgICAgICAgICAgIGlmIChzZWVuLmhhcyhuYW1lKSkge1xuICAgICAgICAgICAgICAgIGR1cGxpY2F0ZXMuYWRkKG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2Vlbi5hZGQobmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgIC4uLmR1cGxpY2F0ZXMsXG4gICAgICAgIF07XG4gICAgfVxuXG4gICAgLy8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIEVuZ2luZS1zcGVjaWZpYyBjb250cmFjdC5cblxuICAgIC8qKlxuICAgICAqIFdoZXRoZXIgYHR5cGVgIGlzIGEgdmFsaWQgY29sdW1uLXR5cGUgc3RyaW5nIGZvciB0aGlzIGVuZ2luZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0eXBlIENvbHVtbiB0eXBlIHN0cmluZyB0byBjaGVjay5cbiAgICAgKiBAcmV0dXJucyBUcnVlIHdoZW4gdGhlIGVuZ2luZSBhY2NlcHRzIHRoZSB0eXBlLlxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBpc1ZhbGlkQ29sdW1uVHlwZSh0eXBlOiBzdHJpbmcpOiBib29sZWFuO1xuXG4gICAgLyoqXG4gICAgICogRW5naW5lLXNwZWNpZmljIHBhcnRpdGlvbiBydWxlczogZHVwbGljYXRlIGRldGVjdGlvbiwgdHlwZS90cmFuc2Zvcm1cbiAgICAgKiBsZWdhbGl0eSwgYW5kIHRoZSBcIm5vIHBhcnRpdGlvbnMgYWxsb3dlZFwiIHJ1bGUgZm9yIGVuZ2luZXMgdGhhdCBkb24ndFxuICAgICAqIHN1cHBvcnQgdGhlbS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEV2ZXJ5IHBhcnRpdGlvbi1yZWxhdGVkIHZpb2xhdGlvbiB0aGlzIHRhYmxlIHByb2R1Y2VzLlxuICAgICAqL1xuICAgIHB1YmxpYyBhYnN0cmFjdCBwYXJ0aXRpb25WaW9sYXRpb25zKCk6IFZpb2xhdGlvbltdO1xuXG4gICAgLy8vIC8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL1xuICAgIC8vIEFnbm9zdGljIGludHJhLXRhYmxlIHJ1bGVzLlxuXG4gICAgLy8vIFBLX0NPTFVNTlNfRVhJU1Qg4oCUIGV2ZXJ5IHByaW1hcnkta2V5IGNvbHVtbiBleGlzdHMgaW4gYGNvbHVtbnNgLlxuICAgIHByaXZhdGUgcHJpbWFyeUtleVZpb2xhdGlvbnMoKTogVmlvbGF0aW9uW10ge1xuICAgICAgICBjb25zdCB2aW9sYXRpb25zOiBWaW9sYXRpb25bXSA9IFtdO1xuICAgICAgICBmb3IgKGNvbnN0IHBrQ29sdW1uIG9mIHRoaXMuZGVmaW5pdGlvbi5wcmltYXJ5S2V5KSB7XG4gICAgICAgICAgICBpZiAoIXRoaXMuaGFzQ29sdW1uKHBrQ29sdW1uKSkge1xuICAgICAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnUEtfQ09MVU1OU19FWElTVCcsXG4gICAgICAgICAgICAgICAgICAgIGZpZWxkOiAncHJpbWFyeUtleScsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBwcmltYXJ5LWtleSBjb2x1bW4gXCIke3BrQ29sdW1ufVwiIGlzIG5vdCBkZWZpbmVkIGluIGNvbHVtbnNgLFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gdmlvbGF0aW9ucztcbiAgICB9XG5cbiAgICAvLy8gTk9fRFVQTElDQVRFX0NPTFVNTlMg4oCUIGNvbHVtbiBuYW1lcyBhcmUgdW5pcXVlIHdpdGhpbiBhIHRhYmxlLlxuICAgIHByaXZhdGUgZHVwbGljYXRlQ29sdW1uVmlvbGF0aW9ucygpOiBWaW9sYXRpb25bXSB7XG4gICAgICAgIGNvbnN0IG5hbWVzID0gdGhpcy5kZWZpbml0aW9uLmNvbHVtbnMubWFwKChjb2x1bW4pID0+IGNvbHVtbi5uYW1lKTtcbiAgICAgICAgcmV0dXJuIHRoaXMuZmluZER1cGxpY2F0ZXMobmFtZXMpLm1hcCgoZHVwbGljYXRlKSA9PiB0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgICAgIGNvZGU6ICdOT19EVVBMSUNBVEVfQ09MVU1OUycsXG4gICAgICAgICAgICBmaWVsZDogJ2NvbHVtbnMnLFxuICAgICAgICAgICAgbWVzc2FnZTogYGR1cGxpY2F0ZSBjb2x1bW4gbmFtZSBcIiR7ZHVwbGljYXRlfVwiYCxcbiAgICAgICAgfSkpO1xuICAgIH1cblxuICAgIC8vLyBDT0xVTU5fVFlQRV9WQUxJRCDigJQgZXZlcnkgY29sdW1uIHR5cGUgaXMgdmFsaWQgZm9yIHRoZSB0YWJsZSdzIGVuZ2luZS5cbiAgICBwcml2YXRlIGNvbHVtblR5cGVWaW9sYXRpb25zKCk6IFZpb2xhdGlvbltdIHtcbiAgICAgICAgY29uc3QgdmlvbGF0aW9uczogVmlvbGF0aW9uW10gPSBbXTtcbiAgICAgICAgdGhpcy5kZWZpbml0aW9uLmNvbHVtbnMuZm9yRWFjaCgoY29sdW1uLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgaWYgKCF0aGlzLmlzVmFsaWRDb2x1bW5UeXBlKGNvbHVtbi50eXBlKSkge1xuICAgICAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnQ09MVU1OX1RZUEVfVkFMSUQnLFxuICAgICAgICAgICAgICAgICAgICBmaWVsZDogYGNvbHVtbnNbJHtpbmRleH1dLnR5cGVgLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgXCIke2NvbHVtbi50eXBlfVwiIGlzIG5vdCBhIHZhbGlkICR7dGhpcy5kZWZpbml0aW9uLnRhYmxlVHlwZX0gdHlwZSBgXG4gICAgICAgICAgICAgICAgICAgICAgICArIGBmb3IgY29sdW1uIFwiJHtjb2x1bW4ubmFtZX1cImAsXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuIHZpb2xhdGlvbnM7XG4gICAgfVxuXG4gICAgLy8vIFJBV19OT19ERVBFTkRTX09OIC8gTk9OUkFXX1JFUVVJUkVTX0RFUEVORFNfT04uXG4gICAgcHJpdmF0ZSByYXdDb25zaXN0ZW5jeVZpb2xhdGlvbnMoKTogVmlvbGF0aW9uW10ge1xuICAgICAgICBjb25zdCB2aW9sYXRpb25zOiBWaW9sYXRpb25bXSA9IFtdO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBpc1Jhd0RhdGEsXG4gICAgICAgICAgICBkZXBlbmRzT24sXG4gICAgICAgIH0gPSB0aGlzLmRlZmluaXRpb247XG4gICAgICAgIGlmIChpc1Jhd0RhdGEgJiYgZGVwZW5kc09uLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgbGV2ZWw6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ1JBV19OT19ERVBFTkRTX09OJyxcbiAgICAgICAgICAgICAgICBmaWVsZDogJ2RlcGVuZHNPbicsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogJ3JhdyB0YWJsZXMgKGlzUmF3RGF0YT10cnVlKSBtdXN0IG5vdCBkZWNsYXJlIGRlcGVuZHNPbicsXG4gICAgICAgICAgICB9KSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKCFpc1Jhd0RhdGEgJiYgZGVwZW5kc09uLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgdmlvbGF0aW9ucy5wdXNoKHRoaXMudmlvbGF0aW9uKHtcbiAgICAgICAgICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICBjb2RlOiAnTk9OUkFXX1JFUVVJUkVTX0RFUEVORFNfT04nLFxuICAgICAgICAgICAgICAgIGZpZWxkOiAnZGVwZW5kc09uJyxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiAnbm9uLXJhdyB0YWJsZXMgKGlzUmF3RGF0YT1mYWxzZSkgbXVzdCBkZWNsYXJlIGF0IGxlYXN0IG9uZSBkZXBlbmRzT24nLFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB2aW9sYXRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsbCBpbnRyYS10YWJsZSB2aW9sYXRpb25zIGZvciB0aGlzIHRhYmxlIChlbmdpbmUtYWdub3N0aWMgcnVsZXMgcGx1c1xuICAgICAqIHRoZSBlbmdpbmUtc3BlY2lmaWMgcGFydGl0aW9uIHJ1bGVzKS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIEV2ZXJ5IGludHJhLXRhYmxlIHZpb2xhdGlvbiB0aGlzIHRhYmxlIHByb2R1Y2VzLlxuICAgICAqL1xuICAgIHB1YmxpYyBpbnRyYVRhYmxlVmlvbGF0aW9ucygpOiBWaW9sYXRpb25bXSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAuLi50aGlzLnByaW1hcnlLZXlWaW9sYXRpb25zKCksXG4gICAgICAgICAgICAuLi50aGlzLmR1cGxpY2F0ZUNvbHVtblZpb2xhdGlvbnMoKSxcbiAgICAgICAgICAgIC4uLnRoaXMuY29sdW1uVHlwZVZpb2xhdGlvbnMoKSxcbiAgICAgICAgICAgIC4uLnRoaXMucGFydGl0aW9uVmlvbGF0aW9ucygpLFxuICAgICAgICAgICAgLi4udGhpcy5yYXdDb25zaXN0ZW5jeVZpb2xhdGlvbnMoKSxcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICAvLy8gLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vXG4gICAgLy8gQ3Jvc3MtZmlsZSBydWxlcy5cblxuICAgIC8vLyBERVBFTkRTX09OX1JFU09MVkVTIOKAlCBldmVyeSBkZXBlbmRzT24gZW50cnkgcmVzb2x2ZXMgdG8gYSByZWFsIHRhYmxlLlxuICAgIHByaXZhdGUgZGVwZW5kc09uVmlvbGF0aW9ucyh3b3JsZDogV29ybGQpOiBWaW9sYXRpb25bXSB7XG4gICAgICAgIGNvbnN0IHZpb2xhdGlvbnM6IFZpb2xhdGlvbltdID0gW107XG4gICAgICAgIHRoaXMuZGVmaW5pdGlvbi5kZXBlbmRzT24uZm9yRWFjaCgoZGVwZW5kZW5jeSwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGlmICghd29ybGQudGFibGVzLmhhcyhkZXBlbmRlbmN5KSkge1xuICAgICAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnREVQRU5EU19PTl9SRVNPTFZFUycsXG4gICAgICAgICAgICAgICAgICAgIGZpZWxkOiBgZGVwZW5kc09uWyR7aW5kZXh9XWAsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBkZXBlbmRzT24gXCIke2RlcGVuZGVuY3l9XCIgZG9lcyBub3QgcmVzb2x2ZSB0byBhIGtub3duIHRhYmxlYCxcbiAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICByZXR1cm4gdmlvbGF0aW9ucztcbiAgICB9XG5cbiAgICAvLy8gRm9yZWlnbi1rZXkgY2hlY2tzIGZvciBhIHNpbmdsZSBGSyBlbnRyeS5cbiAgICBwcml2YXRlIGZvcmVpZ25LZXlWaW9sYXRpb25zKHdvcmxkOiBXb3JsZCwgZms6IEZvcmVpZ25LZXksIGluZGV4OiBudW1iZXIpOiBWaW9sYXRpb25bXSB7XG4gICAgICAgIGNvbnN0IHZpb2xhdGlvbnM6IFZpb2xhdGlvbltdID0gW107XG4gICAgICAgIGNvbnN0IGZpZWxkID0gYGZvcmVpZ25LZXlzWyR7aW5kZXh9XWA7XG5cbiAgICAgICAgaWYgKCF0aGlzLmhhc0NvbHVtbihmay5sb2NhbENvbHVtbikpIHtcbiAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgbGV2ZWw6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ0ZLX0xPQ0FMX0NPTFVNTl9FWElTVFMnLFxuICAgICAgICAgICAgICAgIGZpZWxkOiBgJHtmaWVsZH0ubG9jYWxDb2x1bW5gLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBsb2NhbCBjb2x1bW4gXCIke2ZrLmxvY2FsQ29sdW1ufVwiIGlzIG5vdCBkZWZpbmVkIGluIGNvbHVtbnNgLFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8vIEEgc2VsZi1yZWZlcmVudGlhbCBmb3JlaWduIGtleSAoZS5nLiBhIGBwYXJlbnRfaWRgIHBvaW50aW5nIGF0IHRoZSBzYW1lXG4gICAgICAgIC8vLyB0YWJsZSdzIGtleSkgZG9lcyBub3QgY3JlYXRlIGEgcGlwZWxpbmUgZGVwZW5kZW5jeSwgc28gaXQgaXMgZXhlbXB0IGZyb21cbiAgICAgICAgLy8vIEZLX0lNUExJRVNfREVQRU5ERU5DWSDigJQgcmVxdWlyaW5nIGEgc2VsZi1gZGVwZW5kc09uYCB3b3VsZCBvdGhlcndpc2UgZm9yY2VcbiAgICAgICAgLy8vIGEgc3B1cmlvdXMgZGVwZW5kZW5jeSBjeWNsZS5cbiAgICAgICAgY29uc3QgaXNTZWxmUmVmZXJlbmNlID0gZmsuc291cmNlVGFibGUgPT09IHRoaXMucXVhbGlmaWVkTmFtZTtcbiAgICAgICAgaWYgKCFpc1NlbGZSZWZlcmVuY2UgJiYgIXRoaXMuZGVmaW5pdGlvbi5kZXBlbmRzT24uaW5jbHVkZXMoZmsuc291cmNlVGFibGUpKSB7XG4gICAgICAgICAgICB2aW9sYXRpb25zLnB1c2godGhpcy52aW9sYXRpb24oe1xuICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgIGNvZGU6ICdGS19JTVBMSUVTX0RFUEVOREVOQ1knLFxuICAgICAgICAgICAgICAgIGZpZWxkOiBgJHtmaWVsZH0uc291cmNlVGFibGVgLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBmb3JlaWduIGtleSB0YXJnZXRzIFwiJHtmay5zb3VyY2VUYWJsZX1cIiBidXQgaXQgaXMgbm90IGxpc3RlZCBpbiBkZXBlbmRzT25gLFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdGFyZ2V0ID0gd29ybGQudGFibGVzLmdldChmay5zb3VyY2VUYWJsZSk7XG4gICAgICAgIGlmICh0YXJnZXQgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgdmlvbGF0aW9ucy5wdXNoKHRoaXMudmlvbGF0aW9uKHtcbiAgICAgICAgICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICBjb2RlOiAnRktfU09VUkNFX1RBQkxFX1JFU09MVkVTJyxcbiAgICAgICAgICAgICAgICBmaWVsZDogYCR7ZmllbGR9LnNvdXJjZVRhYmxlYCxcbiAgICAgICAgICAgICAgICBtZXNzYWdlOiBgZm9yZWlnbiBrZXkgc291cmNlIHRhYmxlIFwiJHtmay5zb3VyY2VUYWJsZX1cIiBkb2VzIG5vdCByZXNvbHZlIHRvIGEga25vd24gdGFibGVgLFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgcmV0dXJuIHZpb2xhdGlvbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLy8gVGhlIHRhcmdldCdzIG93biBzdHJ1Y3R1cmFsIGVycm9ycyAocmVwb3J0ZWQgYnkgTGF5ZXIgMSkgYWxyZWFkeSBleHBsYWluXG4gICAgICAgIC8vLyB3aHkgaXRzIGNvbHVtbnMgY2FuJ3QgYmUgdHJ1c3RlZDsgc2tpcCBjb2x1bW4tbGV2ZWwgY2hlY2tzIHRvIGF2b2lkXG4gICAgICAgIC8vLyBwaWxpbmcgbWlzbGVhZGluZyBmaW5kaW5ncyBvbiB0b3AuXG4gICAgICAgIGlmICghdGFyZ2V0LnN0cnVjdHVyYWxseVZhbGlkKSB7XG4gICAgICAgICAgICByZXR1cm4gdmlvbGF0aW9ucztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRhcmdldEhhc0NvbHVtbiA9IHRhcmdldC5kZWZpbml0aW9uLmNvbHVtbnMuc29tZSgoY29sdW1uKSA9PiBjb2x1bW4ubmFtZSA9PT0gZmsuc291cmNlQ29sdW1uKTtcbiAgICAgICAgaWYgKCF0YXJnZXRIYXNDb2x1bW4pIHtcbiAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgbGV2ZWw6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgY29kZTogJ0ZLX1NPVVJDRV9DT0xVTU5fRVhJU1RTJyxcbiAgICAgICAgICAgICAgICBmaWVsZDogYCR7ZmllbGR9LnNvdXJjZUNvbHVtbmAsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYGZvcmVpZ24ga2V5IHNvdXJjZSBjb2x1bW4gXCIke2ZrLnNvdXJjZUNvbHVtbn1cIiBpcyBub3QgZGVmaW5lZCBpbiBcIiR7Zmsuc291cmNlVGFibGV9XCJgLFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgcmV0dXJuIHZpb2xhdGlvbnM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRhcmdldC5kZWZpbml0aW9uLnByaW1hcnlLZXkuaW5jbHVkZXMoZmsuc291cmNlQ29sdW1uKSkge1xuICAgICAgICAgICAgdmlvbGF0aW9ucy5wdXNoKHRoaXMudmlvbGF0aW9uKHtcbiAgICAgICAgICAgICAgICBsZXZlbDogJ3dhcm5pbmcnLFxuICAgICAgICAgICAgICAgIGNvZGU6ICdGS19TT1VSQ0VfSVNfS0VZJyxcbiAgICAgICAgICAgICAgICBmaWVsZDogYCR7ZmllbGR9LnNvdXJjZUNvbHVtbmAsXG4gICAgICAgICAgICAgICAgbWVzc2FnZTogYGZvcmVpZ24ga2V5IHNvdXJjZSBjb2x1bW4gXCIke2ZrLnNvdXJjZUNvbHVtbn1cIiBpcyBub3QgcGFydCBvZiB0aGUgcHJpbWFyeSBrZXkgYFxuICAgICAgICAgICAgICAgICAgICArIGBvZiBcIiR7Zmsuc291cmNlVGFibGV9XCJgLFxuICAgICAgICAgICAgfSkpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHZpb2xhdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxsIGNyb3NzLWZpbGUgdmlvbGF0aW9ucyBmb3IgdGhpcyB0YWJsZSAoYGRlcGVuZHNPbmAgcmVzb2x1dGlvbiBwbHVzXG4gICAgICogdGhlIGZ1bGwgZm9yZWlnbi1rZXkgc3VpdGUpLlxuICAgICAqXG4gICAgICogQHBhcmFtIHdvcmxkIFRoZSBsb2FkZWQgZGF0YXNldCByb290LlxuICAgICAqIEByZXR1cm5zIEV2ZXJ5IGNyb3NzLWZpbGUgdmlvbGF0aW9uIHRoaXMgdGFibGUgcHJvZHVjZXMuXG4gICAgICovXG4gICAgcHVibGljIGNyb3NzRmlsZVZpb2xhdGlvbnMod29ybGQ6IFdvcmxkKTogVmlvbGF0aW9uW10ge1xuICAgICAgICBjb25zdCB2aW9sYXRpb25zOiBWaW9sYXRpb25bXSA9IFtcbiAgICAgICAgICAgIC4uLnRoaXMuZGVwZW5kc09uVmlvbGF0aW9ucyh3b3JsZCksXG4gICAgICAgIF07XG4gICAgICAgIHRoaXMuZGVmaW5pdGlvbi5mb3JlaWduS2V5cy5mb3JFYWNoKChmaywgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCguLi50aGlzLmZvcmVpZ25LZXlWaW9sYXRpb25zKHdvcmxkLCBmaywgaW5kZXgpKTtcbiAgICAgICAgfSk7XG4gICAgICAgIHJldHVybiB2aW9sYXRpb25zO1xuICAgIH1cbn1cbiJdfQ==
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Hive (parquet) table type.
3
+ *
4
+ * Hive partitions are *new* columns at write time, distinct from data
5
+ * columns: their identity is the partition name and the validator forbids
6
+ * shadowing an existing data column.
7
+ */
8
+ import { Violation } from '../model';
9
+ import { TableTypeBase } from '../table-type';
10
+ /** Hive (parquet) table. */
11
+ export declare class HiveParquetTable extends TableTypeBase {
12
+ /**
13
+ * Validate a column type against the Hive type registry.
14
+ *
15
+ * @param type Type string from a column definition.
16
+ * @returns True when the type is a valid Hive type.
17
+ */
18
+ isValidColumnType(type: string): boolean;
19
+ /**
20
+ * Hive partition rules.
21
+ *
22
+ * Emits: `NO_DUPLICATE_PARTITIONS` (by partition name),
23
+ * `HIVE_PARTITION_NOT_IN_COLUMNS` (a Hive partition is a new column, so
24
+ * it must not collide with a data column), and `HIVE_PARTITION_TYPE_VALID`.
25
+ *
26
+ * @returns Every partition-related violation.
27
+ */
28
+ partitionViolations(): Violation[];
29
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ /**
3
+ * Hive (parquet) table type.
4
+ *
5
+ * Hive partitions are *new* columns at write time, distinct from data
6
+ * columns: their identity is the partition name and the validator forbids
7
+ * shadowing an existing data column.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.HiveParquetTable = void 0;
11
+ const table_type_1 = require("../table-type");
12
+ const types_1 = require("../types");
13
+ /** Hive (parquet) table. */
14
+ class HiveParquetTable extends table_type_1.TableTypeBase {
15
+ /**
16
+ * Validate a column type against the Hive type registry.
17
+ *
18
+ * @param type Type string from a column definition.
19
+ * @returns True when the type is a valid Hive type.
20
+ */
21
+ isValidColumnType(type) {
22
+ return (0, types_1.isValidHiveType)(type);
23
+ }
24
+ /**
25
+ * Hive partition rules.
26
+ *
27
+ * Emits: `NO_DUPLICATE_PARTITIONS` (by partition name),
28
+ * `HIVE_PARTITION_NOT_IN_COLUMNS` (a Hive partition is a new column, so
29
+ * it must not collide with a data column), and `HIVE_PARTITION_TYPE_VALID`.
30
+ *
31
+ * @returns Every partition-related violation.
32
+ */
33
+ partitionViolations() {
34
+ const violations = [];
35
+ const { partitions, } = this.definition;
36
+ const seen = new Set();
37
+ partitions.forEach((partition, index) => {
38
+ if (seen.has(partition.name)) {
39
+ violations.push(this.violation({
40
+ level: 'error',
41
+ code: 'NO_DUPLICATE_PARTITIONS',
42
+ field: `partitions[${index}]`,
43
+ message: `duplicate partition name "${partition.name}"`,
44
+ }));
45
+ }
46
+ seen.add(partition.name);
47
+ });
48
+ partitions.forEach((partition, index) => {
49
+ if (this.hasColumn(partition.name)) {
50
+ violations.push(this.violation({
51
+ level: 'error',
52
+ code: 'HIVE_PARTITION_NOT_IN_COLUMNS',
53
+ field: `partitions[${index}].name`,
54
+ message: `Hive partition "${partition.name}" must not also be a data column`,
55
+ }));
56
+ }
57
+ if (!(0, types_1.isValidHiveType)(partition.type)) {
58
+ violations.push(this.violation({
59
+ level: 'error',
60
+ code: 'HIVE_PARTITION_TYPE_VALID',
61
+ field: `partitions[${index}].type`,
62
+ message: `"${partition.type}" is not a valid Hive partition type`,
63
+ }));
64
+ }
65
+ });
66
+ return violations;
67
+ }
68
+ }
69
+ exports.HiveParquetTable = HiveParquetTable;
70
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaGl2ZS1wYXJxdWV0LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vc3JjL3RhYmxlLXR5cGVzL2hpdmUtcGFycXVldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7QUFLSCw4Q0FFdUI7QUFDdkIsb0NBRWtCO0FBRWxCLDRCQUE0QjtBQUM1QixNQUFhLGdCQUFpQixTQUFRLDBCQUFhO0lBQy9DOzs7OztPQUtHO0lBQ0ksaUJBQWlCLENBQUMsSUFBWTtRQUNqQyxPQUFPLElBQUEsdUJBQWUsRUFBQyxJQUFJLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBRUQ7Ozs7Ozs7O09BUUc7SUFDSSxtQkFBbUI7UUFDdEIsTUFBTSxVQUFVLEdBQWdCLEVBQUUsQ0FBQztRQUNuQyxNQUFNLEVBQ0YsVUFBVSxHQUNiLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQztRQUVwQixNQUFNLElBQUksR0FBRyxJQUFJLEdBQUcsRUFBVSxDQUFDO1FBQy9CLFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDcEMsSUFBSSxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUMzQixVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQzNCLEtBQUssRUFBRSxPQUFPO29CQUNkLElBQUksRUFBRSx5QkFBeUI7b0JBQy9CLEtBQUssRUFBRSxjQUFjLEtBQUssR0FBRztvQkFDN0IsT0FBTyxFQUFFLDZCQUE2QixTQUFTLENBQUMsSUFBSSxHQUFHO2lCQUMxRCxDQUFDLENBQUMsQ0FBQztZQUNSLENBQUM7WUFDRCxJQUFJLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUM3QixDQUFDLENBQUMsQ0FBQztRQUVILFVBQVUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxTQUFTLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDcEMsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO2dCQUNqQyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLENBQUM7b0JBQzNCLEtBQUssRUFBRSxPQUFPO29CQUNkLElBQUksRUFBRSwrQkFBK0I7b0JBQ3JDLEtBQUssRUFBRSxjQUFjLEtBQUssUUFBUTtvQkFDbEMsT0FBTyxFQUFFLG1CQUFtQixTQUFTLENBQUMsSUFBSSxrQ0FBa0M7aUJBQy9FLENBQUMsQ0FBQyxDQUFDO1lBQ1IsQ0FBQztZQUNELElBQUksQ0FBQyxJQUFBLHVCQUFlLEVBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ25DLFVBQVUsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQztvQkFDM0IsS0FBSyxFQUFFLE9BQU87b0JBQ2QsSUFBSSxFQUFFLDJCQUEyQjtvQkFDakMsS0FBSyxFQUFFLGNBQWMsS0FBSyxRQUFRO29CQUNsQyxPQUFPLEVBQUUsSUFBSSxTQUFTLENBQUMsSUFBSSxzQ0FBc0M7aUJBQ3BFLENBQUMsQ0FBQyxDQUFDO1lBQ1IsQ0FBQztRQUNMLENBQUMsQ0FBQyxDQUFDO1FBRUgsT0FBTyxVQUFVLENBQUM7SUFDdEIsQ0FBQztDQUNKO0FBNURELDRDQTREQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogSGl2ZSAocGFycXVldCkgdGFibGUgdHlwZS5cbiAqXG4gKiBIaXZlIHBhcnRpdGlvbnMgYXJlICpuZXcqIGNvbHVtbnMgYXQgd3JpdGUgdGltZSwgZGlzdGluY3QgZnJvbSBkYXRhXG4gKiBjb2x1bW5zOiB0aGVpciBpZGVudGl0eSBpcyB0aGUgcGFydGl0aW9uIG5hbWUgYW5kIHRoZSB2YWxpZGF0b3IgZm9yYmlkc1xuICogc2hhZG93aW5nIGFuIGV4aXN0aW5nIGRhdGEgY29sdW1uLlxuICovXG5cbmltcG9ydCB7XG4gICAgVmlvbGF0aW9uLFxufSBmcm9tICcuLi9tb2RlbCc7XG5pbXBvcnQge1xuICAgIFRhYmxlVHlwZUJhc2UsXG59IGZyb20gJy4uL3RhYmxlLXR5cGUnO1xuaW1wb3J0IHtcbiAgICBpc1ZhbGlkSGl2ZVR5cGUsXG59IGZyb20gJy4uL3R5cGVzJztcblxuLyoqIEhpdmUgKHBhcnF1ZXQpIHRhYmxlLiAqL1xuZXhwb3J0IGNsYXNzIEhpdmVQYXJxdWV0VGFibGUgZXh0ZW5kcyBUYWJsZVR5cGVCYXNlIHtcbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSBhIGNvbHVtbiB0eXBlIGFnYWluc3QgdGhlIEhpdmUgdHlwZSByZWdpc3RyeS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB0eXBlIFR5cGUgc3RyaW5nIGZyb20gYSBjb2x1bW4gZGVmaW5pdGlvbi5cbiAgICAgKiBAcmV0dXJucyBUcnVlIHdoZW4gdGhlIHR5cGUgaXMgYSB2YWxpZCBIaXZlIHR5cGUuXG4gICAgICovXG4gICAgcHVibGljIGlzVmFsaWRDb2x1bW5UeXBlKHR5cGU6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgICAgICByZXR1cm4gaXNWYWxpZEhpdmVUeXBlKHR5cGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhpdmUgcGFydGl0aW9uIHJ1bGVzLlxuICAgICAqXG4gICAgICogRW1pdHM6IGBOT19EVVBMSUNBVEVfUEFSVElUSU9OU2AgKGJ5IHBhcnRpdGlvbiBuYW1lKSxcbiAgICAgKiBgSElWRV9QQVJUSVRJT05fTk9UX0lOX0NPTFVNTlNgIChhIEhpdmUgcGFydGl0aW9uIGlzIGEgbmV3IGNvbHVtbiwgc29cbiAgICAgKiBpdCBtdXN0IG5vdCBjb2xsaWRlIHdpdGggYSBkYXRhIGNvbHVtbiksIGFuZCBgSElWRV9QQVJUSVRJT05fVFlQRV9WQUxJRGAuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBFdmVyeSBwYXJ0aXRpb24tcmVsYXRlZCB2aW9sYXRpb24uXG4gICAgICovXG4gICAgcHVibGljIHBhcnRpdGlvblZpb2xhdGlvbnMoKTogVmlvbGF0aW9uW10ge1xuICAgICAgICBjb25zdCB2aW9sYXRpb25zOiBWaW9sYXRpb25bXSA9IFtdO1xuICAgICAgICBjb25zdCB7XG4gICAgICAgICAgICBwYXJ0aXRpb25zLFxuICAgICAgICB9ID0gdGhpcy5kZWZpbml0aW9uO1xuXG4gICAgICAgIGNvbnN0IHNlZW4gPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgICAgICAgcGFydGl0aW9ucy5mb3JFYWNoKChwYXJ0aXRpb24sIGluZGV4KSA9PiB7XG4gICAgICAgICAgICBpZiAoc2Vlbi5oYXMocGFydGl0aW9uLm5hbWUpKSB7XG4gICAgICAgICAgICAgICAgdmlvbGF0aW9ucy5wdXNoKHRoaXMudmlvbGF0aW9uKHtcbiAgICAgICAgICAgICAgICAgICAgbGV2ZWw6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgICAgIGNvZGU6ICdOT19EVVBMSUNBVEVfUEFSVElUSU9OUycsXG4gICAgICAgICAgICAgICAgICAgIGZpZWxkOiBgcGFydGl0aW9uc1ske2luZGV4fV1gLFxuICAgICAgICAgICAgICAgICAgICBtZXNzYWdlOiBgZHVwbGljYXRlIHBhcnRpdGlvbiBuYW1lIFwiJHtwYXJ0aXRpb24ubmFtZX1cImAsXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgc2Vlbi5hZGQocGFydGl0aW9uLm5hbWUpO1xuICAgICAgICB9KTtcblxuICAgICAgICBwYXJ0aXRpb25zLmZvckVhY2goKHBhcnRpdGlvbiwgaW5kZXgpID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmhhc0NvbHVtbihwYXJ0aXRpb24ubmFtZSkpIHtcbiAgICAgICAgICAgICAgICB2aW9sYXRpb25zLnB1c2godGhpcy52aW9sYXRpb24oe1xuICAgICAgICAgICAgICAgICAgICBsZXZlbDogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICAgICAgY29kZTogJ0hJVkVfUEFSVElUSU9OX05PVF9JTl9DT0xVTU5TJyxcbiAgICAgICAgICAgICAgICAgICAgZmllbGQ6IGBwYXJ0aXRpb25zWyR7aW5kZXh9XS5uYW1lYCxcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZTogYEhpdmUgcGFydGl0aW9uIFwiJHtwYXJ0aXRpb24ubmFtZX1cIiBtdXN0IG5vdCBhbHNvIGJlIGEgZGF0YSBjb2x1bW5gLFxuICAgICAgICAgICAgICAgIH0pKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghaXNWYWxpZEhpdmVUeXBlKHBhcnRpdGlvbi50eXBlKSkge1xuICAgICAgICAgICAgICAgIHZpb2xhdGlvbnMucHVzaCh0aGlzLnZpb2xhdGlvbih7XG4gICAgICAgICAgICAgICAgICAgIGxldmVsOiAnZXJyb3InLFxuICAgICAgICAgICAgICAgICAgICBjb2RlOiAnSElWRV9QQVJUSVRJT05fVFlQRV9WQUxJRCcsXG4gICAgICAgICAgICAgICAgICAgIGZpZWxkOiBgcGFydGl0aW9uc1ske2luZGV4fV0udHlwZWAsXG4gICAgICAgICAgICAgICAgICAgIG1lc3NhZ2U6IGBcIiR7cGFydGl0aW9uLnR5cGV9XCIgaXMgbm90IGEgdmFsaWQgSGl2ZSBwYXJ0aXRpb24gdHlwZWAsXG4gICAgICAgICAgICAgICAgfSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdmlvbGF0aW9ucztcbiAgICB9XG59XG4iXX0=
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Iceberg (parquet) table type.
3
+ *
4
+ * Iceberg partitions are transforms applied to a data column, so duplicate
5
+ * detection keys on the (source column, normalized transform) pair — `year(ts)`
6
+ * and `month(ts)` are distinct, while `day` and `DAY` collapse.
7
+ */
8
+ import { Violation } from '../model';
9
+ import { TableTypeBase } from '../table-type';
10
+ /** Iceberg (parquet) table. */
11
+ export declare class IcebergParquetTable extends TableTypeBase {
12
+ /**
13
+ * Validate a column type against the Iceberg v0 type registry.
14
+ *
15
+ * @param type Type string from a column definition.
16
+ * @returns True when the type is a valid Iceberg type.
17
+ */
18
+ isValidColumnType(type: string): boolean;
19
+ /**
20
+ * Iceberg partition rules.
21
+ *
22
+ * Emits: `NO_DUPLICATE_PARTITIONS` (keyed by `${name} ${transformKind}:${param}`,
23
+ * falling back to a lowercased trim of the raw transform when it doesn't
24
+ * parse, so whitespace / case variants of the same transform collapse),
25
+ * `ICEBERG_TRANSFORM_SOURCE_EXISTS`, `ICEBERG_TRANSFORM_VALID`, and
26
+ * `ICEBERG_TRANSFORM_SOURCE_TYPE_LEGAL`.
27
+ *
28
+ * @returns Every partition-related violation.
29
+ */
30
+ partitionViolations(): Violation[];
31
+ /**
32
+ * Normalize a partition into its identity key. When the transform parses,
33
+ * collapse on `${kind}:${param}` so `day` and `DAY`, `bucket[16]` and
34
+ * `bucket[ 16 ]` are the same. When the transform doesn't parse, the
35
+ * lowercased trim of the raw string is the best identity we have.
36
+ *
37
+ * @param partition Partition to key.
38
+ * @returns The identity string for duplicate detection.
39
+ */
40
+ private partitionKey;
41
+ }