From 3133098c7b2d6b04f1c2bf091cf68e3de2ab2606 Mon Sep 17 00:00:00 2001 From: TheOtherBrian1 <91111415+TheOtherBrian1@users.noreply.github.com> Date: Tue, 29 Jul 2025 04:18:55 -0400 Subject: [PATCH 1/4] Update postgis.mdx (#37521) * Update postgis.mdx * run pnpm format to fix prettier errors --------- Co-authored-by: PLyn --- .../guides/database/extensions/postgis.mdx | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/apps/docs/content/guides/database/extensions/postgis.mdx b/apps/docs/content/guides/database/extensions/postgis.mdx index c5588a1b93fac..c338c1ac912b4 100644 --- a/apps/docs/content/guides/database/extensions/postgis.mdx +++ b/apps/docs/content/guides/database/extensions/postgis.mdx @@ -436,12 +436,6 @@ val data = supabase.postgrest.rpc( ## Troubleshooting - - -The [official PostGIS documentation](https://postgis.net/documentation/tips/tip-move-postgis-schema/) for relocating the schema will cause issues for Supabase projects. These issues might not be apparent immediately but will eventually surface. To relocate your schema, use the following steps instead. - - - As of PostGIS 2.3 or newer, the PostGIS extension is no longer relocatable from one schema to another. If you need to move it from one schema to another for any reason (e.g. from the public schema to the extensions schema for security reasons), you would normally run a ALTER EXTENSION to relocate the schema. However, you will now to do the following steps: 1. Backup your Database to prevent data loss - You can do this through the [CLI](https://supabase.com/docs/reference/cli/supabase-db-dump) or Postgres backup tools such as [pg_dumpall](https://www.postgresql.org/docs/current/backup-dump.html#BACKUP-DUMP-ALL) @@ -452,6 +446,28 @@ As of PostGIS 2.3 or newer, the PostGIS extension is no longer relocatable from 4. Restore dropped data via the Backup if necessary from step 1 with your tool of choice. +Alternatively, you can contact the [Supabase Support Team](https://supabase.com/dashboard/support/new) and ask them to run the following SQL on your instance: + +```sql +BEGIN; + UPDATE pg_extension + SET extrelocatable = true + WHERE extname = 'postgis'; + + ALTER EXTENSION postgis + SET SCHEMA extensions; + + ALTER EXTENSION postgis + UPDATE TO "next"; + + ALTER EXTENSION postgis UPDATE; + + UPDATE pg_extension + SET extrelocatable = false + WHERE extname = 'postgis'; +COMMIT; +``` + ## Resources - [Official PostGIS documentation](https://postgis.net/documentation/) From 5da5ad06c0be8b482d772d336ed295a1349b58a8 Mon Sep 17 00:00:00 2001 From: Joshen Lim Date: Tue, 29 Jul 2025 16:33:14 +0800 Subject: [PATCH 2/4] Shift pipeline status page to its own route (#37431) * Shift pipeline status page to its own route * Fix back link --- .../Database/Replication/DestinationRow.tsx | 25 ++++---- .../Database/Replication/Destinations.tsx | 8 +-- .../Replication/Replication.constants.ts | 1 + .../Replication/ReplicationPipelineStatus.tsx | 57 ++++++------------- .../Database/Replication/RowMenu.tsx | 41 ++----------- .../data/replication/pipelines-query.ts | 1 + .../database/replication/[pipelineId].tsx | 50 ++++++++++++++++ .../[ref]/database/replication/index.tsx | 29 +--------- 8 files changed, 87 insertions(+), 125 deletions(-) create mode 100644 apps/studio/components/interfaces/Database/Replication/Replication.constants.ts create mode 100644 apps/studio/pages/project/[ref]/database/replication/[pipelineId].tsx diff --git a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx index 04386674eeb7f..5e693553554be 100644 --- a/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx +++ b/apps/studio/components/interfaces/Database/Replication/DestinationRow.tsx @@ -1,3 +1,4 @@ +import Link from 'next/link' import { useEffect, useState } from 'react' import { toast } from 'sonner' @@ -6,24 +7,22 @@ import Table from 'components/to-be-cleaned/Table' import AlertError from 'components/ui/AlertError' import { useDeleteDestinationMutation } from 'data/replication/delete-destination-mutation' import { useReplicationPipelineStatusQuery } from 'data/replication/pipeline-status-query' -import { ReplicationPipelinesData } from 'data/replication/pipelines-query' +import { Pipeline } from 'data/replication/pipelines-query' import { useStopPipelineMutation } from 'data/replication/stop-pipeline-mutation' import { PipelineStatusRequestStatus, usePipelineRequestStatus, } from 'state/replication-pipeline-request-status' import { ResponseError } from 'types' +import { Button } from 'ui' import ShimmeringLoader from 'ui-patterns/ShimmeringLoader' import DeleteDestination from './DeleteDestination' import DestinationPanel from './DestinationPanel' import { getStatusName, PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' import { PipelineStatus, PipelineStatusName } from './PipelineStatus' +import { STATUS_REFRESH_FREQUENCY_MS } from './Replication.constants' import { RowMenu } from './RowMenu' -export type Pipeline = ReplicationPipelinesData['pipelines'][0] - -const refreshFrequencyMs: number = 2000 - interface DestinationRowProps { sourceId: number | undefined destinationId: number @@ -34,7 +33,6 @@ interface DestinationRowProps { isLoading: boolean isError: boolean isSuccess: boolean - onSelectPipeline?: (pipelineId: number, destinationName: string) => void } export const DestinationRow = ({ @@ -47,7 +45,6 @@ export const DestinationRow = ({ isLoading: isPipelineLoading, isError: isPipelineError, isSuccess: isPipelineSuccess, - onSelectPipeline, }: DestinationRowProps) => { const { ref: projectRef } = useParams() const [showDeleteDestinationForm, setShowDeleteDestinationForm] = useState(false) @@ -64,7 +61,7 @@ export const DestinationRow = ({ projectRef, pipelineId: pipeline?.id, }, - { refetchInterval: refreshFrequencyMs } + { refetchInterval: STATUS_REFRESH_FREQUENCY_MS } ) const { getRequestStatus, updatePipelineStatus } = usePipelineRequestStatus() const requestStatus = pipeline?.id @@ -107,12 +104,7 @@ export const DestinationRow = ({ )} {isPipelineSuccess && ( - { - if (pipeline) onSelectPipeline?.(pipeline.id, destinationName) - }} - > + {isPipelineLoading ? : destinationName} {isPipelineLoading ? : type} @@ -138,6 +130,11 @@ export const DestinationRow = ({
+ void -} - -export const Destinations = ({ onSelectPipeline = noop }: DestinationsProps) => { +export const Destinations = () => { const [showNewDestinationPanel, setShowNewDestinationPanel] = useState(false) const [filterString, setFilterString] = useState('') const { ref: projectRef } = useParams() @@ -122,7 +117,6 @@ export const Destinations = ({ onSelectPipeline = noop }: DestinationsProps) => isLoading={isPipelinesLoading} isError={isPipelinesError} isSuccess={isPipelinesSuccess} - onSelectPipeline={onSelectPipeline} /> ) })} diff --git a/apps/studio/components/interfaces/Database/Replication/Replication.constants.ts b/apps/studio/components/interfaces/Database/Replication/Replication.constants.ts new file mode 100644 index 0000000000000..273adac9f5bf6 --- /dev/null +++ b/apps/studio/components/interfaces/Database/Replication/Replication.constants.ts @@ -0,0 +1 @@ +export const STATUS_REFRESH_FREQUENCY_MS: number = 5000 diff --git a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.tsx b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.tsx index 24d41862f06be..29ccd56c33392 100644 --- a/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.tsx +++ b/apps/studio/components/interfaces/Database/Replication/ReplicationPipelineStatus.tsx @@ -20,23 +20,15 @@ import { Badge, Button, cn, copyToClipboard, Input_Shadcn_ } from 'ui' import { GenericSkeletonLoader } from 'ui-patterns' import { getStatusName, PIPELINE_ERROR_MESSAGES } from './Pipeline.utils' import { PipelineStatus } from './PipelineStatus' +import { STATUS_REFRESH_FREQUENCY_MS } from './Replication.constants' import { TableState } from './ReplicationPipelineStatus.types' import { getDisabledStateConfig, getStatusConfig } from './ReplicationPipelineStatus.utils' -interface ReplicationPipelineStatusProps { - pipelineId: number - destinationName?: string - onSelectBack: () => void -} - -export const ReplicationPipelineStatus = ({ - pipelineId, - destinationName, - onSelectBack, -}: ReplicationPipelineStatusProps) => { - const { ref: projectRef } = useParams() +export const ReplicationPipelineStatus = () => { + const { ref: projectRef, pipelineId: _pipelineId } = useParams() const [filterString, setFilterString] = useState('') + const pipelineId = Number(_pipelineId) const { getRequestStatus, updatePipelineStatus, setRequestStatus } = usePipelineRequestStatus() const requestStatus = getRequestStatus(pipelineId) @@ -60,7 +52,7 @@ export const ReplicationPipelineStatus = ({ { projectRef, pipelineId }, { enabled: !!pipelineId, - refetchInterval: 2000, // Poll every 2 seconds + refetchInterval: STATUS_REFRESH_FREQUENCY_MS, } ) @@ -73,13 +65,14 @@ export const ReplicationPipelineStatus = ({ { projectRef, pipelineId }, { enabled: !!pipelineId, - refetchInterval: 2000, // Poll every 2 seconds + refetchInterval: STATUS_REFRESH_FREQUENCY_MS, } ) const { mutateAsync: startPipeline, isLoading: isStartingPipeline } = useStartPipelineMutation() const { mutateAsync: stopPipeline, isLoading: isStoppingPipeline } = useStopPipelineMutation() + const destinationName = pipeline?.destination_name const statusName = getStatusName(pipelineStatusData?.status) const config = getDisabledStateConfig({ requestStatus, statusName }) @@ -138,36 +131,13 @@ export const ReplicationPipelineStatus = ({ updatePipelineStatus(pipelineId, statusName) }, [pipelineId, statusName, updatePipelineStatus]) - if (isPipelineError) { - return ( -
-
-
-
-
- -
- ) - } - return (
- {/* Header with back button and filters */}
-

{destinationName || 'Pipeline'}

@@ -192,13 +162,14 @@ export const ReplicationPipelineStatus = ({ className="pl-7 h-[26px] text-xs" placeholder="Search for tables" value={filterString} + disabled={isPipelineError} onChange={(e) => setFilterString(e.target.value)} />