fix: move extension requests to query route (#35583)

* fix: move extension requests to query route

* chore: escape schema name as identifier
This commit is contained in:
Han Qiao authored and GitHub committed 2025-05-13 00:31:18 +08:00
1 parent e2fddfeeeb
commit ca06acef00
3 files changed
+34 -92

No files matched your search

@@ -1,7 +1,8 @@
import pgMeta from '@supabase/pg-meta'
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { del, handleError } from 'data/fetchers'
import { executeSql } from 'data/sql/execute-sql-query'
import type { ResponseError } from 'types'
import { databaseExtensionsKeys } from './keys'
@@ -9,27 +10,27 @@ export type DatabaseExtensionDisableVariables = {
projectRef: string
connectionString?: string | null
id: string
cascade?: boolean
}
export async function disableDatabaseExtension({
projectRef,
connectionString,
id,
cascade,
}: DatabaseExtensionDisableVariables) {
let headers = new Headers()
if (connectionString) headers.set('x-connection-encrypted', connectionString)
const { data, error } = await del('/platform/pg-meta/{ref}/extensions', {
params: {
header: { 'x-connection-encrypted': connectionString! },
path: { ref: projectRef },
query: { id },
},
headers,
const { sql } = pgMeta.extensions.remove(id, { cascade })
const { result } = await executeSql({
projectRef,
connectionString,
sql,
queryKey: ['extension', 'delete', id],
})
if (error) handleError(error)
return data
return result
}
type DatabaseExtensionDisableData = Awaited<ReturnType<typeof disableDatabaseExtension>>
@@ -1,7 +1,8 @@
import pgMeta from '@supabase/pg-meta'
import { ident } from '@supabase/pg-meta/src/pg-format'
import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query'
import { toast } from 'sonner'
import { handleError, post } from 'data/fetchers'
import { executeSql } from 'data/sql/execute-sql-query'
import type { ResponseError } from 'types'
import { databaseExtensionsKeys } from './keys'
@@ -28,29 +29,15 @@ export async function enableDatabaseExtension({
let headers = new Headers()
if (connectionString) headers.set('x-connection-encrypted', connectionString)
if (createSchema) {
try {
await executeSql({
projectRef,
connectionString,
sql: `create schema if not exists ${schema}`,
})
} catch (error) {
throw error
}
}
const { data, error } = await post('/platform/pg-meta/{ref}/extensions', {
params: {
header: { 'x-connection-encrypted': connectionString! },
path: { ref: projectRef },
},
body: { schema, name, version, cascade },
headers,
const { sql } = pgMeta.extensions.create({ schema, name, version, cascade })
const { result } = await executeSql({
projectRef,
connectionString,
sql: createSchema ? `create schema if not exists ${ident(schema)}; ${sql}` : sql,
queryKey: ['extension', 'create'],
})
if (error) handleError(error)
return data
return result
}
type DatabaseExtensionEnableData = Awaited<ReturnType<typeof enableDatabaseExtension>>
+14 -60
View File
@@ -1,4 +1,4 @@
import { literal } from './pg-format'
import { ident, literal } from './pg-format'
import { EXTENSIONS_SQL } from './sql/extensions'
import { z } from 'zod'
@@ -60,26 +60,10 @@ function create({ name, schema, version, cascade = false }: ExtensionCreateParam
sql: string
} {
const sql = `
do $$
begin
-- Check if extension exists
if exists (
select 1 from pg_extension where extname = ${literal(name)}
) then
raise exception 'Extension % already exists', ${literal(name)};
end if;
execute(format('CREATE EXTENSION %I
%s
%s
%s',
${literal(name)},
${schema ? `'SCHEMA ' || quote_ident(${literal(schema)})` : `''`},
${version ? `'VERSION ' || quote_ident(${literal(version)})` : `''`},
${cascade ? `'CASCADE'` : `''`}
));
end
$$;`
CREATE EXTENSION ${ident(name)}
${schema === undefined ? '' : `SCHEMA ${ident(schema)}`}
${version === undefined ? '' : `VERSION ${literal(version)}`}
${cascade ? 'CASCADE' : ''};`
return { sql }
}
@@ -93,36 +77,16 @@ function update(
name: string,
{ update = false, version, schema }: ExtensionUpdateParams
): { sql: string } {
const sql = `
do $$
declare
ext record;
begin
-- Check if extension exists
select * into ext from pg_extension where extname = ${literal(name)};
if ext is null then
raise exception 'Extension % does not exist', ${literal(name)};
end if;
${
update
? `execute(format('ALTER EXTENSION %I UPDATE %s',
${literal(name)},
${version ? `'TO ' || quote_ident(${literal(version)})` : `''`}
));`
: ''
let updateSql = ''
if (update) {
updateSql = `ALTER EXTENSION ${ident(name)} UPDATE ${
version === undefined ? '' : `TO ${literal(version)}`
};`
}
const schemaSql =
schema === undefined ? '' : `ALTER EXTENSION ${ident(name)} SET SCHEMA ${ident(schema)};`
${
schema
? `execute(format('ALTER EXTENSION %I SET SCHEMA %I',
${literal(name)},
${literal(schema)}
));`
: ''
}
end
$$;`
const sql = `BEGIN; ${updateSql} ${schemaSql} COMMIT;`
return { sql }
}
@@ -131,17 +95,7 @@ type ExtensionRemoveParams = {
}
function remove(name: string, { cascade = false }: ExtensionRemoveParams = {}): { sql: string } {
const sql = `
do $$
declare
ext record;
begin
execute(format('DROP EXTENSION %I %s',
${literal(name)},
${cascade ? `'CASCADE'` : `'RESTRICT'`}
));
end
$$;`
const sql = `DROP EXTENSION ${ident(name)} ${cascade ? 'CASCADE' : 'RESTRICT'};`
return { sql }
}