Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | 50x 50x 50x 50x 50x 50x 50x 18x 122x 50x 122x 214x 214x 32x 18x 32x 32x 58x 182x 182x 10x 182x 50x 122x 122x 208x 32x 176x 122x 50x 50x 41x 41x 50x 50x 18x 50x | import type { NormalizedData, NormalizedValue } from "../normalize";
import { createForeignKey } from "./create-foreign-key";
import { getIsNullable } from "./get-is-nullable";
import { getType, UnknownTypeError } from "./get-type";
import type { Field, RelationalTable } from "./types";
export function createRelationalStructure(
prefix: string,
data: NormalizedData,
parentTable?: RelationalTable,
): RelationalTable[] {
const fields: Map<string, Field> = new Map();
const fieldTypes: Map<string, Field["type"]> = new Map();
const fieldIsNullable: Map<string, Field["isNullable"]> = new Map();
const nestedData: Map<string, NormalizedData> = new Map();
const selfData: Record<string, NormalizedValue>[] = [];
fields.set("normalize_id", {
key: "normalize_id",
type: "integer",
isPrimaryKey: true,
});
if (parentTable) {
fields.set("normalize_parent_id", {
key: "normalize_parent_id",
type: "integer",
reference: createForeignKey(parentTable, "normalize_id"),
});
}
const keys = new Set(data.map((row) => Object.keys(row)).flat());
data.forEach((row, normalize_parent_id) => {
for (const key of keys) {
const value = row[key];
if (Array.isArray(value)) {
if (!nestedData.has(key)) {
nestedData.set(key, []);
}
const nestedDataByKey = nestedData.get(key)!;
value.forEach((item) =>
nestedDataByKey.push({ ...item, normalize_parent_id }),
);
} else {
try {
fieldTypes.set(key, getType(fieldTypes.get(key), value));
} catch (error) {
Iif (!(error instanceof UnknownTypeError)) {
throw error;
}
}
fieldIsNullable.set(
key,
getIsNullable(fieldIsNullable.get(key), value),
);
}
}
});
data.forEach((row, normalize_id) => {
const selfDataItem: Record<string, NormalizedValue> = { normalize_id };
for (const [key, value] of Object.entries(row)) {
if (Array.isArray(value)) {
continue;
}
selfDataItem[key] = value;
}
selfData.push(selfDataItem);
});
fieldTypes.delete("normalize_parent_id");
for (const [key, type] of fieldTypes.entries()) {
const isNullable = fieldIsNullable.get(key);
fields.set(key, {
key,
type,
...(isNullable ? { isNullable } : {}),
});
}
const relationalTable: RelationalTable = {
name: prefix,
fields: [...fields.values()],
data: selfData,
};
const nestedRelationalTables = [...nestedData.entries()]
.map((entry) =>
createRelationalStructure(
`${prefix}_${entry[0]}`,
entry[1],
relationalTable,
),
)
.flat();
return [relationalTable, ...nestedRelationalTables];
}
|