Files
supabase/apps/studio/data/fdw/fdw-import-foreign-schema-mutation.ts
Joshen Lim 9aa6e167c9 Update vector bucket SQL queries for wrappers ext 0.5.7 (#42274)
## Context

There's some changes for Vector Buckets with the wrappers extension on
version 0.5.7 and above

The "Query from Postgres" CTA (which runs an import foreign schema
command) no longer accepts the bucket name as part of the schema options
(ref
[changelog](https://github.com/supabase/wrappers/releases/tag/v0.5.7)),
and instead takes the bucket name as the remote schema name.

So changes here are to update the SQL for importing foreign schema for
vector buckets if wrappers extension is above 0.5.7

Also - the `::embd` type no longer seems to exist in 0.5.7 as well, so
updated the example code too

## To test

Can probably test on a new US East 1 project on the preview
- [ ] Verify creating a vector bucket table + can query from postgres
(via the Insert vectors CTA after creating a table)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
  * Fixed breadcrumb navigation links for vector bucket pages.

* **Improvements**
* Unified loading state for schema workflows and disabled actions while
loading.
* Enhanced version compatibility checks for foreign schema imports to
support newer extension syntax.
* Adjusted generated SQL for vector data to use the appropriate
embedding syntax based on extension version.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-30 18:53:53 +08:00

82 lines
2.6 KiB
TypeScript

import { useMutation, useQueryClient } from '@tanstack/react-query'
import { entityTypeKeys } from 'data/entity-types/keys'
import { foreignTableKeys } from 'data/foreign-tables/keys'
import { executeSql } from 'data/sql/execute-sql-query'
import { wrapWithTransaction } from 'data/sql/utils/transaction'
import { vaultSecretsKeys } from 'data/vault/keys'
import { toast } from 'sonner'
import type { ResponseError, UseCustomMutationOptions } from 'types'
import { fdwKeys } from './keys'
export type FDWImportForeignSchemaVariables = {
projectRef?: string
connectionString?: string | null
serverName: string
sourceSchema: string
targetSchema: string
schemaOptions?: string[]
}
export function getImportForeignSchemaSql({
serverName,
sourceSchema,
targetSchema,
schemaOptions = [],
}: Omit<FDWImportForeignSchemaVariables, 'projectRef' | 'connectionString'>) {
const options = [...schemaOptions, "strict 'true'"].join(', ')
const sql = /* SQL */ `
import foreign schema "${sourceSchema}" from server ${serverName} into ${targetSchema} options (${options});
`
return sql
}
export async function importForeignSchema({
projectRef,
connectionString,
...rest
}: FDWImportForeignSchemaVariables) {
const sql = wrapWithTransaction(getImportForeignSchemaSql(rest))
const { result } = await executeSql({ projectRef, connectionString, sql })
return result
}
type ImportForeignSchemaData = Awaited<ReturnType<typeof importForeignSchema>>
export const useFDWImportForeignSchemaMutation = ({
onSuccess,
onError,
...options
}: Omit<
UseCustomMutationOptions<ImportForeignSchemaData, ResponseError, FDWImportForeignSchemaVariables>,
'mutationFn'
> = {}) => {
const queryClient = useQueryClient()
return useMutation<ImportForeignSchemaData, ResponseError, FDWImportForeignSchemaVariables>({
mutationFn: (vars) => importForeignSchema(vars),
async onSuccess(data, variables, context) {
const { projectRef } = variables
await Promise.all([
queryClient.invalidateQueries({ queryKey: fdwKeys.list(projectRef), refetchType: 'all' }),
queryClient.invalidateQueries({ queryKey: entityTypeKeys.list(projectRef) }),
queryClient.invalidateQueries({ queryKey: foreignTableKeys.list(projectRef) }),
queryClient.invalidateQueries({ queryKey: vaultSecretsKeys.list(projectRef) }),
])
await onSuccess?.(data, variables, context)
},
async onError(data, variables, context) {
if (onError === undefined) {
toast.error(`Failed to import schema for foreign data wrapper: ${data.message}`)
} else {
onError(data, variables, context)
}
},
...options,
})
}