Skip to content

Commit

Permalink
Move the schema field from database to table model
Browse files Browse the repository at this point in the history
  • Loading branch information
tjdammann committed Apr 11, 2024
1 parent 0e555a7 commit d5dd36b
Show file tree
Hide file tree
Showing 18 changed files with 241 additions and 366 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/*
Warnings:
- You are about to drop the column `schema` on the `database` table. All the data in the column will be lost.
*/
-- AlterTable
ALTER TABLE "database" DROP COLUMN "schema";
1 change: 0 additions & 1 deletion backend/prisma/schema.prisma
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ model database {
external_name String
connection_url String
encryption_vector String
schema String
organization_id String
require_ssl Boolean
tables table[]
Expand Down
11 changes: 0 additions & 11 deletions backend/src/databases/databases.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,24 +111,13 @@ export class DatabasesService {
data: {
name: createDatabaseObj.name,
external_name: externalName,
schema: createDatabaseObj.schema ?? "public",
require_ssl: createDatabaseObj.require_ssl,
connection_url: cypherText,
encryption_vector: encryptionVector,
organization_id: orgId,
},
});

// Get current schemas and assign default schema for database
const schemas = await this.findAllSchemas(database.id);

if (schemas.length > 0) {
const defaultSchema = schemas.includes("public") ? "public" : schemas[0];
await this.updateDatabase(database.id, {
schema: defaultSchema,
});
}

assert(database, "Database creation error");

