mirror of
https://github.com/stackrender/stackrender.git
synced 2026-09-10 11:15:42 +00:00
render mysql code
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
|
||||
import { Autocomplete as HeroUiAutocomplete, AutocompleteItem } from "@heroui/react";
|
||||
import { Autocomplete as HeroUiAutocomplete, AutocompleteItem, AutocompleteSection } from "@heroui/react";
|
||||
import { Key } from "react";
|
||||
|
||||
interface AutocompleteProps {
|
||||
@@ -10,29 +10,60 @@ interface AutocompleteProps {
|
||||
onSelectionChange?: (item: any) => void,
|
||||
placeholder?: string
|
||||
isDisabled?: boolean
|
||||
selectedItem?: Key
|
||||
selectedItem?: Key,
|
||||
grouped?: boolean
|
||||
}
|
||||
|
||||
|
||||
const headingClasses =
|
||||
"flex w-full py-1.5 px-2 bg-default shadow-small rounded-small";
|
||||
|
||||
const Autocomplete: React.FC<AutocompleteProps> = ({ items, label = "name", onSelectionChange, defaultSelection, placeholder, isDisabled, selectedItem }) => {
|
||||
|
||||
const Autocomplete: React.FC<AutocompleteProps> = ({ items, label = "name", onSelectionChange, defaultSelection, placeholder, isDisabled, selectedItem, grouped = false }) => {
|
||||
|
||||
|
||||
const onItemChange = (item: Key | null) => {
|
||||
onSelectionChange && onSelectionChange(item);
|
||||
}
|
||||
if (!grouped)
|
||||
return (
|
||||
<HeroUiAutocomplete
|
||||
radius="sm"
|
||||
isDisabled={isDisabled}
|
||||
className="w-full"
|
||||
defaultItems={items || []}
|
||||
size="sm"
|
||||
onSelectionChange={onItemChange}
|
||||
defaultSelectedKey={defaultSelection as any}
|
||||
variant="bordered"
|
||||
aria-label={placeholder}
|
||||
placeholder={placeholder}
|
||||
selectedKey={selectedItem as any}
|
||||
inputProps={{
|
||||
classNames: {
|
||||
|
||||
inputWrapper: "border-divider group-hover:border-primary",
|
||||
|
||||
return (
|
||||
<HeroUiAutocomplete
|
||||
},
|
||||
}}
|
||||
|
||||
>
|
||||
{(item: any) => <AutocompleteItem key={item.id}>{item[label]}</AutocompleteItem>}
|
||||
</HeroUiAutocomplete>
|
||||
)
|
||||
if (grouped) {
|
||||
return <HeroUiAutocomplete
|
||||
radius="sm"
|
||||
isDisabled={isDisabled}
|
||||
className="w-full"
|
||||
defaultItems={items || []}
|
||||
|
||||
size="sm"
|
||||
onSelectionChange={onItemChange}
|
||||
defaultSelectedKey={defaultSelection as any}
|
||||
variant="bordered"
|
||||
aria-label={placeholder}
|
||||
placeholder={placeholder}
|
||||
|
||||
selectedKey={selectedItem as any}
|
||||
inputProps={{
|
||||
classNames: {
|
||||
@@ -43,9 +74,27 @@ const Autocomplete: React.FC<AutocompleteProps> = ({ items, label = "name", onSe
|
||||
}}
|
||||
|
||||
>
|
||||
{(item: any) => <AutocompleteItem key={item.id}>{item[label]}</AutocompleteItem>}
|
||||
{
|
||||
items ? Object.keys(items).map((key: any) => (
|
||||
<AutocompleteSection
|
||||
classNames={{
|
||||
heading: headingClasses,
|
||||
}}
|
||||
title={key}
|
||||
>
|
||||
{
|
||||
items[key].map((item: any) => (
|
||||
<AutocompleteItem key={item.id}>{item[label]}</AutocompleteItem>
|
||||
))
|
||||
}
|
||||
</AutocompleteSection>
|
||||
|
||||
)) : []
|
||||
}
|
||||
|
||||
|
||||
</HeroUiAutocomplete>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default Autocomplete;
|
||||
@@ -7,6 +7,7 @@ import { useEffect, useState } from "react";
|
||||
import { Parser } from "node-sql-parser";
|
||||
import { DatabaseType } from "@/lib/schemas/database-schema";
|
||||
import { format } from 'sql-formatter';
|
||||
import { getDatabaseByDialect } from "@/lib/database";
|
||||
|
||||
const parser = new Parser();
|
||||
|
||||
@@ -16,8 +17,11 @@ export const useRenderSql = (database: DatabaseType) => {
|
||||
const { data_types } = useDatabaseOperations();
|
||||
|
||||
useEffect(() => {
|
||||
const dbAst: any = DatabaseToAst(database, data_types);
|
||||
const formattedSqlCode = format(parser.sqlify(dbAst), { language: 'sql' }); // or 'mysql', 'postgresql', etc.
|
||||
const dbAst: any = DatabaseToAst(database, data_types);
|
||||
|
||||
const formattedSqlCode = format(parser.sqlify(dbAst , {
|
||||
database : "MySQL" // getDatabaseByDialect(database.dialect).name
|
||||
}), { language: 'sql' });
|
||||
setSql(
|
||||
formattedSqlCode
|
||||
);
|
||||
|
||||
+2
-2
@@ -10,11 +10,11 @@ export interface DatabaseType {
|
||||
|
||||
export const DBTypes: DatabaseType[] = [
|
||||
{
|
||||
name: "PostgreSql",
|
||||
name: "Postgresql",
|
||||
dialect: "postgres",
|
||||
logo: "/postgresql_logo.png"
|
||||
}, {
|
||||
name: "Mysql",
|
||||
name: "MySQL",
|
||||
dialect: "mysql",
|
||||
logo: "/mysql_logo.png"
|
||||
},
|
||||
|
||||
@@ -9,6 +9,7 @@ export const data_types = sqliteTable('data_types', {
|
||||
dialect: text("dialect", {
|
||||
enum: ["postgres", "mysql", "sqlite", "mariadb"],
|
||||
}).notNull().default("postgres"),
|
||||
type: text('type').notNull()
|
||||
});
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ import { TableInsertType } from "@/lib/schemas/table-schema";
|
||||
import { useDatabase, useDatabaseOperations } from "@/providers/database-provider/database-provider";
|
||||
import { useTableToNode } from "@/hooks/use-table-to-node";
|
||||
import { useRelationshipToEdge } from "@/hooks/use-relationship-to-edge";
|
||||
import { RelationshipInsertType } from "@/lib/schemas/relationship-schema";
|
||||
import { Cardinality, RelationshipInsertType } from "@/lib/schemas/relationship-schema";
|
||||
|
||||
// Utils and constants
|
||||
import { v4 } from "uuid";
|
||||
@@ -38,6 +38,8 @@ import { useTranslation } from "react-i18next";
|
||||
import useOverlappingTables from "@/hooks/use-overlapping-tables";
|
||||
import { useTheme } from "next-themes";
|
||||
import { Parser } from "node-sql-parser";
|
||||
import { getRelationshipSourceAndTarget } from "@/utils/relationship";
|
||||
|
||||
const parser = new Parser();
|
||||
const DatabasePage: React.FC = () => {
|
||||
|
||||
@@ -65,25 +67,29 @@ const DatabasePage: React.FC = () => {
|
||||
const edgeTypes = useMemo(() => ({ 'relationship-edge': Relationship }), []);
|
||||
|
||||
// Called when a connection is made between fields
|
||||
const onConnect = useCallback((connection: Connection) => {
|
||||
const sourceFieldId: string | undefined = (connection.sourceHandle as string).split("_").pop();
|
||||
const targetFieldId: string = (connection.targetHandle as string).replace(TARGET_PREFIX, "");
|
||||
const onConnect = useCallback(async (connection: Connection) => {
|
||||
const sourceId: string | undefined = (connection.sourceHandle as string).split("_").pop();
|
||||
const targetId: string = (connection.targetHandle as string).replace(TARGET_PREFIX, "");
|
||||
|
||||
const sourceField: FieldType | undefined = getField(connection.source, sourceFieldId as string);
|
||||
const targetField: FieldType | undefined = getField(connection.target, targetFieldId);
|
||||
const sourceField: FieldType = getField(connection.source, sourceId as string) as FieldType;
|
||||
const targetField: FieldType = getField(connection.target, targetId) as FieldType;
|
||||
|
||||
|
||||
const { sourceTableId, targetTableId, sourceFieldId, targetFieldId } = getRelationshipSourceAndTarget(connection.source, sourceField, connection.target, targetField);
|
||||
|
||||
// Check if both fields have the same type (valid relationship)
|
||||
if (sourceField?.typeId == targetField?.typeId) {
|
||||
createRelationship({
|
||||
await createRelationship({
|
||||
id: v4(),
|
||||
sourceTableId: connection.source,
|
||||
targetTableId: connection.target,
|
||||
sourceTableId,
|
||||
targetTableId,
|
||||
sourceFieldId,
|
||||
targetFieldId
|
||||
targetFieldId,
|
||||
|
||||
} as RelationshipInsertType);
|
||||
|
||||
// Add edge to the diagram
|
||||
setEdges((eds) => addEdge(connection, eds));
|
||||
//setEdges((eds) => addEdge(connection, eds));
|
||||
} else {
|
||||
// Show error toast if invalid relationship
|
||||
addToast({
|
||||
|
||||
+6
-7
@@ -2,34 +2,33 @@
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/tooltip/tooltip";
|
||||
import { Cardinality, RelationshipInsertType, RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { useDatabaseOperations } from "@/providers/database-provider/database-provider";
|
||||
|
||||
import { Button, Select, SelectItem, SharedSelection } from "@heroui/react";
|
||||
import { ChevronsLeftRightEllipsis, FileMinus2, FileOutput, Trash2 } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
|
||||
|
||||
interface RelationshipAccordionBodyProps {
|
||||
relationship: RelationshipType
|
||||
}
|
||||
|
||||
|
||||
|
||||
const RelationshipAccordionBody: React.FC<RelationshipAccordionBodyProps> = ({ relationship }) => {
|
||||
const [cardinality, setCardinality] = useState(new Set([relationship.cardinality]));
|
||||
const { editRelationship, deleteRelationship } = useDatabaseOperations();
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
|
||||
const changeCardinality = (keys: SharedSelection) => {
|
||||
|
||||
if (keys.anchorKey != relationship.cardinality)
|
||||
if (keys.anchorKey != relationship.cardinality) {
|
||||
|
||||
editRelationship({
|
||||
id: relationship.id,
|
||||
cardinality: keys.anchorKey as Cardinality
|
||||
cardinality: keys.anchorKey as Cardinality,
|
||||
|
||||
} as RelationshipInsertType);
|
||||
}
|
||||
|
||||
setCardinality(keys as any);
|
||||
}
|
||||
|
||||
@@ -11,23 +11,27 @@ import { Parser } from "node-sql-parser";
|
||||
const parser = new Parser();
|
||||
const code = `
|
||||
|
||||
-- Addresses table with a foreign key to users
|
||||
CREATE TABLE addresses (
|
||||
id INTEGER PRIMARY KEY,
|
||||
user_id INT NOT NULL,
|
||||
street VARCHAR(255),
|
||||
city VARCHAR(100),
|
||||
state VARCHAR(100),
|
||||
postal_code VARCHAR(20),
|
||||
country VARCHAR(100),
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
|
||||
CREATE TABLE \`users\` (
|
||||
id BIGINT NOT NULL PRIMARY KEY UNIQUE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
lastname VARCHAR(255) NOT NULL,
|
||||
email VARCHAR(255) NOT NULL UNIQUE,
|
||||
password VARCHAR(255) NOT NULL,
|
||||
profile_url VARCHAR(255),
|
||||
age SMALLINT,
|
||||
birthday DATE,
|
||||
created_at TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
-- Indexes to improve lookup performance
|
||||
CREATE UNIQUE INDEX idx_addresses_user_id ON addresses(user_id);
|
||||
CREATE INDEX idx_addresses_city ON addresses(city , country);
|
||||
|
||||
CREATE TABLE \`addresses\` (
|
||||
id BIGINT NOT NULL PRIMARY KEY UNIQUE,
|
||||
street_line VARCHAR(255) NOT NULL,
|
||||
latitude FLOAT,
|
||||
longitude FLOAT, -- fixed spelling
|
||||
state_id BIGINT NOT NULL,
|
||||
user_id BIGINT NOT NULL,
|
||||
FOREIGN KEY (\`user_id\`) REFERENCES \`users\` (\`id\`)
|
||||
);
|
||||
|
||||
`
|
||||
|
||||
@@ -40,7 +44,9 @@ const SqlPreview: React.FC = ({ }) => {
|
||||
const {resolvedTheme} = useTheme();
|
||||
|
||||
useEffect(() => {
|
||||
const ast = parser.astify(code )
|
||||
const ast = parser.astify(code , {
|
||||
database : "Mysql"
|
||||
} )
|
||||
console.log (ast)
|
||||
}, [])
|
||||
|
||||
|
||||
+3
-3
@@ -21,7 +21,7 @@ const FieldItem: React.FC<Props> = ({ field }) => {
|
||||
const [fieldName, setFieldName] = useState<string>(field.name);
|
||||
|
||||
const [popOverOpen, setPopOverOpen] = useState<boolean>(false);
|
||||
const { data_types } = useDatabaseOperations();
|
||||
const { data_types , grouped_data_types } = useDatabaseOperations();
|
||||
const { deleteField, editField } = useDatabaseOperations();
|
||||
|
||||
const [note, setNote] = useState<string | undefined>(field.note as string | undefined);
|
||||
@@ -109,9 +109,9 @@ const FieldItem: React.FC<Props> = ({ field }) => {
|
||||
}}
|
||||
/>
|
||||
<Autocomplete
|
||||
items={data_types}
|
||||
items={grouped_data_types}
|
||||
onSelectionChange={updateFieldType}
|
||||
|
||||
grouped
|
||||
selectedItem={selectedType}
|
||||
placeholder={t("db_controller.type")}
|
||||
/>
|
||||
|
||||
@@ -12,9 +12,6 @@ import { useDiagram } from "@/providers/diagram-provider/diagram-provider";
|
||||
import { useReactFlow } from "@xyflow/react";
|
||||
import SqlPreview from "../sql-preview";
|
||||
|
||||
|
||||
|
||||
|
||||
interface Props { }
|
||||
const PADDING_X = 40;
|
||||
const PADDING_Y = 80;
|
||||
|
||||
@@ -27,6 +27,7 @@ interface DatabaseDataContextType {
|
||||
|
||||
interface DatabaseOperationsContextType {
|
||||
data_types: DataType[],
|
||||
grouped_data_types : any ;
|
||||
// database operations
|
||||
createDatabase: (database: DatabaseInsertType) => Promise<QueryResult>,
|
||||
editDatabase: (database: DatabaseInsertType) => Promise<QueryResult>,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { RelationshipInsertType, relationships } from "@/lib/schemas/relationshi
|
||||
import DatabaseHistoryProvider from "../database-history/database-history-provider";
|
||||
import { DBDiffOperation } from "@/utils/database";
|
||||
import { DatabaseInsertType, DatabaseType, databases as databaseModel } from "@/lib/schemas/database-schema";
|
||||
import { getTimestamp } from "@/utils/utils";
|
||||
import { getTimestamp, groupBy } from "@/utils/utils";
|
||||
import { IndexInsertType, indices } from "@/lib/schemas/index-schema";
|
||||
import { field_indices } from "@/lib/schemas/field_index-schema";
|
||||
import { v4 } from "uuid";
|
||||
@@ -87,6 +87,12 @@ const DatabaseProvider: React.FC<Props> = ({ children }) => {
|
||||
where : (data_types , { eq })=> eq(data_types.dialect, (database as any).dialect)
|
||||
})
|
||||
));
|
||||
|
||||
const grouped_data_types : any = useMemo(() => {
|
||||
return groupBy(data_types , "type") ;
|
||||
} , [data_types])
|
||||
|
||||
|
||||
|
||||
// Auto-select first database if none is selected
|
||||
useEffect(() => {
|
||||
@@ -380,7 +386,8 @@ const DatabaseProvider: React.FC<Props> = ({ children }) => {
|
||||
editIndex,
|
||||
deleteIndex,
|
||||
editFieldIndices,
|
||||
data_types
|
||||
data_types ,
|
||||
grouped_data_types
|
||||
}), [
|
||||
createDatabase,
|
||||
editDatabase,
|
||||
@@ -403,7 +410,8 @@ const DatabaseProvider: React.FC<Props> = ({ children }) => {
|
||||
editIndex,
|
||||
deleteIndex,
|
||||
editFieldIndices,
|
||||
data_types
|
||||
data_types ,
|
||||
grouped_data_types
|
||||
]);
|
||||
|
||||
return (
|
||||
|
||||
+6
-6
@@ -1,6 +1,6 @@
|
||||
import { FieldType } from "@/lib/schemas/field-schema";
|
||||
import { v4 } from "uuid";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -17,13 +17,13 @@ export const getNextSequence = (fields: FieldType[]): number => {
|
||||
|
||||
|
||||
|
||||
export const cloneField = ( field : FieldType) : FieldType => {
|
||||
export const cloneField = (field: FieldType): FieldType => {
|
||||
return {
|
||||
...field ,
|
||||
id : v4() ,
|
||||
} as FieldType ;
|
||||
...field,
|
||||
id: v4(),
|
||||
} as FieldType;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import { FieldType } from "@/lib/schemas/field-schema"
|
||||
|
||||
export const getRelationshipSourceAndTarget = (sourceTableId: string, sourceField: FieldType, targetTableId: string, targetField: FieldType) => {
|
||||
if (sourceField.isPrimary || targetField.isPrimary) {
|
||||
if (sourceField.isPrimary) {
|
||||
return {
|
||||
sourceTableId: sourceTableId,
|
||||
targetTableId: targetTableId,
|
||||
sourceFieldId: sourceField.id,
|
||||
targetFieldId: targetField.id,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
|
||||
sourceTableId: targetTableId,
|
||||
targetTableId: sourceTableId,
|
||||
sourceFieldId: targetField.id,
|
||||
targetFieldId: sourceField.id,
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (sourceField.unique || targetField.unique) {
|
||||
if (sourceField.unique) {
|
||||
return {
|
||||
|
||||
sourceTableId: sourceTableId,
|
||||
targetTableId: targetTableId,
|
||||
sourceFieldId: sourceField.id,
|
||||
targetFieldId: targetField.id,
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
|
||||
sourceTableId: targetTableId,
|
||||
targetTableId: sourceTableId,
|
||||
sourceFieldId: targetField.id,
|
||||
targetFieldId: sourceField.id,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return {
|
||||
sourceTableId: sourceTableId,
|
||||
targetTableId: targetTableId,
|
||||
sourceFieldId: sourceField.id,
|
||||
targetFieldId: targetField.id,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { DatabaseType } from "@/lib/schemas/database-schema";
|
||||
import { FieldType } from "@/lib/schemas/field-schema";
|
||||
import { FieldIndexType } from "@/lib/schemas/field_index-schema";
|
||||
import { IndexType } from "@/lib/schemas/index-schema";
|
||||
import { RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { Cardinality, RelationshipType } from "@/lib/schemas/relationship-schema";
|
||||
import { TableType } from "@/lib/schemas/table-schema";
|
||||
|
||||
|
||||
@@ -16,8 +16,6 @@ export const DatabaseToAst = (database: DatabaseType, data_types: DataType[]) =>
|
||||
for (const table of database.tables) {
|
||||
dbAst.push(TableToAst({
|
||||
...table,
|
||||
sourceRelations: database.relationships.filter((relationship: RelationshipType) => relationship.sourceTableId == table.id),
|
||||
targetRelations: database.relationships.filter((relationship: RelationshipType) => relationship.targetTableId == table.id),
|
||||
}, data_types));
|
||||
|
||||
if (table.indices && table.indices.length > 0)
|
||||
@@ -28,55 +26,37 @@ export const DatabaseToAst = (database: DatabaseType, data_types: DataType[]) =>
|
||||
}, table));
|
||||
};
|
||||
|
||||
for (const relationship of database.relationships) {
|
||||
dbAst.push(relationshipToAst(relationship))
|
||||
}
|
||||
//console.log (dbAst)
|
||||
return dbAst;
|
||||
}
|
||||
|
||||
|
||||
export const TableToAst = (table: TableType, data_types: DataType[]) => {
|
||||
|
||||
const constraints: any[] = table.sourceRelations ? table.sourceRelations?.map((relationship: RelationshipType) => {
|
||||
return {
|
||||
constraint_type: "FOREIGN KEY",
|
||||
resource: "constraint",
|
||||
definition: [
|
||||
{
|
||||
type: "column_ref",
|
||||
column: relationship.sourceField.name,
|
||||
const primaryKeys: FieldType[] = table.fields.filter((field: FieldType) => field.isPrimary);
|
||||
const multiPrimaryKeys: boolean = primaryKeys.length > 1;
|
||||
const primaryKeysConstraints: any[] | undefined = multiPrimaryKeys ? [{
|
||||
constraint_type: "primary key",
|
||||
resource: "constraint",
|
||||
definition: primaryKeys.map((field: FieldType) => ({
|
||||
column: field.name,
|
||||
type: "column_ref"
|
||||
}))
|
||||
}] : [];
|
||||
|
||||
}
|
||||
],
|
||||
reference_definition: {
|
||||
on_action: [
|
||||
{
|
||||
"type": "on delete",
|
||||
"value": {
|
||||
"type": "origin",
|
||||
"value": "cascade"
|
||||
}
|
||||
}
|
||||
],
|
||||
keyword: "references",
|
||||
table: [{
|
||||
table: relationship.targetTable.name,
|
||||
}],
|
||||
definition: [
|
||||
{
|
||||
type: "column_ref",
|
||||
column: relationship.targetField.name,
|
||||
}
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
}) : [];
|
||||
|
||||
|
||||
|
||||
|
||||
const constraints: any[] = [...primaryKeysConstraints];
|
||||
const filed_definitions = table.fields.map((field: FieldType) => FieldToAst({
|
||||
...field,
|
||||
type: data_types.find((dataType: DataType) => dataType.id == field.typeId) as DataType,
|
||||
sourceRelations: table.sourceRelations?.filter((relationship: RelationshipType) => relationship.sourceFieldId == field.id),
|
||||
targetRelations: table.targetRelations?.filter((relationship: RelationshipType) => relationship.targetFieldId == field.id),
|
||||
|
||||
}));
|
||||
}, multiPrimaryKeys));
|
||||
return {
|
||||
keyword: "table",
|
||||
type: "create",
|
||||
@@ -85,12 +65,8 @@ export const TableToAst = (table: TableType, data_types: DataType[]) => {
|
||||
}],
|
||||
create_definitions: [...filed_definitions, ...constraints]
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
export const FieldToAst = (field: FieldType) => {
|
||||
|
||||
export const FieldToAst = (field: FieldType, ignorePrimaryKey: boolean = false) => {
|
||||
return {
|
||||
column: {
|
||||
type: "column_ref",
|
||||
@@ -108,9 +84,11 @@ export const FieldToAst = (field: FieldType) => {
|
||||
},
|
||||
definition: {
|
||||
dataType: field.type?.name?.toLocaleUpperCase(),
|
||||
length : field.type.name == "varchar" && field.type.dialect == "mysql" ? 255 : null ,
|
||||
|
||||
|
||||
},
|
||||
primary_key: field.isPrimary ? "primary key" : null,
|
||||
primary_key: field.isPrimary && !ignorePrimaryKey ? "primary key" : null,
|
||||
resource: "column"
|
||||
}
|
||||
}
|
||||
@@ -124,10 +102,62 @@ export const IndexToAst = (index: IndexType, table: TableType) => {
|
||||
type: "create",
|
||||
table: { table: table.name },
|
||||
keyword: "index",
|
||||
on_kw: "on",
|
||||
index_type: index.unique ? "unique" : null,
|
||||
index_columns: index.fields.map((field: FieldType) => ({
|
||||
column: field.name,
|
||||
type: "column_ref"
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export const relationshipToAst = (relationship: RelationshipType) => {
|
||||
|
||||
console.log(relationship);
|
||||
let primaryKey: FieldType = relationship.sourceField;
|
||||
let foreignKey: FieldType = relationship.targetField;
|
||||
|
||||
let sourceTable : TableType = relationship.sourceTable ;
|
||||
let targetTable : TableType = relationship.targetTable ;
|
||||
|
||||
if (relationship.cardinality == Cardinality.many_to_one) {
|
||||
primaryKey = relationship.targetField;
|
||||
foreignKey = relationship.sourceField;
|
||||
sourceTable = relationship.targetTable ;
|
||||
targetTable = relationship.sourceTable ;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
table: [{
|
||||
table: targetTable.name,
|
||||
}],
|
||||
type: "alter",
|
||||
expr: [{
|
||||
action: "add",
|
||||
resource: "constraint",
|
||||
type: "alter",
|
||||
create_definitions: {
|
||||
constraint: relationship.name ? relationship.name : null,
|
||||
constraint_type: "FOREIGN KEY",
|
||||
index: null,
|
||||
keyword: null,
|
||||
resource: "constraint",
|
||||
definition: [{
|
||||
column: foreignKey.name,
|
||||
type: "column_ref"
|
||||
}],
|
||||
reference_definition: {
|
||||
keyword: "references",
|
||||
on_action: [],
|
||||
table: [{ table: sourceTable.name }],
|
||||
definition: [{
|
||||
column: primaryKey.name,
|
||||
type: "column_ref"
|
||||
}],
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
+15
-3
@@ -52,12 +52,24 @@ function excludeFields(
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
function groupBy(array: any[], key: string) {
|
||||
return array.reduce((acc, item) => {
|
||||
const groupKey = item[key];
|
||||
if (!acc[groupKey]) {
|
||||
acc[groupKey] = [];
|
||||
}
|
||||
acc[groupKey].push(item);
|
||||
return acc;
|
||||
}, {});
|
||||
}
|
||||
|
||||
|
||||
|
||||
export {
|
||||
areArraysEqual,
|
||||
getTimestamp,
|
||||
excludeFields ,
|
||||
|
||||
excludeFields,
|
||||
groupBy
|
||||
}
|
||||
Reference in New Issue
Block a user