Skip to content

Commit 7526740

Browse files
committed
feat: support COMMENTs on /tables & /columns
This adds support for adding COMMENTs on /tables & /columns through POST and PATCH, plus updated tests (and minor refactorings).
1 parent 33174bd commit 7526740

File tree

5 files changed

+50
-10
lines changed

5 files changed

+50
-10
lines changed

src/api/columns.ts

+16-1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ const addColumnSqlize = ({
105105
is_nullable = true,
106106
is_primary_key = false,
107107
is_unique = false,
108+
comment,
108109
}: {
109110
schema: string
110111
table: string
@@ -115,20 +116,27 @@ const addColumnSqlize = ({
115116
is_nullable?: boolean
116117
is_primary_key?: boolean
117118
is_unique?: boolean
119+
comment?: string
118120
}) => {
119121
const defaultValueSql = default_value === undefined ? '' : `DEFAULT ${default_value}`
120122
const isIdentitySql = is_identity ? 'GENERATED BY DEFAULT AS IDENTITY' : ''
121123
const isNullableSql = is_nullable ? 'NULL' : 'NOT NULL'
122124
const isPrimaryKeySql = is_primary_key ? 'PRIMARY KEY' : ''
123125
const isUniqueSql = is_unique ? 'UNIQUE' : ''
126+
const commentSql =
127+
comment === undefined
128+
? ''
129+
: `COMMENT ON COLUMN "${schema}"."${table}"."${name}" IS '${comment}';`
124130

125131
return `
126132
ALTER TABLE "${schema}"."${table}" ADD COLUMN "${name}" "${type}"
127133
${defaultValueSql}
128134
${isIdentitySql}
129135
${isNullableSql}
130136
${isPrimaryKeySql}
131-
${isUniqueSql}`
137+
${isUniqueSql};
138+
139+
${commentSql}`
132140
}
133141
const getColumnSqlize = (tableId: number, name: string) => {
134142
return SQL``.append(columns).append(SQL` WHERE c.oid = ${tableId} AND column_name = ${name}`)
@@ -147,6 +155,7 @@ const alterColumnSqlize = ({
147155
drop_default = false,
148156
default_value,
149157
is_nullable,
158+
comment,
150159
}: {
151160
schema: string
152161
table: string
@@ -156,6 +165,7 @@ const alterColumnSqlize = ({
156165
drop_default?: boolean
157166
default_value?: any
158167
is_nullable?: boolean
168+
comment?: string
159169
}) => {
160170
const nameSql =
161171
name === undefined
@@ -177,13 +187,18 @@ const alterColumnSqlize = ({
177187
? `ALTER TABLE "${schema}"."${table}" ALTER COLUMN "${oldName}" DROP NOT NULL;`
178188
: `ALTER TABLE "${schema}"."${table}" ALTER COLUMN "${oldName}" SET NOT NULL;`
179189
}
190+
const commentSql =
191+
comment === undefined
192+
? ''
193+
: `COMMENT ON COLUMN "${schema}"."${table}"."${oldName}" IS '${comment}';`
180194

181195
// nameSql must be last.
182196
return `
183197
BEGIN;
184198
${isNullableSql}
185199
${defaultValueSql}
186200
${typeSql}
201+
${commentSql}
187202
${nameSql}
188203
COMMIT;`
189204
}

src/api/tables.ts

+20-5
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,10 @@ router.get('/', async (req, res) => {
3232
router.post('/', async (req, res) => {
3333
try {
3434
const pcConnection: string = req.headers.pg.toString()
35-
const schema: string = req.body.schema || 'public'
36-
const name: string = req.body.name
35+
const { schema = 'public', name } = req.body
3736

3837
// Create the table
39-
const createTableSql = createTable(name, schema)
38+
const createTableSql = createTableSqlize(req.body)
4039
const alterSql = alterTableSql(req.body)
4140
const transaction = toTransaction([createTableSql, alterSql])
4241
await RunQuery(pcConnection, transaction)
@@ -144,8 +143,19 @@ const selectSingleByName = (sqlTemplates, schema: string, name: string) => {
144143
const { tables } = sqlTemplates
145144
return `${tables} and table_schema = '${schema}' and table_name = '${name}';`.trim()
146145
}
147-
const createTable = (name: string, schema: string = 'postgres') => {
148-
return `CREATE TABLE IF NOT EXISTS "${schema}"."${name}" ();`.trim()
146+
const createTableSqlize = ({
147+
name,
148+
schema = 'public',
149+
comment,
150+
}: {
151+
name: string
152+
schema?: string
153+
comment?: string
154+
}) => {
155+
const tableSql = `CREATE TABLE IF NOT EXISTS "${schema}"."${name}" ();`
156+
const commentSql =
157+
comment === undefined ? '' : `COMMENT ON TABLE "${schema}"."${name}" IS '${comment}';`
158+
return `${tableSql} ${commentSql}`
149159
}
150160
const alterTableName = (previousName: string, newName: string, schema: string) => {
151161
return `ALTER TABLE "${schema}"."${previousName}" RENAME TO "${newName}";`.trim()
@@ -155,11 +165,13 @@ const alterTableSql = ({
155165
name,
156166
rls_enabled,
157167
rls_forced,
168+
comment,
158169
}: {
159170
schema?: string
160171
name: string
161172
rls_enabled?: boolean
162173
rls_forced?: boolean
174+
comment?: string
163175
}) => {
164176
let alter = `ALTER table "${schema}"."${name}"`
165177
let enableRls = ''
@@ -174,9 +186,12 @@ const alterTableSql = ({
174186
let disable = `${alter} NO FORCE ROW LEVEL SECURITY;`
175187
forceRls = rls_forced ? enable : disable
176188
}
189+
const commentSql =
190+
comment === undefined ? '' : `COMMENT ON TABLE "${schema}"."${name}" IS '${comment}';`
177191
return `
178192
${enableRls}
179193
${forceRls}
194+
${commentSql}
180195
`.trim()
181196
}
182197
const dropTableSql = (schema: string, name: string, cascade: boolean) => {

src/lib/sql/columns.sql

+3-2
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ SELECT
2424
ORDER BY
2525
enums.enumsortorder
2626
)
27-
) AS enums
27+
) AS enums,
28+
col_description(c.oid, ordinal_position) AS comment
2829
FROM
2930
information_schema.columns
3031
JOIN pg_class c ON quote_ident(table_schema) :: regnamespace = c.relnamespace
31-
AND c.relname = table_name
32+
AND c.relname = table_name

src/lib/sql/tables.sql

+2-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ SELECT
2929
vacuum_count :: bigint,
3030
autovacuum_count :: bigint,
3131
analyze_count :: bigint,
32-
autoanalyze_count :: bigint
32+
autoanalyze_count :: bigint,
33+
obj_description(c.oid) AS comment
3334
FROM
3435
information_schema.tables
3536
JOIN pg_class c ON quote_ident(table_schema)::regnamespace = c.relnamespace

test/integration/index.spec.js

+9-1
Original file line numberDiff line numberDiff line change
@@ -229,8 +229,9 @@ describe('/tables', async () => {
229229
assert.equal(true, !!included)
230230
})
231231
it('POST /tables should create a table', async () => {
232-
const { data: newTable } = await axios.post(`${URL}/tables`, { name: 'test' })
232+
const { data: newTable } = await axios.post(`${URL}/tables`, { name: 'test', comment: 'foo' })
233233
assert.equal(`${newTable.schema}.${newTable.name}`, 'public.test')
234+
assert.equal(newTable.comment, 'foo')
234235

235236
const { data: tables } = await axios.get(`${URL}/tables`)
236237
const newTableExists = tables.some((table) => table.id === newTable.id)
@@ -246,10 +247,12 @@ describe('/tables', async () => {
246247
name: 'test a',
247248
rls_enabled: true,
248249
rls_forced: true,
250+
comment: 'foo',
249251
})
250252
assert.equal(updatedTable.name, `test a`)
251253
assert.equal(updatedTable.rls_enabled, true)
252254
assert.equal(updatedTable.rls_forced, true)
255+
assert.equal(updatedTable.comment, 'foo')
253256
await axios.delete(`${URL}/tables/${newTable.id}`)
254257
})
255258
it('DELETE /tables', async () => {
@@ -268,6 +271,7 @@ describe('/tables', async () => {
268271
type: 'int2',
269272
default_value: 42,
270273
is_nullable: false,
274+
comment: 'foo',
271275
// Currently no way to test these:
272276
// isPrimaryKey: true,
273277
// isUnique: true,
@@ -280,6 +284,7 @@ describe('/tables', async () => {
280284
)
281285
assert.equal(newColumn.default_value, 42)
282286
assert.equal(newColumn.is_nullable, false)
287+
assert.equal(newColumn.comment, 'foo')
283288

284289
await axios.delete(`${URL}/columns/${newTable.id}.1`)
285290
await axios.delete(`${URL}/tables/${newTable.id}`)
@@ -291,13 +296,15 @@ describe('/tables', async () => {
291296
name: 'foo',
292297
type: 'int2',
293298
default_value: 42,
299+
comment: 'foo',
294300
})
295301

296302
await axios.patch(`${URL}/columns/${newTable.id}.1`, {
297303
name: 'foo bar',
298304
type: 'int4',
299305
drop_default: true,
300306
is_nullable: false,
307+
comment: 'bar',
301308
})
302309

303310
const { data: columns } = await axios.get(`${URL}/columns`)
@@ -307,6 +314,7 @@ describe('/tables', async () => {
307314
)
308315
assert.equal(updatedColumn.default_value, null)
309316
assert.equal(updatedColumn.is_nullable, false)
317+
assert.equal(updatedColumn.comment, 'bar')
310318

311319
await axios.delete(`${URL}/columns/${newTable.id}.1`)
312320
await axios.delete(`${URL}/tables/${newTable.id}`)

0 commit comments

Comments
 (0)