Skip to content

Commit 4686238

Browse files
committed
add support to send add multiple column to a table
1 parent 3514106 commit 4686238

File tree

3 files changed

+84
-68
lines changed

3 files changed

+84
-68
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ typings/
5151
# Optional npm cache directory
5252
.npm
5353

54+
# npm config
55+
.npmrc
56+
5457
# Optional eslint cache
5558
.eslintcache
5659

src/lib/PostgresMetaColumns.ts

+76-64
Original file line numberDiff line numberDiff line change
@@ -115,89 +115,101 @@ WHERE
115115
}
116116
}
117117

118-
async create({
119-
table_id,
120-
name,
121-
type,
122-
default_value,
123-
default_value_format = 'literal',
124-
is_identity = false,
125-
identity_generation = 'BY DEFAULT',
126-
// Can't pick a value as default since regular columns are nullable by default but PK columns aren't
127-
is_nullable,
128-
is_primary_key = false,
129-
is_unique = false,
130-
comment,
131-
check,
132-
}: {
133-
table_id: number
134-
name: string
135-
type: string
136-
default_value?: any
137-
default_value_format?: 'expression' | 'literal'
138-
is_identity?: boolean
139-
identity_generation?: 'BY DEFAULT' | 'ALWAYS'
140-
is_nullable?: boolean
141-
is_primary_key?: boolean
142-
is_unique?: boolean
143-
comment?: string
144-
check?: string
145-
}): Promise<PostgresMetaResult<PostgresColumn>> {
118+
async create(
119+
columns: {
120+
table_id: number
121+
name: string
122+
type: string
123+
default_value?: any
124+
default_value_format?: 'expression' | 'literal'
125+
is_identity?: boolean
126+
identity_generation?: 'BY DEFAULT' | 'ALWAYS'
127+
is_nullable?: boolean
128+
is_primary_key?: boolean
129+
is_unique?: boolean
130+
comment?: string
131+
check?: string
132+
}[]
133+
): Promise<PostgresMetaResult<PostgresColumn[]>> {
134+
const { table_id } = columns[0]
135+
146136
const { data, error } = await this.metaTables.retrieve({ id: table_id })
147137
if (error) {
148138
return { data: null, error }
149139
}
150140
const { name: table, schema } = data!
141+
let sql = `BEGIN;`
142+
for (const column of columns) {
143+
const {
144+
name,
145+
type,
146+
default_value,
147+
default_value_format = 'literal',
148+
is_identity = false,
149+
identity_generation = 'BY DEFAULT',
150+
// Can't pick a value as default since regular columns are nullable by default but PK columns aren't
151+
is_nullable,
152+
is_primary_key = false,
153+
is_unique = false,
154+
comment,
155+
check,
156+
} = column
157+
sql += `
158+
ALTER TABLE ${ident(schema)}.${ident(table)} ADD COLUMN ${ident(name)} ${typeIdent(type)}`
151159

152-
let defaultValueClause = ''
153-
if (is_identity) {
154-
if (default_value !== undefined) {
155-
return {
156-
data: null,
157-
error: { message: 'Columns cannot both be identity and have a default value' },
160+
let defaultValueClause = ''
161+
if (is_identity) {
162+
if (default_value !== undefined) {
163+
return {
164+
data: null,
165+
error: { message: 'Columns cannot both be identity and have a default value' },
166+
}
158167
}
159-
}
160168

161-
defaultValueClause = `GENERATED ${identity_generation} AS IDENTITY`
162-
} else {
163-
if (default_value === undefined) {
164-
// skip
165-
} else if (default_value_format === 'expression') {
166-
defaultValueClause = `DEFAULT ${default_value}`
169+
defaultValueClause = `GENERATED ${identity_generation} AS IDENTITY`
167170
} else {
168-
defaultValueClause = `DEFAULT ${literal(default_value)}`
171+
if (default_value === undefined) {
172+
// skip
173+
} else if (default_value_format === 'expression') {
174+
defaultValueClause = `DEFAULT ${default_value}`
175+
} else {
176+
defaultValueClause = `DEFAULT ${literal(default_value)}`
177+
}
169178
}
170-
}
171179

172-
let isNullableClause = ''
173-
if (is_nullable !== undefined) {
174-
isNullableClause = is_nullable ? 'NULL' : 'NOT NULL'
180+
let isNullableClause = ''
181+
if (is_nullable !== undefined) {
182+
isNullableClause = is_nullable ? 'NULL' : 'NOT NULL'
183+
}
184+
const isPrimaryKeyClause = is_primary_key ? 'PRIMARY KEY' : ''
185+
const isUniqueClause = is_unique ? 'UNIQUE' : ''
186+
const checkSql = check === undefined ? '' : `CHECK (${check})`
187+
const commentSql =
188+
comment === undefined
189+
? ''
190+
: `COMMENT ON COLUMN ${ident(schema)}.${ident(table)}.${ident(name)} IS ${literal(
191+
comment
192+
)}`
193+
194+
sql += `
195+
${defaultValueClause}
196+
${isNullableClause}
197+
${isPrimaryKeyClause}
198+
${isUniqueClause}
199+
${checkSql};
200+
${commentSql};`
175201
}
176-
const isPrimaryKeyClause = is_primary_key ? 'PRIMARY KEY' : ''
177-
const isUniqueClause = is_unique ? 'UNIQUE' : ''
178-
const checkSql = check === undefined ? '' : `CHECK (${check})`
179-
const commentSql =
180-
comment === undefined
181-
? ''
182-
: `COMMENT ON COLUMN ${ident(schema)}.${ident(table)}.${ident(name)} IS ${literal(comment)}`
183202

184-
const sql = `
185-
BEGIN;
186-
ALTER TABLE ${ident(schema)}.${ident(table)} ADD COLUMN ${ident(name)} ${typeIdent(type)}
187-
${defaultValueClause}
188-
${isNullableClause}
189-
${isPrimaryKeyClause}
190-
${isUniqueClause}
191-
${checkSql};
192-
${commentSql};
193-
COMMIT;`
203+
sql += `COMMIT;`
194204
{
195205
const { error } = await this.query(sql)
196206
if (error) {
197207
return { data: null, error }
198208
}
199209
}
200-
return await this.retrieve({ name, table, schema })
210+
const res = await this.list({ tableId: table_id, includedSchemas: [schema] })
211+
res.data = res.data?.filter((d) => columns.find((c) => d.name === c.name)) as PostgresColumn[]
212+
return res
201213
}
202214

203215
async update(

src/server/routes/columns.ts

+5-4
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,9 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => {
140140
headers: Type.Object({
141141
pg: Type.String(),
142142
}),
143-
body: postgresColumnCreateSchema,
143+
body: Type.Union([postgresColumnCreateSchema, Type.Array(postgresColumnCreateSchema)]),
144144
response: {
145-
200: postgresColumnSchema,
145+
200: Type.Union([postgresColumnSchema, Type.Array(postgresColumnSchema)]),
146146
400: Type.Object({
147147
error: Type.String(),
148148
}),
@@ -153,7 +153,8 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => {
153153
const connectionString = request.headers.pg
154154

155155
const pgMeta = new PostgresMeta({ ...DEFAULT_POOL_CONFIG, connectionString })
156-
const { data, error } = await pgMeta.columns.create(request.body)
156+
const colMutations = Array.isArray(request.body) ? request.body : [request.body]
157+
const { data, error } = await pgMeta.columns.create(colMutations)
157158
await pgMeta.end()
158159
if (error) {
159160
request.log.error({ error, request: extractRequestForLogging(request) })
@@ -162,7 +163,7 @@ const route: FastifyPluginAsyncTypebox = async (fastify) => {
162163
return { error: error.message }
163164
}
164165

165-
return data
166+
return Array.isArray(request.body) ? data : data[0]
166167
}
167168
)
168169

0 commit comments

Comments
 (0)