diff --git a/frontend/packages/db-structure/src/parser/__snapshots__/index.test.ts.snap b/frontend/packages/db-structure/src/parser/__snapshots__/index.test.ts.snap index 3bbeee949..0b5655cc1 100644 --- a/frontend/packages/db-structure/src/parser/__snapshots__/index.test.ts.snap +++ b/frontend/packages/db-structure/src/parser/__snapshots__/index.test.ts.snap @@ -91,7 +91,7 @@ exports[`parse > should parse postgresql to JSON correctly 1`] = ` "unique": true, }, }, - "comment": null, + "comment": "store our users.", "indices": { "index_users_on_id_and_email": { "columns": [ diff --git a/frontend/packages/db-structure/src/parser/schemarb/index.test.ts b/frontend/packages/db-structure/src/parser/schemarb/index.test.ts index 71a98f77e..d9ed5a7f2 100644 --- a/frontend/packages/db-structure/src/parser/schemarb/index.test.ts +++ b/frontend/packages/db-structure/src/parser/schemarb/index.test.ts @@ -4,7 +4,7 @@ import { aColumn, aDBStructure, aTable, anIndex } from '../../schema/index.js' import { processor } from './index.js' describe(processor, () => { - describe('should parse create_table correctry', () => { + describe('should parse create_table correctly', () => { const userTable = (override?: Partial) => aDBStructure({ tables: { diff --git a/frontend/packages/db-structure/src/parser/sql/input/postgresql_schema1.in.sql b/frontend/packages/db-structure/src/parser/sql/input/postgresql_schema1.in.sql index d1d06ad53..706f7d638 100644 --- a/frontend/packages/db-structure/src/parser/sql/input/postgresql_schema1.in.sql +++ b/frontend/packages/db-structure/src/parser/sql/input/postgresql_schema1.in.sql @@ -11,3 +11,4 @@ CREATE TABLE posts ( ); CREATE UNIQUE INDEX index_users_on_id_and_email ON public.users USING btree (id, email); +COMMENT ON TABLE users IS 'store our users.'; diff --git a/frontend/packages/db-structure/src/parser/sql/postgresql/converter.ts b/frontend/packages/db-structure/src/parser/sql/postgresql/converter.ts index e539fedd0..30721f020 100644 --- a/frontend/packages/db-structure/src/parser/sql/postgresql/converter.ts +++ b/frontend/packages/db-structure/src/parser/sql/postgresql/converter.ts @@ -1,7 +1,9 @@ import type { + CommentStmt, Constraint, CreateStmt, IndexStmt, + List, Node, String as PgString, } from '@pgsql/types' @@ -40,6 +42,10 @@ export const convertToDBStructure = (ast: RawStmtWrapper[]): DBStructure => { return 'IndexStmt' in stmt } + function isCommentStmt(stmt: Node): stmt is { CommentStmt: CommentStmt } { + return 'CommentStmt' in stmt + } + function handleCreateStmt(createStmt: CreateStmt) { if (!createStmt || !createStmt.relation || !createStmt.tableElts) return @@ -212,6 +218,37 @@ export const convertToDBStructure = (ast: RawStmtWrapper[]): DBStructure => { } } + function handleCommentStmt(commentStmt: CommentStmt) { + if (commentStmt.objtype !== 'OBJECT_TABLE') return + const objectNode = commentStmt.object + if (!objectNode) return + + const isList = (stmt: Node): stmt is { List: List } => 'List' in stmt + if (!isList(objectNode)) return + + // Handles statements like `COMMENT ON TABLE IS '';`. + // NOTE: PostgreSQL allows only one comment to be added to one table per statement, + // so we can reasonably assume the number of `` elements is 1. + const item = objectNode.List?.items?.[0] + if (!item) return + const tableName = + 'String' in item && + typeof item.String === 'object' && + item.String !== null && + 'sval' in item.String && + item.String.sval + + if (!tableName) return + if (!tables[tableName]) return + const comment = commentStmt.comment + if (!comment) return + + tables[tableName] = { + ...tables[tableName], + comment, + } + } + if (!ast) { return { tables: {}, @@ -229,6 +266,8 @@ export const convertToDBStructure = (ast: RawStmtWrapper[]): DBStructure => { handleCreateStmt(stmt.CreateStmt) } else if (isIndexStmt(stmt)) { handleIndexStmt(stmt.IndexStmt) + } else if (isCommentStmt(stmt)) { + handleCommentStmt(stmt.CommentStmt) } } diff --git a/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts b/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts index ae2aa7e0e..1b16ac8d1 100644 --- a/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts +++ b/frontend/packages/db-structure/src/parser/sql/postgresql/index.test.ts @@ -4,7 +4,7 @@ import { aColumn, aDBStructure, aTable } from '../../../schema/index.js' import { processor } from './index.js' describe(processor, () => { - describe('should parse create_table correctry', () => { + describe('should parse create_table correctly', () => { const userTable = (override?: Partial
) => aDBStructure({ tables: { @@ -28,10 +28,27 @@ describe(processor, () => { indices: { ...override?.indices, }, + comment: override?.comment ?? null, }), }, }) + it('comment', async () => { + const result = await processor(/* PostgreSQL */ ` + CREATE TABLE users ( + id SERIAL PRIMARY KEY, + name VARCHAR(255) + ); + COMMENT ON TABLE users IS 'store our users.'; + `) + + const expected = userTable({ + comment: 'store our users.', + }) + + expect(result).toEqual(expected) + }) + it('not null', async () => { const result = await processor(/* sql */ ` CREATE TABLE users (