diff --git a/packages/pg-meta/src/pg-meta-columns.ts b/packages/pg-meta/src/pg-meta-columns.ts index 34d43ed4c2a..c99c5fc3279 100644 --- a/packages/pg-meta/src/pg-meta-columns.ts +++ b/packages/pg-meta/src/pg-meta-columns.ts @@ -2,7 +2,7 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' import { filterByList } from './helpers' -import { ident, literal } from './pg-format' +import { ident, literal, safeSql, type SafeSqlFragment } from './pg-format' import { COLUMNS_SQL } from './sql/columns' const pgColumnZod = z.object({ @@ -46,10 +46,10 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgColumnArrayZod } { - let sql = ` + let sql = safeSql` with columns as (${COLUMNS_SQL}) select @@ -67,16 +67,16 @@ where ) if (filter) { - sql += ` and schema ${filter}` + sql = safeSql`${sql} and schema ${filter}` } if (tableId !== undefined) { - sql += ` and table_id = ${literal(tableId)} ` + sql = safeSql`${sql} and table_id = ${literal(tableId)} ` } if (limit) { - sql = `${sql} limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql = `${sql} offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -86,20 +86,20 @@ where type ColumnIdentifier = Pick | Pick -function getIdentifierWhereClause(identifier: ColumnIdentifier) { +function getIdentifierWhereClause(identifier: ColumnIdentifier): SafeSqlFragment { if ('id' in identifier && identifier.id) { - return `${ident('id')} = ${literal(identifier.id)}` + return safeSql`${ident('id')} = ${literal(identifier.id)}` } else if ('name' in identifier && identifier.name && identifier.schema && identifier.table) { - return `schema = ${literal(identifier.schema)} AND ${ident('table')} = ${literal(identifier.table)} AND name = ${literal(identifier.name)}` + return safeSql`schema = ${literal(identifier.schema)} AND ${ident('table')} = ${literal(identifier.table)} AND name = ${literal(identifier.name)}` } throw new Error('Must provide either id or schema, name and table') } function retrieve(identifier: ColumnIdentifier): { - sql: string + sql: SafeSqlFragment zod: typeof pgColumnOptionalZod } { - const sql = `WITH columns AS (${COLUMNS_SQL}) SELECT * FROM columns WHERE ${getIdentifierWhereClause(identifier)};` + const sql = safeSql`WITH columns AS (${COLUMNS_SQL}) SELECT * FROM columns WHERE ${getIdentifierWhereClause(identifier)};` return { sql, zod: pgColumnOptionalZod, @@ -393,10 +393,8 @@ COMMIT;` function remove( column: Pick, { cascade = false } = {} -): { sql: string } { - const sql = `ALTER TABLE ${ident(column.schema)}.${ident(column.table)} DROP COLUMN ${ident( - column.name - )} ${cascade ? 'CASCADE' : 'RESTRICT'};` +): { sql: SafeSqlFragment } { + const sql = safeSql`ALTER TABLE ${ident(column.schema)}.${ident(column.table)} DROP COLUMN ${ident(column.name)} ${cascade ? safeSql`CASCADE` : safeSql`RESTRICT`};` return { sql } } diff --git a/packages/pg-meta/src/pg-meta-config.ts b/packages/pg-meta/src/pg-meta-config.ts index 3a688c31e1c..867b3efbb79 100644 --- a/packages/pg-meta/src/pg-meta-config.ts +++ b/packages/pg-meta/src/pg-meta-config.ts @@ -1,5 +1,6 @@ import { z } from 'zod' +import { literal, safeSql, type SafeSqlFragment } from './pg-format' import { CONFIG_SQL } from './sql/config' const pgConfigZod = z.object({ @@ -33,15 +34,15 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgConfigArrayZod } { let sql = CONFIG_SQL if (limit) { - sql += ` LIMIT ${limit}` + sql = safeSql`${sql} LIMIT ${literal(limit)}` } if (offset) { - sql += ` OFFSET ${offset}` + sql = safeSql`${sql} OFFSET ${literal(offset)}` } return { sql, diff --git a/packages/pg-meta/src/pg-meta-extensions.ts b/packages/pg-meta/src/pg-meta-extensions.ts index 096bf257af7..c59778dbb27 100644 --- a/packages/pg-meta/src/pg-meta-extensions.ts +++ b/packages/pg-meta/src/pg-meta-extensions.ts @@ -1,6 +1,6 @@ import { z } from 'zod' -import { ident, literal } from './pg-format' +import { ident, literal, safeSql, type SafeSqlFragment } from './pg-format' import { EXTENSIONS_SQL } from './sql/extensions' const pgExtensionZod = z.object({ @@ -23,15 +23,15 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgExtensionArrayZod } { let sql = EXTENSIONS_SQL if (limit) { - sql = `${sql} LIMIT ${limit}` + sql = safeSql`${sql} LIMIT ${literal(limit)}` } if (offset) { - sql = `${sql} OFFSET ${offset}` + sql = safeSql`${sql} OFFSET ${literal(offset)}` } return { sql, @@ -40,10 +40,10 @@ function list({ } function retrieve({ name }: { name: string }): { - sql: string + sql: SafeSqlFragment zod: typeof pgExtensionOptionalZod } { - const sql = `${EXTENSIONS_SQL} WHERE name = ${literal(name)};` + const sql = safeSql`${EXTENSIONS_SQL} WHERE name = ${literal(name)};` return { sql, zod: pgExtensionOptionalZod, @@ -58,13 +58,13 @@ type ExtensionCreateParams = { } function create({ name, schema, version, cascade = false }: ExtensionCreateParams): { - sql: string + sql: SafeSqlFragment } { - const sql = ` + const sql = safeSql` CREATE EXTENSION ${ident(name)} - ${schema === undefined ? '' : `SCHEMA ${ident(schema)}`} - ${version === undefined ? '' : `VERSION ${literal(version)}`} - ${cascade ? 'CASCADE' : ''};` + ${schema === undefined ? safeSql`` : safeSql`SCHEMA ${ident(schema)}`} + ${version === undefined ? safeSql`` : safeSql`VERSION ${literal(version)}`} + ${cascade ? safeSql`CASCADE` : safeSql``};` return { sql } } @@ -77,17 +77,19 @@ type ExtensionUpdateParams = { function update( name: string, { update = false, version, schema }: ExtensionUpdateParams -): { sql: string } { - let updateSql = '' +): { sql: SafeSqlFragment } { + let updateSql = safeSql`` if (update) { - updateSql = `ALTER EXTENSION ${ident(name)} UPDATE ${ - version === undefined ? '' : `TO ${literal(version)}` + updateSql = safeSql`ALTER EXTENSION ${ident(name)} UPDATE ${ + version === undefined ? safeSql`` : safeSql`TO ${literal(version)}` };` } const schemaSql = - schema === undefined ? '' : `ALTER EXTENSION ${ident(name)} SET SCHEMA ${ident(schema)};` + schema === undefined + ? safeSql`` + : safeSql`ALTER EXTENSION ${ident(name)} SET SCHEMA ${ident(schema)};` - const sql = `BEGIN; ${updateSql} ${schemaSql} COMMIT;` + const sql = safeSql`BEGIN; ${updateSql} ${schemaSql} COMMIT;` return { sql } } @@ -95,8 +97,13 @@ type ExtensionRemoveParams = { cascade?: boolean } -function remove(name: string, { cascade = false }: ExtensionRemoveParams = {}): { sql: string } { - const sql = `DROP EXTENSION ${ident(name)} ${cascade ? 'CASCADE' : 'RESTRICT'};` +function remove( + name: string, + { cascade = false }: ExtensionRemoveParams = {} +): { + sql: SafeSqlFragment +} { + const sql = safeSql`DROP EXTENSION ${ident(name)} ${cascade ? safeSql`CASCADE` : safeSql`RESTRICT`};` return { sql } } diff --git a/packages/pg-meta/src/pg-meta-functions.ts b/packages/pg-meta/src/pg-meta-functions.ts index e9c6d09c1c0..886702ccd75 100644 --- a/packages/pg-meta/src/pg-meta-functions.ts +++ b/packages/pg-meta/src/pg-meta-functions.ts @@ -2,7 +2,7 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' import { filterByList } from './helpers' -import { ident, literal } from './pg-format' +import { ident, joinSqlFragments, literal, safeSql, type SafeSqlFragment } from './pg-format' import { FUNCTIONS_SQL } from './sql/functions' export const pgFunctionZod = z.object({ @@ -55,10 +55,10 @@ export function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgFunctionArrayZod } { - let sql = /* SQL */ ` + let sql = safeSql` with f as ( ${FUNCTIONS_SQL} ) @@ -72,13 +72,13 @@ export function list({ !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined ) if (filter) { - sql += ` where schema ${filter}` + sql = safeSql`${sql} where schema ${filter}` } if (limit) { - sql = `${sql} limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql = `${sql} offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { @@ -88,7 +88,7 @@ export function list({ } type FunctionsRetrieveReturn = { - sql: string + sql: SafeSqlFragment zod: typeof pgFunctionOptionalZod } @@ -114,7 +114,7 @@ export function retrieve({ args?: string[] }): FunctionsRetrieveReturn { if (id) { - const sql = /* SQL */ ` + const sql = safeSql` with f as ( ${FUNCTIONS_SQL} ) @@ -127,16 +127,8 @@ export function retrieve({ zod: pgFunctionOptionalZod, } } else if (name && schema && args) { - const sql = /* SQL */ `with f as ( - ${FUNCTIONS_SQL} - ) - select - f.* - from f join pg_proc as p on id = p.oid where schema = ${literal( - schema - )} and name = ${literal(name)} and p.proargtypes::text = ${ - args.length - ? /* SQL */ `( + const argsFragment = args.length + ? safeSql`( select string_agg(type_oid::text, ' ') from ( select ( split_args.arr[ @@ -148,15 +140,20 @@ export function retrieve({ ) as type_oid from ( select string_to_array( unnest( - array[${args.map(literal)}] + array[${joinSqlFragments(args.map(literal), ',')}] ), ' ' ) as arr ) as split_args ) args )` - : literal('') - }` + : literal('') + const sql = safeSql`with f as ( + ${FUNCTIONS_SQL} + ) + select + f.* + from f join pg_proc as p on id = p.oid where schema = ${literal(schema)} and name = ${literal(name)} and p.proargtypes::text = ${argsFragment}` return { sql, diff --git a/packages/pg-meta/src/pg-meta-indexes.ts b/packages/pg-meta/src/pg-meta-indexes.ts index 3fd4f12487a..959f55de90f 100644 --- a/packages/pg-meta/src/pg-meta-indexes.ts +++ b/packages/pg-meta/src/pg-meta-indexes.ts @@ -2,7 +2,7 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' import { filterByList } from './helpers' -import { literal } from './pg-format' +import { literal, safeSql, type SafeSqlFragment } from './pg-format' import { INDEXES_SQL } from './sql/indexes' const pgIndexZod = z.object({ @@ -54,10 +54,10 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgIndexArrayZod } { - let sql = ` + let sql = safeSql` with indexes as (${INDEXES_SQL}) select * from indexes @@ -68,13 +68,13 @@ function list({ !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined ) if (filter) { - sql += ` where schema ${filter}` + sql = safeSql`${sql} where schema ${filter}` } if (limit) { - sql += ` limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql += ` offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -82,8 +82,11 @@ function list({ } } -function retrieve({ id }: { id: number }): { sql: string; zod: typeof pgIndexOptionalZod } { - const sql = ` +function retrieve({ id }: { id: number }): { + sql: SafeSqlFragment + zod: typeof pgIndexOptionalZod +} { + const sql = safeSql` with indexes as (${INDEXES_SQL}) select * from indexes diff --git a/packages/pg-meta/src/pg-meta-policies.ts b/packages/pg-meta/src/pg-meta-policies.ts index d8a6e00112e..cf82713820e 100644 --- a/packages/pg-meta/src/pg-meta-policies.ts +++ b/packages/pg-meta/src/pg-meta-policies.ts @@ -2,7 +2,7 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' import { filterByList } from './helpers' -import { ident, literal } from './pg-format' +import { ident, literal, safeSql, type SafeSqlFragment } from './pg-format' import { POLICIES_SQL } from './sql/policies' const pgPolicyZod = z.object({ @@ -30,11 +30,11 @@ export type PGPolicy = z.infer type PolicyIdentifier = Pick | Pick -function getIdentifierWhereClause(identifier: PolicyIdentifier): string { +function getIdentifierWhereClause(identifier: PolicyIdentifier): SafeSqlFragment { if ('id' in identifier && identifier.id) { - return `id = ${literal(identifier.id)}` + return safeSql`id = ${literal(identifier.id)}` } else if ('name' in identifier && identifier.name && identifier.schema && identifier.table) { - return `name = ${literal(identifier.name)} AND schema = ${literal(identifier.schema)} AND table = ${literal(identifier.table)}` + return safeSql`name = ${literal(identifier.name)} AND schema = ${literal(identifier.schema)} AND table = ${literal(identifier.table)}` } throw new Error('Must provide either id or name, schema and table') } @@ -52,10 +52,10 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgPolicyArrayZod } { - let sql = ` + let sql = safeSql` with policies as (${POLICIES_SQL}) select * from policies @@ -66,13 +66,13 @@ function list({ !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined ) if (filter) { - sql += `where schema ${filter}` + sql = safeSql`${sql}where schema ${filter}` } if (limit) { - sql += ` limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql += ` offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -81,10 +81,10 @@ function list({ } function retrieve(identifier: PolicyIdentifier): { - sql: string + sql: SafeSqlFragment zod: typeof pgPolicyOptionalZod } { - const sql = `with policies as (${POLICIES_SQL}) select * from policies where ${getIdentifierWhereClause(identifier)};` + const sql = safeSql`with policies as (${POLICIES_SQL}) select * from policies where ${getIdentifierWhereClause(identifier)};` return { sql, zod: pgPolicyOptionalZod, @@ -147,10 +147,8 @@ function update( return { sql } } -function remove(identifier: Pick): { sql: string } { - const sql = `DROP POLICY ${ident(identifier.name)} ON ${ident(identifier.schema)}.${ident( - identifier.table - )};` +function remove(identifier: Pick): { sql: SafeSqlFragment } { + const sql = safeSql`DROP POLICY ${ident(identifier.name)} ON ${ident(identifier.schema)}.${ident(identifier.table)};` return { sql } } diff --git a/packages/pg-meta/src/pg-meta-publications.ts b/packages/pg-meta/src/pg-meta-publications.ts index bb61a896082..eecd5d1c41e 100644 --- a/packages/pg-meta/src/pg-meta-publications.ts +++ b/packages/pg-meta/src/pg-meta-publications.ts @@ -1,6 +1,6 @@ import { z } from 'zod' -import { ident, literal } from './pg-format' +import { ident, joinSqlFragments, literal, safeSql, type SafeSqlFragment } from './pg-format' import { PUBLICATIONS_SQL } from './sql/publications' const pgPublicationTableZod = z.object({ @@ -32,15 +32,15 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgPublicationArrayZod } { - let sql = `with publications as (${PUBLICATIONS_SQL}) select * from publications` + let sql = safeSql`with publications as (${PUBLICATIONS_SQL}) select * from publications` if (limit) { - sql += ` limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql += ` offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -50,20 +50,20 @@ function list({ type PublicationIdentifier = Pick | Pick -function getIdentifierWhereClause(identifier: PublicationIdentifier) { +function getIdentifierWhereClause(identifier: PublicationIdentifier): SafeSqlFragment { if ('id' in identifier && identifier.id) { - return `${ident('id')} = ${literal(identifier.id)}` + return safeSql`${ident('id')} = ${literal(identifier.id)}` } else if ('name' in identifier && identifier.name) { - return `${ident('name')} = ${literal(identifier.name)}` + return safeSql`${ident('name')} = ${literal(identifier.name)}` } throw new Error('Must provide either id or name') } function retrieve(identifier: PublicationIdentifier): { - sql: string + sql: SafeSqlFragment zod: typeof pgPublicationOptionalZod } { - const sql = `with publications as (${PUBLICATIONS_SQL}) select * from publications where ${getIdentifierWhereClause(identifier)};` + const sql = safeSql`with publications as (${PUBLICATIONS_SQL}) select * from publications where ${getIdentifierWhereClause(identifier)};` return { sql, zod: pgPublicationOptionalZod, @@ -86,35 +86,35 @@ function create({ publish_delete = false, publish_truncate = false, tables = null, -}: PublicationCreateParams): { sql: string } { - let tableClause: string +}: PublicationCreateParams): { sql: SafeSqlFragment } { + let tableClause: SafeSqlFragment if (tables === undefined || tables === null) { - tableClause = 'FOR ALL TABLES' + tableClause = safeSql`FOR ALL TABLES` } else if (tables.length === 0) { - tableClause = '' + tableClause = safeSql`` } else { - tableClause = `FOR TABLE ${tables - .map((t) => { + tableClause = safeSql`FOR TABLE ${joinSqlFragments( + tables.map((t) => { if (!t.includes('.')) { return ident(t) } - const [schema, ...rest] = t.split('.') const table = rest.join('.') - return `${ident(schema)}.${ident(table)}` - }) - .join(',')}` + return safeSql`${ident(schema)}.${ident(table)}` + }), + ',' + )}` } - let publishOps = [] + const publishOps: Array = [] if (publish_insert) publishOps.push('insert') if (publish_update) publishOps.push('update') if (publish_delete) publishOps.push('delete') if (publish_truncate) publishOps.push('truncate') - const sql = ` + const sql = safeSql` CREATE PUBLICATION ${ident(name)} ${tableClause} - WITH (publish = '${publishOps.join(',')}');` + WITH (publish = ${literal(publishOps.join(','))});` return { sql } } @@ -140,21 +140,21 @@ function update( publish_truncate, tables, }: PublicationUpdateParams -): { sql: string } { - const sql = ` +): { sql: SafeSqlFragment } { + const sql = safeSql` do $$ declare id oid := ${literal(id)}; old record; - new_name text := ${name === undefined ? null : literal(name)}; - new_owner text := ${owner === undefined ? null : literal(owner)}; - new_publish_insert bool := ${publish_insert ?? null}; - new_publish_update bool := ${publish_update ?? null}; - new_publish_delete bool := ${publish_delete ?? null}; - new_publish_truncate bool := ${publish_truncate ?? null}; + new_name text := ${name === undefined ? literal(null) : literal(name)}; + new_owner text := ${owner === undefined ? literal(null) : literal(owner)}; + new_publish_insert bool := ${literal(publish_insert ?? null)}; + new_publish_update bool := ${literal(publish_update ?? null)}; + new_publish_delete bool := ${literal(publish_delete ?? null)}; + new_publish_truncate bool := ${literal(publish_truncate ?? null)}; new_tables text := ${ tables === undefined - ? null + ? literal(null) : literal( tables === null ? 'all tables' @@ -166,7 +166,7 @@ declare const [schema, ...rest] = t.split('.') const table = rest.join('.') - return `${ident(schema)}.${ident(table)}` + return safeSql`${ident(schema)}.${ident(table)}` }) .join(',') ) @@ -237,8 +237,8 @@ end $$; return { sql } } -function remove(publication: Pick): { sql: string } { - const sql = `DROP PUBLICATION IF EXISTS ${ident(publication.name)};` +function remove(publication: Pick): { sql: SafeSqlFragment } { + const sql = safeSql`DROP PUBLICATION IF EXISTS ${ident(publication.name)};` return { sql } } diff --git a/packages/pg-meta/src/pg-meta-roles.ts b/packages/pg-meta/src/pg-meta-roles.ts index 5d4a7edcf5b..ab2bf21ecde 100644 --- a/packages/pg-meta/src/pg-meta-roles.ts +++ b/packages/pg-meta/src/pg-meta-roles.ts @@ -1,6 +1,6 @@ import { z } from 'zod' -import { ident, literal } from './pg-format' +import { ident, joinSqlFragments, literal, safeSql, type SafeSqlFragment } from './pg-format' import { ROLES_SQL } from './sql/roles' const pgRoleZod = z.object({ @@ -32,10 +32,10 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgRoleArrayZod } { - let sql = ` + let sql = safeSql` with roles as (${ROLES_SQL}) select @@ -54,13 +54,13 @@ where // ERROR: role name "pg_myrole" is reserved // DETAIL: Role names starting with "pg_" are reserved. // ``` - sql += ` and not pg_catalog.starts_with(name, 'pg_')` + sql = safeSql`${sql} and not pg_catalog.starts_with(name, 'pg_')` } if (limit) { - sql += ` limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql += ` offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -70,20 +70,20 @@ where type RoleIdentifier = Pick | Pick -function getIdentifierWhereClause(identifier: RoleIdentifier) { +function getIdentifierWhereClause(identifier: RoleIdentifier): SafeSqlFragment { if ('id' in identifier && identifier.id) { - return `${ident('id')} = ${literal(identifier.id)}` + return safeSql`${ident('id')} = ${literal(identifier.id)}` } else if ('name' in identifier && identifier.name) { - return `${ident('name')} = ${literal(identifier.name)}` + return safeSql`${ident('name')} = ${literal(identifier.name)}` } throw new Error('Must provide either id or name') } function retrieve(identifier: RoleIdentifier): { - sql: string + sql: SafeSqlFragment zod: typeof pgRoleOptionalZod } { - const sql = `with roles as (${ROLES_SQL}) select * from roles where ${getIdentifierWhereClause(identifier)};` + const sql = safeSql`with roles as (${ROLES_SQL}) select * from roles where ${getIdentifierWhereClause(identifier)};` return { sql, zod: pgRoleOptionalZod, @@ -102,9 +102,9 @@ type RoleCreateParams = { connectionLimit?: number password?: string validUntil?: string - memberOf?: string[] - members?: string[] - admins?: string[] + memberOf?: Array + members?: Array + admins?: Array config?: Record } function create({ @@ -123,26 +123,29 @@ function create({ members = [], admins = [], config = {}, -}: RoleCreateParams): { sql: string } { - const sql = ` +}: RoleCreateParams): { sql: SafeSqlFragment } { + const sql = safeSql` create role ${ident(name)} - ${isSuperuser ? 'superuser' : ''} - ${canCreateDb ? 'createdb' : ''} - ${canCreateRole ? 'createrole' : ''} - ${inheritRole ? '' : 'noinherit'} - ${canLogin ? 'login' : ''} - ${isReplicationRole ? 'replication' : ''} - ${canBypassRls ? 'bypassrls' : ''} - connection limit ${connectionLimit} - ${password === undefined ? '' : `password ${literal(password)}`} - ${validUntil === undefined ? '' : `valid until ${literal(validUntil)}`} - ${memberOf.length === 0 ? '' : `in role ${memberOf.map(ident).join(',')}`} - ${members.length === 0 ? '' : `role ${members.map(ident).join(',')}`} - ${admins.length === 0 ? '' : `admin ${admins.map(ident).join(',')}`} + ${isSuperuser ? safeSql`superuser` : safeSql``} + ${canCreateDb ? safeSql`createdb` : safeSql``} + ${canCreateRole ? safeSql`createrole` : safeSql``} + ${inheritRole ? safeSql`` : safeSql`noinherit`} + ${canLogin ? safeSql`login` : safeSql``} + ${isReplicationRole ? safeSql`replication` : safeSql``} + ${canBypassRls ? safeSql`bypassrls` : safeSql``} + connection limit ${literal(connectionLimit)} + ${password === undefined ? safeSql`` : safeSql`password ${literal(password)}`} + ${validUntil === undefined ? safeSql`` : safeSql`valid until ${literal(validUntil)}`} + ${memberOf.length === 0 ? safeSql`` : safeSql`in role ${joinSqlFragments(memberOf.map(ident), ',')}`} + ${members.length === 0 ? safeSql`` : safeSql`role ${joinSqlFragments(members.map(ident), ',')}`} + ${admins.length === 0 ? safeSql`` : safeSql`admin ${joinSqlFragments(admins.map(ident), ',')}`} ; -${Object.entries(config) - .map(([param, value]) => `alter role ${ident(name)} set ${ident(param)} = ${literal(value)};`) - .join('\n')} +${joinSqlFragments( + Object.entries(config).map( + ([param, value]) => safeSql`alter role ${ident(name)} set ${ident(param)} = ${literal(value)};` + ), + '\n' +)} ` return { sql } } @@ -160,7 +163,7 @@ type RoleUpdateParams = { password?: string validUntil?: string } -function update(identifier: RoleIdentifier, params: RoleUpdateParams): { sql: string } { +function update(identifier: RoleIdentifier, params: RoleUpdateParams): { sql: SafeSqlFragment } { const { name: newName, isSuperuser, @@ -174,7 +177,7 @@ function update(identifier: RoleIdentifier, params: RoleUpdateParams): { sql: st password, validUntil, } = params - const sql = ` + const sql = safeSql` do $$ declare old record; @@ -186,22 +189,22 @@ begin end if; execute(format('alter role %I - ${isSuperuser === undefined ? '' : isSuperuser ? 'superuser' : 'nosuperuser'} - ${canCreateDb === undefined ? '' : canCreateDb ? 'createdb' : 'nocreatedb'} - ${canCreateRole === undefined ? '' : canCreateRole ? 'createrole' : 'nocreaterole'} - ${inheritRole === undefined ? '' : inheritRole ? 'inherit' : 'noinherit'} - ${canLogin === undefined ? '' : canLogin ? 'login' : 'nologin'} - ${isReplicationRole === undefined ? '' : isReplicationRole ? 'replication' : 'noreplication'} - ${canBypassRls === undefined ? '' : canBypassRls ? 'bypassrls' : 'nobypassrls'} - ${connectionLimit === undefined ? '' : `connection limit ${connectionLimit}`} - ${password === undefined ? '' : `password ${literal(password)}`} - ${validUntil === undefined ? '' : `valid until %L`} - ', old.name${validUntil === undefined ? '' : `, ${literal(validUntil)}`})); + ${isSuperuser === undefined ? safeSql`` : isSuperuser ? safeSql`superuser` : safeSql`nosuperuser`} + ${canCreateDb === undefined ? safeSql`` : canCreateDb ? safeSql`createdb` : safeSql`nocreatedb`} + ${canCreateRole === undefined ? safeSql`` : canCreateRole ? safeSql`createrole` : safeSql`nocreaterole`} + ${inheritRole === undefined ? safeSql`` : inheritRole ? safeSql`inherit` : safeSql`noinherit`} + ${canLogin === undefined ? safeSql`` : canLogin ? safeSql`login` : safeSql`nologin`} + ${isReplicationRole === undefined ? safeSql`` : isReplicationRole ? safeSql`replication` : safeSql`noreplication`} + ${canBypassRls === undefined ? safeSql`` : canBypassRls ? safeSql`bypassrls` : safeSql`nobypassrls`} + ${connectionLimit === undefined ? safeSql`` : safeSql`connection limit ${literal(connectionLimit)}`} + ${password === undefined ? safeSql`` : safeSql`password ${literal(password)}`} + ${validUntil === undefined ? safeSql`` : safeSql`valid until %L`} + ', old.name${validUntil === undefined ? safeSql`` : safeSql`, ${literal(validUntil)}`})); ${ newName === undefined - ? '' - : ` + ? safeSql`` + : safeSql` -- Using the same name in the rename clause gives an error, so only do it if the new name is different. if ${literal(newName)} != old.name then execute(format('alter role %I rename to %I;', old.name, ${literal(newName)})); @@ -220,8 +223,8 @@ type RoleRemoveParams = { function remove( identifier: RoleIdentifier, { ifExists = false }: RoleRemoveParams = {} -): { sql: string } { - const sql = ` +): { sql: SafeSqlFragment } { + const sql = safeSql` do $$ declare old record; @@ -232,7 +235,7 @@ begin raise exception 'Cannot find role with id %', id; end if; - execute(format('drop role ${ifExists ? 'if exists' : ''} %I;', old.name)); + execute(format('drop role ${ifExists ? safeSql`if exists` : safeSql``} %I;', old.name)); end $$; ` diff --git a/packages/pg-meta/src/pg-meta-schemas.ts b/packages/pg-meta/src/pg-meta-schemas.ts index 17cf6ea3631..3ff8ba8d487 100644 --- a/packages/pg-meta/src/pg-meta-schemas.ts +++ b/packages/pg-meta/src/pg-meta-schemas.ts @@ -1,7 +1,7 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' -import { ident, literal } from './pg-format' +import { ident, joinSqlFragments, literal, safeSql, type SafeSqlFragment } from './pg-format' import { SCHEMAS_SQL } from './sql/schemas' const pgSchemaZod = z.object({ @@ -22,18 +22,18 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgSchemaArrayZod } { let sql = SCHEMAS_SQL if (!includeSystemSchemas) { - sql = `${sql} and not (n.nspname in (${DEFAULT_SYSTEM_SCHEMAS.map(literal).join(',')}))` + sql = safeSql`${sql} and not (n.nspname in (${joinSqlFragments(DEFAULT_SYSTEM_SCHEMAS.map(literal), ',')}))` } if (limit) { - sql = `${sql} limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql = `${sql} offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -41,20 +41,23 @@ function list({ } } -function retrieve({ id }: { id: number }): { sql: string; zod: typeof pgSchemaOptionalZod } -function retrieve({ name }: { name: string }): { sql: string; zod: typeof pgSchemaOptionalZod } +function retrieve({ id }: { id: number }): { sql: SafeSqlFragment; zod: typeof pgSchemaOptionalZod } +function retrieve({ name }: { name: string }): { + sql: SafeSqlFragment + zod: typeof pgSchemaOptionalZod +} function retrieve({ id, name }: { id?: number; name?: string }): { - sql: string + sql: SafeSqlFragment zod: typeof pgSchemaOptionalZod } { if (id) { - const sql = `${SCHEMAS_SQL} and n.oid = ${literal(id)};` + const sql = safeSql`${SCHEMAS_SQL} and n.oid = ${literal(id)};` return { sql, zod: pgSchemaOptionalZod, } } else { - const sql = `${SCHEMAS_SQL} and n.nspname = ${literal(name)};` + const sql = safeSql`${SCHEMAS_SQL} and n.nspname = ${literal(name)};` return { sql, zod: pgSchemaOptionalZod, @@ -66,9 +69,9 @@ type SchemaCreateParams = { name: string owner?: string } -function create({ name, owner }: SchemaCreateParams): { sql: string } { - const sql = `create schema ${ident(name)} - ${owner === undefined ? '' : `authorization ${ident(owner)}`}; +function create({ name, owner }: SchemaCreateParams): { sql: SafeSqlFragment } { + const sql = safeSql`create schema ${ident(name)} + ${owner === undefined ? safeSql`` : safeSql`authorization ${ident(owner)}`}; ` return { sql } } @@ -77,8 +80,8 @@ type SchemaUpdateParams = { name?: string owner?: string } -function update({ id }: { id: number }, params: SchemaUpdateParams): { sql: string } -function update({ name }: { name: string }, params: SchemaUpdateParams): { sql: string } +function update({ id }: { id: number }, params: SchemaUpdateParams): { sql: SafeSqlFragment } +function update({ name }: { name: string }, params: SchemaUpdateParams): { sql: SafeSqlFragment } function update( { id, @@ -88,14 +91,14 @@ function update( name?: string }, { name: newName, owner }: SchemaUpdateParams -): { sql: string } { - const sql = ` +): { sql: SafeSqlFragment } { + const sql = safeSql` do $$ declare - id oid := ${id === undefined ? `${literal(name)}::regnamespace` : literal(id)}; + id oid := ${id === undefined ? safeSql`${literal(name)}::regnamespace` : literal(id)}; old record; - new_name text := ${newName === undefined ? null : literal(newName)}; - new_owner text := ${owner === undefined ? null : literal(owner)}; + new_name text := ${newName === undefined ? literal(null) : literal(newName)}; + new_owner text := ${owner === undefined ? literal(null) : literal(owner)}; begin select * into old from pg_namespace where oid = id; if old is null then @@ -119,8 +122,8 @@ $$; type SchemaRemoveParams = { cascade?: boolean } -function remove({ id }: { id: number }, params?: SchemaRemoveParams): { sql: string } -function remove({ name }: { name: string }, params?: SchemaRemoveParams): { sql: string } +function remove({ id }: { id: number }, params?: SchemaRemoveParams): { sql: SafeSqlFragment } +function remove({ name }: { name: string }, params?: SchemaRemoveParams): { sql: SafeSqlFragment } function remove( { id, @@ -130,11 +133,11 @@ function remove( name?: string }, { cascade = false }: SchemaRemoveParams = {} -): { sql: string } { - const sql = ` +): { sql: SafeSqlFragment } { + const sql = safeSql` do $$ declare - id oid := ${id === undefined ? `${literal(name)}::regnamespace` : literal(id)}; + id oid := ${id === undefined ? safeSql`${literal(name)}::regnamespace` : literal(id)}; old record; cascade bool := ${literal(cascade)}; begin diff --git a/packages/pg-meta/src/pg-meta-table-privileges.ts b/packages/pg-meta/src/pg-meta-table-privileges.ts index d72afa57c96..984a1b9b22b 100644 --- a/packages/pg-meta/src/pg-meta-table-privileges.ts +++ b/packages/pg-meta/src/pg-meta-table-privileges.ts @@ -2,7 +2,14 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' import { filterByList } from './helpers' -import { ident, literal } from './pg-format' +import { + ident, + joinSqlFragments, + keyword, + literal, + safeSql, + type SafeSqlFragment, +} from './pg-format' import { TABLE_PRIVILEGES_SQL } from './sql/table-privileges' const pgTablePrivilegesZod = z.object({ @@ -50,10 +57,10 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgTablePrivilegesArrayZod } { - let sql = ` + let sql = safeSql` with table_privileges as (${TABLE_PRIVILEGES_SQL}) select * from table_privileges @@ -64,13 +71,13 @@ from table_privileges !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined ) if (filter) { - sql += ` where schema ${filter}` + sql = safeSql`${sql} where schema ${filter}` } if (limit) { - sql += ` limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql += ` offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -78,9 +85,12 @@ from table_privileges } } -function retrieve({ id }: { id: number }): { sql: string; zod: typeof pgTablePrivilegesOptionalZod } +function retrieve({ id }: { id: number }): { + sql: SafeSqlFragment + zod: typeof pgTablePrivilegesOptionalZod +} function retrieve({ name, schema }: { name: string; schema?: string }): { - sql: string + sql: SafeSqlFragment zod: typeof pgTablePrivilegesOptionalZod } function retrieve({ @@ -92,11 +102,11 @@ function retrieve({ name?: string schema?: string }): { - sql: string + sql: SafeSqlFragment zod: typeof pgTablePrivilegesOptionalZod } { if (id) { - const sql = /* SQL */ ` + const sql = /* SQL */ safeSql` with table_privileges as (${TABLE_PRIVILEGES_SQL}) select * from table_privileges @@ -106,7 +116,7 @@ where table_privileges.relation_id = ${literal(id)};` zod: pgTablePrivilegesOptionalZod, } } else { - const sql = /* SQL */ ` + const sql = /* SQL */ safeSql` with table_privileges as (${TABLE_PRIVILEGES_SQL}) select * from table_privileges @@ -135,18 +145,19 @@ type TablePrivilegesGrant = { | 'MAINTAIN' isGrantable?: boolean } -function grant(grants: TablePrivilegesGrant[]): { sql: string } { - const sql = ` +function grant(grants: TablePrivilegesGrant[]): { sql: SafeSqlFragment } { + const sql = safeSql` do $$ begin -${grants - .map( +${joinSqlFragments( + grants.map( ({ privilegeType, relationId, grantee, isGrantable }) => - `execute format('grant ${privilegeType} on table %s to ${ - grantee.toLowerCase() === 'public' ? 'public' : ident(grantee) - } ${isGrantable ? 'with grant option' : ''}', ${relationId}::regclass);` - ) - .join('\n')} + safeSql`execute format('grant ${keyword(privilegeType)} on table %s to ${ + grantee.toLowerCase() === 'public' ? safeSql`public` : ident(grantee) + } ${isGrantable ? safeSql`with grant option` : safeSql``}', ${literal(relationId)}::regclass);` + ), + '\n' +)} end $$; ` return { sql } @@ -166,16 +177,19 @@ type TablePrivilegesRevoke = { | 'TRIGGER' | 'MAINTAIN' } -function revoke(revokes: TablePrivilegesRevoke[]): { sql: string } { - const sql = ` +function revoke(revokes: TablePrivilegesRevoke[]): { sql: SafeSqlFragment } { + const sql = safeSql` do $$ begin -${revokes - .map( +${joinSqlFragments( + revokes.map( ({ privilegeType, relationId, grantee }) => - `execute format('revoke ${privilegeType} on table %s from ${grantee.toLowerCase() === 'public' ? 'public' : ident(grantee)}', ${relationId}::regclass);` - ) - .join('\n')} + safeSql`execute format('revoke ${keyword(privilegeType)} on table %s from ${ + grantee.toLowerCase() === 'public' ? safeSql`public` : ident(grantee) + }', ${literal(relationId)}::regclass);` + ), + '\n' +)} end $$; ` return { sql } diff --git a/packages/pg-meta/src/pg-meta-triggers.ts b/packages/pg-meta/src/pg-meta-triggers.ts index 5bae66efa16..f2a10184334 100644 --- a/packages/pg-meta/src/pg-meta-triggers.ts +++ b/packages/pg-meta/src/pg-meta-triggers.ts @@ -2,17 +2,17 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' import { filterByList } from './helpers' -import { ident, literal } from './pg-format' +import { ident, keyword, literal, safeSql, type SafeSqlFragment } from './pg-format' import { TRIGGERS_SQL } from './sql/triggers' type TriggerIdentifier = Pick | Pick -function getIdentifierWhereClause(identifier: TriggerIdentifier): string { +function getIdentifierWhereClause(identifier: TriggerIdentifier): SafeSqlFragment { if ('id' in identifier && identifier.id) { - return `${ident('id')} = ${literal(identifier.id)}` + return safeSql`${ident('id')} = ${literal(identifier.id)}` } if ('name' in identifier && identifier.name && identifier.table && identifier.schema) { - return `${ident('name')} = ${literal(identifier.name)} and ${ident('schema')} = ${literal(identifier.schema)} and ${ident('table')} = ${literal(identifier.table)}` + return safeSql`${ident('name')} = ${literal(identifier.name)} and ${ident('schema')} = ${literal(identifier.schema)} and ${ident('table')} = ${literal(identifier.table)}` } throw new Error('Must provide either id or name, schema and table') } @@ -51,23 +51,23 @@ export function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgTriggerArrayZod } { - let sql = `with triggers as (${TRIGGERS_SQL}) select * from triggers` + let sql = safeSql`with triggers as (${TRIGGERS_SQL}) select * from triggers` const filter = filterByList( includedSchemas, excludedSchemas, !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined ) if (filter) { - sql += ` where schema ${filter}` + sql = safeSql`${sql} where schema ${filter}` } if (limit) { - sql += ` limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql += ` offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, @@ -76,14 +76,14 @@ export function list({ } type TriggersRetrieveReturn = { - sql: string + sql: SafeSqlFragment zod: typeof pgTriggerOptionalZod } export function retrieve(identifier: TriggerIdentifier): TriggersRetrieveReturn export function retrieve(params: TriggerIdentifier): TriggersRetrieveReturn { const whereIdentifierCondition = getIdentifierWhereClause(params) - const sql = `with triggers as (${TRIGGERS_SQL}) select * from triggers where ${whereIdentifierCondition};` + const sql = safeSql`with triggers as (${TRIGGERS_SQL}) select * from triggers where ${whereIdentifierCondition};` return { sql, zod: pgTriggerOptionalZod, @@ -148,23 +148,23 @@ export function update( id: { name: string; schema: string; table: string }, params: PGTriggerUpdate ): { - sql: string + sql: SafeSqlFragment zod: z.ZodType } { - const qualifiedTableName = `${ident(id.schema)}.${ident(id.table)}` + const qualifiedTableName = safeSql`${ident(id.schema)}.${ident(id.table)}` - let enabledModeSql = '' + let enabledModeSql = safeSql`` switch (params.enabled_mode) { case 'ORIGIN': - enabledModeSql = `alter table ${qualifiedTableName} enable trigger ${ident(id.name)};` + enabledModeSql = safeSql`alter table ${qualifiedTableName} enable trigger ${ident(id.name)};` break case 'DISABLED': - enabledModeSql = `alter table ${qualifiedTableName} disable trigger ${ident(id.name)};` + enabledModeSql = safeSql`alter table ${qualifiedTableName} disable trigger ${ident(id.name)};` break case 'REPLICA': case 'ALWAYS': - enabledModeSql = `alter table ${qualifiedTableName} enable ${params.enabled_mode} trigger ${ident(id.name)};` + enabledModeSql = safeSql`alter table ${qualifiedTableName} enable ${keyword(params.enabled_mode)} trigger ${ident(id.name)};` break default: break @@ -172,11 +172,11 @@ export function update( const updateNameSql = params.name && params.name !== id.name - ? `alter trigger ${ident(id.name)} on ${qualifiedTableName} rename to ${ident(params.name)};` - : '' + ? safeSql`alter trigger ${ident(id.name)} on ${qualifiedTableName} rename to ${ident(params.name)};` + : safeSql`` // updateNameSql must be last - const sql = `begin; ${enabledModeSql}; ${updateNameSql}; commit;` + const sql = safeSql`begin; ${enabledModeSql}; ${updateNameSql}; commit;` return { sql, @@ -188,12 +188,12 @@ export function remove( id: { name: string; schema: string; table: string }, { cascade = false } = {} ): { - sql: string + sql: SafeSqlFragment zod: z.ZodType } { - const qualifiedTableName = `${ident(id.schema)}.${ident(id.table)}` + const qualifiedTableName = safeSql`${ident(id.schema)}.${ident(id.table)}` - const sql = `drop trigger ${ident(id.name)} on ${qualifiedTableName} ${cascade ? 'cascade' : ''};` + const sql = safeSql`drop trigger ${ident(id.name)} on ${qualifiedTableName} ${cascade ? safeSql`cascade` : safeSql``};` return { sql, diff --git a/packages/pg-meta/src/pg-meta-types.ts b/packages/pg-meta/src/pg-meta-types.ts index 33371f3d5d9..547070d51d2 100644 --- a/packages/pg-meta/src/pg-meta-types.ts +++ b/packages/pg-meta/src/pg-meta-types.ts @@ -2,6 +2,7 @@ import { z } from 'zod' import { DEFAULT_SYSTEM_SCHEMAS } from './constants' import { filterByList } from './helpers' +import { literal, safeSql, type SafeSqlFragment } from './pg-format' import { TYPES_SQL } from './sql/types' const pgTypeZod = z.object({ @@ -36,12 +37,12 @@ function list({ limit?: number offset?: number } = {}): { - sql: string + sql: SafeSqlFragment zod: typeof pgTypeArrayZod } { let sql = TYPES_SQL if (!includeArrayTypes) { - sql += ` and not exists ( + sql = safeSql`${sql} and not exists ( select from pg_type el where el.oid = t.typelem and el.typarray = t.oid @@ -53,13 +54,13 @@ function list({ !includeSystemSchemas ? DEFAULT_SYSTEM_SCHEMAS : undefined ) if (filter) { - sql += ` and n.nspname ${filter}` + sql = safeSql`${sql} and n.nspname ${filter}` } if (limit) { - sql += ` limit ${limit}` + sql = safeSql`${sql} limit ${literal(limit)}` } if (offset) { - sql += ` offset ${offset}` + sql = safeSql`${sql} offset ${literal(offset)}` } return { sql, diff --git a/packages/pg-meta/src/pg-meta-version.ts b/packages/pg-meta/src/pg-meta-version.ts index 443da64f13b..2423279addf 100644 --- a/packages/pg-meta/src/pg-meta-version.ts +++ b/packages/pg-meta/src/pg-meta-version.ts @@ -1,5 +1,6 @@ import { z } from 'zod' +import { type SafeSqlFragment } from './pg-format' import { VERSION_SQL } from './sql/version' export const pgVersionZod = z.object({ @@ -9,7 +10,7 @@ export const pgVersionZod = z.object({ max_connections: z.number(), }) -function retrieve() { +function retrieve(): { sql: SafeSqlFragment; zod: typeof pgVersionZod } { return { sql: VERSION_SQL, zod: pgVersionZod, diff --git a/packages/pg-meta/src/sql/config.ts b/packages/pg-meta/src/sql/config.ts index c870ff182ba..c289d5e49f9 100644 --- a/packages/pg-meta/src/sql/config.ts +++ b/packages/pg-meta/src/sql/config.ts @@ -1,4 +1,6 @@ -export const CONFIG_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const CONFIG_SQL = /* SQL */ safeSql` SELECT name, setting, diff --git a/packages/pg-meta/src/sql/extensions.ts b/packages/pg-meta/src/sql/extensions.ts index 403c1c2d20a..2bd5a718a4c 100644 --- a/packages/pg-meta/src/sql/extensions.ts +++ b/packages/pg-meta/src/sql/extensions.ts @@ -1,4 +1,6 @@ -export const EXTENSIONS_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const EXTENSIONS_SQL = /* SQL */ safeSql` SELECT e.name, n.nspname AS schema, diff --git a/packages/pg-meta/src/sql/functions.ts b/packages/pg-meta/src/sql/functions.ts index 996d13fd253..257cb7bc5bf 100644 --- a/packages/pg-meta/src/sql/functions.ts +++ b/packages/pg-meta/src/sql/functions.ts @@ -1,4 +1,6 @@ -export const FUNCTIONS_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const FUNCTIONS_SQL = /* SQL */ safeSql` -- CTE with sane arg_modes, arg_names, and arg_types. -- All three are always of the same length. -- All three include all args, including OUT and TABLE args. diff --git a/packages/pg-meta/src/sql/indexes.ts b/packages/pg-meta/src/sql/indexes.ts index ef7cd40e5f1..db66dc9ab25 100644 --- a/packages/pg-meta/src/sql/indexes.ts +++ b/packages/pg-meta/src/sql/indexes.ts @@ -1,4 +1,6 @@ -export const INDEXES_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const INDEXES_SQL = /* SQL */ safeSql` SELECT idx.indexrelid::int8 AS id, idx.indrelid::int8 AS table_id, diff --git a/packages/pg-meta/src/sql/policies.ts b/packages/pg-meta/src/sql/policies.ts index 66ff548ed8f..00103957959 100644 --- a/packages/pg-meta/src/sql/policies.ts +++ b/packages/pg-meta/src/sql/policies.ts @@ -1,4 +1,6 @@ -export const POLICIES_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const POLICIES_SQL = /* SQL */ safeSql` select pol.oid :: int8 as id, n.nspname as schema, diff --git a/packages/pg-meta/src/sql/publications.ts b/packages/pg-meta/src/sql/publications.ts index ea778615d32..f1a38dddc91 100644 --- a/packages/pg-meta/src/sql/publications.ts +++ b/packages/pg-meta/src/sql/publications.ts @@ -1,4 +1,6 @@ -export const PUBLICATIONS_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const PUBLICATIONS_SQL = /* SQL */ safeSql` SELECT p.oid :: int8 AS id, p.pubname AS name, diff --git a/packages/pg-meta/src/sql/roles.ts b/packages/pg-meta/src/sql/roles.ts index 7dab24f5967..044f77ada5a 100644 --- a/packages/pg-meta/src/sql/roles.ts +++ b/packages/pg-meta/src/sql/roles.ts @@ -1,4 +1,6 @@ -export const ROLES_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const ROLES_SQL = /* SQL */ safeSql` -- Can't use pg_authid here since some managed Postgres providers don't expose it -- https://github.com/supabase/postgres-meta/issues/212 diff --git a/packages/pg-meta/src/sql/schemas.ts b/packages/pg-meta/src/sql/schemas.ts index 092e78495b8..8131f62d633 100644 --- a/packages/pg-meta/src/sql/schemas.ts +++ b/packages/pg-meta/src/sql/schemas.ts @@ -1,4 +1,6 @@ -export const SCHEMAS_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const SCHEMAS_SQL = /* SQL */ safeSql` -- Adapted from information_schema.schemata select diff --git a/packages/pg-meta/src/sql/table-privileges.ts b/packages/pg-meta/src/sql/table-privileges.ts index ad54a2103c6..bd2e031783d 100644 --- a/packages/pg-meta/src/sql/table-privileges.ts +++ b/packages/pg-meta/src/sql/table-privileges.ts @@ -1,4 +1,6 @@ -export const TABLE_PRIVILEGES_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const TABLE_PRIVILEGES_SQL = /* SQL */ safeSql` -- Despite the name \`table_privileges\`, this includes other kinds of relations: -- views, matviews, etc. "Relation privileges" just doesn't roll off the tongue. -- diff --git a/packages/pg-meta/src/sql/triggers.ts b/packages/pg-meta/src/sql/triggers.ts index 4d1f6962328..7f3ec27dd71 100644 --- a/packages/pg-meta/src/sql/triggers.ts +++ b/packages/pg-meta/src/sql/triggers.ts @@ -1,4 +1,6 @@ -export const TRIGGERS_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const TRIGGERS_SQL = /* SQL */ safeSql` SELECT pg_t.oid AS id, pg_t.tgrelid AS table_id, diff --git a/packages/pg-meta/src/sql/types.ts b/packages/pg-meta/src/sql/types.ts index cc73a14c33c..b3da5666d24 100644 --- a/packages/pg-meta/src/sql/types.ts +++ b/packages/pg-meta/src/sql/types.ts @@ -1,4 +1,6 @@ -export const TYPES_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const TYPES_SQL = /* SQL */ safeSql` select t.oid::int8 as id, t.typname as name, diff --git a/packages/pg-meta/src/sql/version.ts b/packages/pg-meta/src/sql/version.ts index 7a5104e4010..99bb8dc3219 100644 --- a/packages/pg-meta/src/sql/version.ts +++ b/packages/pg-meta/src/sql/version.ts @@ -1,4 +1,6 @@ -export const VERSION_SQL = /* SQL */ ` +import { safeSql } from '../pg-format' + +export const VERSION_SQL = /* SQL */ safeSql` select version(), current_setting('server_version_num')::int8 as version_number,