diff --git a/studio/components/interfaces/Database/Migrations/Migrations.tsx b/studio/components/interfaces/Database/Migrations/Migrations.tsx
index fcf2f7649e9..b3e2172d214 100644
--- a/studio/components/interfaces/Database/Migrations/Migrations.tsx
+++ b/studio/components/interfaces/Database/Migrations/Migrations.tsx
@@ -9,6 +9,7 @@ import ShimmeringLoader from 'components/ui/ShimmeringLoader'
import { DatabaseMigration, useMigrationsQuery } from 'data/database/migrations-query'
import { Editor } from '@monaco-editor/react'
import CodeEditor from 'components/ui/CodeEditor'
+import MigrationsEmptyState from './MigrationsEmptyState'
const Wrappers = () => {
const [search, setSearch] = useState('')
@@ -24,6 +25,8 @@ const Wrappers = () => {
? data?.result ?? []
: data?.result.filter((migration) => migration.version.includes(search)) ?? []
+ console.log({ data })
+
return (
<>
@@ -80,51 +83,52 @@ const Wrappers = () => {
)}
{isSuccess && (
-
- setSearch(e.target.value)}
- icon={ }
- />
-
-
- {data.result.length <= 0 &&
No migrations state...
}
+ {data.result.length <= 0 &&
}
{data.result.length > 0 && (
-
Version,
- ,
- ]}
- body={
- migrations.length > 0 ? (
- migrations.map((migration) => (
-
- {migration.version}
-
- setSelectedMigration(migration)}
- >
- View migration SQL
-
+ <>
+
+ setSearch(e.target.value)}
+ icon={ }
+ />
+
+ Version,
+ ,
+ ]}
+ body={
+ migrations.length > 0 ? (
+ migrations.map((migration) => (
+
+ {migration.version}
+
+ setSelectedMigration(migration)}
+ >
+ View migration SQL
+
+
+
+ ))
+ ) : (
+
+
+ No results found
+
+ Your search for "{search}" did not return any results
+
- ))
- ) : (
-
-
- No results found
-
- Your search for "{search}" did not return any results
-
-
-
- )
- }
- />
+ )
+ }
+ />
+ >
)}
)}
diff --git a/studio/components/interfaces/Database/Migrations/MigrationsEmptyState.tsx b/studio/components/interfaces/Database/Migrations/MigrationsEmptyState.tsx
new file mode 100644
index 00000000000..55ef19b3ea7
--- /dev/null
+++ b/studio/components/interfaces/Database/Migrations/MigrationsEmptyState.tsx
@@ -0,0 +1,111 @@
+import clsx from 'clsx'
+import Link from 'next/link'
+import { useState } from 'react'
+import {
+ Button,
+ Collapsible,
+ IconExternalLink,
+ IconMaximize2,
+ IconMinimize2,
+ IconTerminal,
+} from 'ui'
+
+import CommandRender from 'components/interfaces/Functions/CommandRender'
+import { useParams } from 'common'
+
+const MigrationsEmptyState = () => {
+ const { ref } = useParams()
+ const [showInstructions, setShowInstructions] = useState(false)
+
+ const commands = [
+ {
+ comment: 'Link your project',
+ command: `supabase link --project-ref ${ref}`,
+ jsx: () => {
+ return (
+ <>
+ supabase link --project-ref {ref}
+ >
+ )
+ },
+ },
+ {
+ comment: 'Create a new migration called "new-migration"',
+ command: `supabase migration new new-migration`,
+ jsx: () => {
+ return (
+ <>
+ supabase migration new new-migration
+ >
+ )
+ },
+ },
+ {
+ comment: 'Run all migrations against this project',
+ command: `supabase db push`,
+ jsx: () => {
+ return (
+ <>
+ supabase db push
+ >
+ )
+ },
+ },
+ ]
+
+ return (
+
+
+
+
Database migrations
+
+ Database changes are managed through "migrations" and they are a common way of tracking
+ changes to your database over time. You can run migrations against your project's
+ database via the Supabase CLI.
+
+
+
+
+
+
+
+
+
+
+
+
Terminal instructions
+
+ {showInstructions ? (
+
+ ) : (
+
+ )}
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+export default MigrationsEmptyState
diff --git a/studio/data/database/migrations-query.ts b/studio/data/database/migrations-query.ts
index 00e24118c3c..f9a25136e8b 100644
--- a/studio/data/database/migrations-query.ts
+++ b/studio/data/database/migrations-query.ts
@@ -36,6 +36,16 @@ export const useMigrationsQuery = {
+ if (
+ error.code === 400 &&
+ error.message.includes('relation "supabase_migrations.schema_migrations" does not exist')
+ ) {
+ return { result: [] }
+ } else {
+ throw error
+ }
+ },
},
options
)
diff --git a/studio/data/sql/execute-sql-query.ts b/studio/data/sql/execute-sql-query.ts
index 1eb86b56373..76ef0f665aa 100644
--- a/studio/data/sql/execute-sql-query.ts
+++ b/studio/data/sql/execute-sql-query.ts
@@ -10,12 +10,16 @@ import { post } from 'lib/common/fetch'
import { API_URL } from 'lib/constants'
import { useCallback } from 'react'
import { sqlKeys } from './keys'
+import { noop } from 'lodash'
+
+export type Error = { code: number; message: string; requestId: string }
export type ExecuteSqlVariables = {
projectRef?: string
connectionString?: string
sql: string
queryKey?: QueryKey
+ handleError?: (error: { code: number; message: string; requestId: string }) => any
}
export async function executeSql(
@@ -24,7 +28,11 @@ export async function executeSql(
connectionString,
sql,
queryKey,
- }: Pick,
+ handleError,
+ }: Pick<
+ ExecuteSqlVariables,
+ 'projectRef' | 'connectionString' | 'sql' | 'queryKey' | 'handleError'
+ >,
signal?: AbortSignal
) {
if (!projectRef) {
@@ -44,8 +52,13 @@ export async function executeSql(
{ query: sql },
{ headers: Object.fromEntries(headers), signal }
)
+
if (response.error) {
- throw response.error
+ if (handleError !== undefined) {
+ return handleError(response.error)
+ } else {
+ throw response.error
+ }
}
return { result: response }
@@ -55,21 +68,22 @@ export type ExecuteSqlData = Awaited>
export type ExecuteSqlError = unknown
export const useExecuteSqlQuery = (
- { projectRef, connectionString, sql, queryKey }: ExecuteSqlVariables,
+ { projectRef, connectionString, sql, queryKey, handleError }: ExecuteSqlVariables,
{ enabled = true, ...options }: UseQueryOptions = {}
) =>
useQuery(
sqlKeys.query(projectRef, queryKey ?? [md5(sql)]),
- ({ signal }) => executeSql({ projectRef, connectionString, sql, queryKey }, signal),
+ ({ signal }) =>
+ executeSql({ projectRef, connectionString, sql, queryKey, handleError }, signal),
{ enabled: enabled && typeof projectRef !== 'undefined', ...options }
)
export const prefetchExecuteSql = (
client: QueryClient,
- { projectRef, connectionString, sql, queryKey }: ExecuteSqlVariables
+ { projectRef, connectionString, sql, queryKey, handleError }: ExecuteSqlVariables
) => {
return client.prefetchQuery(sqlKeys.query(projectRef, queryKey ?? [md5(sql)]), ({ signal }) =>
- executeSql({ projectRef, connectionString, sql, queryKey }, signal)
+ executeSql({ projectRef, connectionString, sql, queryKey, handleError }, signal)
)
}
@@ -89,13 +103,14 @@ export const useExecuteSqlPrefetch = () => {
const client = useQueryClient()
return useCallback(
- ({ projectRef, connectionString, sql, queryKey }: ExecuteSqlVariables) => {
+ ({ projectRef, connectionString, sql, queryKey, handleError }: ExecuteSqlVariables) => {
if (projectRef) {
return prefetchExecuteSql(client, {
projectRef,
connectionString,
sql,
queryKey,
+ handleError,
})
}