1- import { uniq } from 'lodash'
1+ import { uniq , uniqBy } from 'lodash'
22import { useMemo } from 'react'
33
4- import { WRAPPER_HANDLERS } from 'components/interfaces/Integrations/Wrappers/Wrappers.constants'
4+ import {
5+ SUPABASE_TARGET_SCHEMA_OPTION ,
6+ WRAPPERS ,
7+ } from 'components/interfaces/Integrations/Wrappers/Wrappers.constants'
58import {
69 convertKVStringArrayToJson ,
710 wrapperMetaComparator ,
@@ -34,35 +37,56 @@ export const INTERNAL_SCHEMAS = [
3437]
3538
3639/**
37- * Get the list of schemas used by IcebergFDWs
40+ * Get the list of schemas used by FDWs like Iceberg, S3 Vectors, etc.
3841 */
39- const useIcebergFdwSchemasQuery = ( ) => {
42+ const useFdwSchemasQuery = ( ) => {
4043 const { data : project } = useSelectedProjectQuery ( )
4144 const result = useFDWsQuery ( {
4245 projectRef : project ?. ref ,
4346 connectionString : project ?. connectionString ,
4447 } )
4548
49+ // Find all wrappers that create a schema for their data.
50+ const FDWsWithSchemas = useMemo (
51+ ( ) =>
52+ WRAPPERS . filter ( ( wrapper ) =>
53+ wrapper . server . options . some ( ( option ) => option . name === SUPABASE_TARGET_SCHEMA_OPTION . name )
54+ ) ,
55+ [ ]
56+ )
57+
4658 const schemas = useMemo ( ( ) => {
47- const icebergFDWs = result . data ?. filter ( ( wrapper ) =>
48- wrapperMetaComparator (
49- { handlerName : WRAPPER_HANDLERS . ICEBERG , server : { options : [ ] } } ,
50- wrapper
51- )
52- )
59+ const icebergFDWs =
60+ result . data ?. filter ( ( wrapper ) =>
61+ FDWsWithSchemas . some ( ( w ) => wrapperMetaComparator ( w , wrapper ) )
62+ ) ?? [ ]
63+
64+ const fdwSchemas = icebergFDWs . map ( ( fdw ) => {
65+ const schemaOption =
66+ convertKVStringArrayToJson ( fdw . server_options ) [ 'supabase_target_schema' ] ?? ''
5367
54- const fdwSchemas = icebergFDWs
55- ?. map ( ( fdw ) => convertKVStringArrayToJson ( fdw . server_options ) )
56- . map ( ( options ) => options [ 'supabase_target_schema' ] )
57- . flatMap ( ( s ) => s ?. split ( ',' ) )
58- . filter ( Boolean )
68+ const schemas = uniq ( schemaOption . split ( ',' ) . filter ( Boolean ) )
5969
60- return uniq ( fdwSchemas )
61- } , [ result . data ] )
70+ return {
71+ serverName : fdw . server_name ,
72+ type : fdw . handler . replace ( '_fdw_handler' , '' ) ,
73+ schemas,
74+ }
75+ } )
76+
77+ return fdwSchemas
78+ } , [ result . data , FDWsWithSchemas ] )
6279
6380 return { ...result , data : schemas }
6481}
6582
83+ type ProtectedSchema = {
84+ name : string
85+ type : 'fdw' | 'internal'
86+ fdwType ?: string
87+ serverName ?: string
88+ }
89+
6690/**
6791 * Returns a list of schemas that are protected by Supabase (internal schemas or schemas used by Iceberg FDWs).
6892 */
@@ -73,13 +97,20 @@ export const useProtectedSchemas = ({
7397 // eslint-disable-next-line react-hooks/exhaustive-deps
7498 const stableExcludeSchemas = useMemo ( ( ) => excludeSchemas , [ JSON . stringify ( excludeSchemas ) ] )
7599
76- const result = useIcebergFdwSchemasQuery ( )
100+ const result = useFdwSchemasQuery ( )
77101
78- const schemas = useMemo < { name : string ; type : 'fdw' | 'internal' } [ ] > ( ( ) => {
102+ const schemas = useMemo < ProtectedSchema [ ] > ( ( ) => {
79103 const internalSchemas = INTERNAL_SCHEMAS . map ( ( s ) => ( { name : s , type : 'internal' as const } ) )
80- const icebergFdwSchemas = result . data ?. map ( ( s ) => ( { name : s , type : 'fdw' as const } ) )
104+ const fdwSchemas = result . data ?. flatMap ( ( s ) =>
105+ s . schemas . map ( ( schema ) => ( {
106+ name : schema ,
107+ type : 'fdw' as const ,
108+ fdwType : s . type ,
109+ serverName : s . serverName ,
110+ } ) )
111+ )
81112
82- const schemas = uniq ( [ ...internalSchemas , ...icebergFdwSchemas ] )
113+ const schemas = uniqBy ( [ ...internalSchemas , ...fdwSchemas ] , ( s ) => s . name )
83114 return schemas . filter ( ( schema ) => ! stableExcludeSchemas . includes ( schema . name ) )
84115 } , [ result . data , stableExcludeSchemas ] )
85116
@@ -96,8 +127,8 @@ export const useIsProtectedSchema = ({
96127 schema : string
97128 excludedSchemas ?: string [ ]
98129} ) :
99- | { isSchemaLocked : false ; reason : undefined }
100- | { isSchemaLocked : true ; reason : 'fdw ' | 'internal' } => {
130+ | { isSchemaLocked : false ; reason : undefined ; fdwType : undefined }
131+ | { isSchemaLocked : true ; reason : 'internal ' | 'fdw' ; fdwType : string | undefined } => {
101132 const { data : schemas } = useProtectedSchemas ( { excludeSchemas : excludedSchemas } )
102133
103134 const foundSchema = schemas . find ( ( s ) => s . name === schema )
@@ -106,7 +137,8 @@ export const useIsProtectedSchema = ({
106137 return {
107138 isSchemaLocked : true ,
108139 reason : foundSchema . type ,
140+ fdwType : foundSchema . fdwType ,
109141 }
110142 }
111- return { isSchemaLocked : false , reason : undefined }
143+ return { isSchemaLocked : false , reason : undefined , fdwType : undefined }
112144}
0 commit comments