return database;
Expand Down
1 change: 0 additions & 1 deletion backend/src/definitions/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ export const DatabaseSchema = z.object({
connection_url: z.string(),
encryption_vector: z.string(),
organization_id: z.string(),
schema: z.string(),
require_ssl: z.boolean(),
created_at: z.date(),
updated_at: z.date(),
Expand Down
48 changes: 22 additions & 26 deletions backend/src/postgres-adapter/postgres-adapter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ export class PostgresAdapterService {

return pool.connect();
}

async run(createDatabaseQueryDto: CreateDatabaseQueryDto) {
const client = await this.getClientForDatabase(
createDatabaseQueryDto.databaseId,
Expand All @@ -90,32 +91,33 @@ export class PostgresAdapterService {

async getAllTableSchema(
databaseId: string,
): Promise<Record<string, Record<string, ExternalColumn>>> {
): Promise<Record<string, Record<string, Record<string, ExternalColumn>>>> {
const database = await this.databaseService.findOne(databaseId);
const client = await this.getClientForDatabase(databaseId);
assert(database, "Database not found");

try {
const result = await client.query(
`SELECT
*
FROM
information_schema.columns
WHERE
table_schema = $1;`,
[database.schema || "public"],
`SELECT * FROM information_schema.columns`,
);

// map returned columns into tables
// Build a map of schemata to tables to columns
const columns = result.rows;
const tables = {};
const columnMap = {};
for (const column of columns) {
if (!tables[column.table_name]) {
tables[column.table_name] = {};
if (!columnMap[column.table_schema]) {
columnMap[column.table_schema] = {};
}

if (!columnMap[column.table_schema][column.table_name]) {
columnMap[column.table_schema][column.table_name] = {};
}
tables[column.table_name][column.column_name] = columnMapping(column);

columnMap[column.table_schema][column.table_name][column.column_name] =
columnMapping(column);
}
return tables;

return columnMap;
} catch (e) {
console.log(e);
throw e;
Expand All @@ -131,14 +133,12 @@ export class PostgresAdapterService {

try {
const result = await client.query(
`select schema_name
from information_schema.schemata`,
`SELECT schema_name FROM information_schema.schemata`,
);
const columns = result.rows;
const schemata = columns.map((column) => column.schema_name);

const schemas = columns.map((column) => column.schema_name);

return schemas;
return schemata;
} catch (e) {
console.log(e);
throw e;
Expand All @@ -158,7 +158,9 @@ export class PostgresAdapterService {
tc.constraint_name,
tc.constraint_type,
tc.table_name,
tc.table_schema,
kcu.column_name,
ccu.table_schema AS foreign_schema_name,
ccu.table_name AS foreign_table_name,
ccu.column_name AS foreign_column_name
FROM
Expand All @@ -172,13 +174,7 @@ export class PostgresAdapterService {
ON tc.constraint_name = ccu.constraint_name
AND tc.table_schema = ccu.table_schema
WHERE
tc.constraint_type IN ('FOREIGN KEY', 'PRIMARY KEY', 'UNIQUE')
AND tc.table_schema = $1
ORDER BY
tc.table_name,
tc.constraint_type,
kcu.column_name;`,
[database.schema || "public"],
tc.constraint_type IN ('FOREIGN KEY', 'PRIMARY KEY', 'UNIQUE');`,
);

return result.rows;
Expand Down
85 changes: 47 additions & 38 deletions backend/src/relations/relations.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,53 +57,62 @@ export class RelationsService {
_.forEach(externalConstraints, (constraint) => {
if (constraint.constraint_type === "FOREIGN KEY") {
const table1 = _.find(tables, (table) => {
return table.external_name === constraint.foreign_table_name;
return (
table.schema === constraint.foreign_schema_name &&
table.external_name === constraint.foreign_table_name
);
});
assert(table1, `Table not found: ${constraint.foreign_table_name}`);

const table2 = _.find(tables, (table) => {
return table.external_name === constraint.table_name;
});
assert(table2, `Table not found: ${constraint.table_name}`);

// To determine the relation type, check for uniqueness of the current column
// If the column is unique, then the relation is one-to-one (otherwise it’s one-to-many)
const isUnique = _.some(externalConstraints, (c) => {
return (
c.table_name === constraint.table_name &&
c.column_name === constraint.column_name &&
(c.constraint_type === "UNIQUE" ||
c.constraint_type === "PRIMARY KEY")
table.schema === constraint.table_schema &&
table.external_name === constraint.table_name
);
});

const relationType = (
isUnique ? "one_to_one" : "one_to_many"
) as RelationType;

const foundConstraint = _.find(parsedExistingRelations, (relation) => {
return (
relation.table_1 === table1.id &&
relation.table_2 === table2.id &&
relation.column_1 === constraint.foreign_column_name &&
relation.column_2 === constraint.column_name &&
relation.type === relationType
if (table1 && table2) {
// To determine the relation type, check for uniqueness of the current column
// If the column is unique, then the relation is one-to-one (otherwise it’s one-to-many)
const isUnique = _.some(externalConstraints, (c) => {
return (
c.table_name === constraint.table_name &&
c.column_name === constraint.column_name &&
(c.constraint_type === "UNIQUE" ||
c.constraint_type === "PRIMARY KEY")
);
});

const relationType = (
isUnique ? "one_to_one" : "one_to_many"
) as RelationType;

const foundConstraint = _.find(
parsedExistingRelations,
(relation) => {
return (
relation.table_1 === table1.id &&
relation.table_2 === table2.id &&
relation.column_1 === constraint.foreign_column_name &&
relation.column_2 === constraint.column_name &&
relation.type === relationType
);
},
);
});

// If the relation isn't found, add it in the db
if (!foundConstraint) {
const newRelation = {
database_id: databaseId,
type: relationType,
generated: true,
table_1: table1.id,
table_2: table2.id,
column_1: constraint.foreign_column_name,
column_2: constraint.column_name,
};

promises.push(this.create(newRelation));
// If the relation isn't found, add it in the db
if (!foundConstraint) {
const newRelation = {
database_id: databaseId,
type: relationType,
generated: true,
table_1: table1.id,
table_2: table2.id,
column_1: constraint.foreign_column_name,
column_2: constraint.column_name,
};

promises.push(this.create(newRelation));
}
}
}
});
Expand Down
Loading

0 comments on commit d5dd36b

Please sign in to comment.