diff --git a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx index 140fb26a64f..c5d1fab5de4 100644 --- a/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx +++ b/apps/studio/components/interfaces/Organization/TeamSettings/InviteMemberButton.tsx @@ -280,7 +280,7 @@ export const InviteMemberButton = () => { - + Invite team members diff --git a/apps/studio/data/table-rows/table-rows-count-query.ts b/apps/studio/data/table-rows/table-rows-count-query.ts index 3933afd0c73..111be34e74c 100644 --- a/apps/studio/data/table-rows/table-rows-count-query.ts +++ b/apps/studio/data/table-rows/table-rows-count-query.ts @@ -1,4 +1,5 @@ import { getTableRowsCountSql } from '@supabase/pg-meta' +import { PermissionAction } from '@supabase/shared-types/out/constants' import { QueryClient, useQuery, useQueryClient } from '@tanstack/react-query' import { IS_PLATFORM } from 'common' @@ -9,6 +10,7 @@ import type { Filter, SupaTable } from '@/components/grid/types' import { useConnectionStringForReadOps } from '@/data/read-replicas/replicas-query' import { executeSql } from '@/data/sql/execute-sql-mutation' import { prefetchTableEditor } from '@/data/table-editor/table-editor-query' +import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { RoleImpersonationState, wrapWithRoleImpersonation } from '@/lib/role-impersonation' import { isRoleImpersonationEnabled } from '@/state/role-impersonation-state' import { ResponseError, UseCustomQueryOptions } from '@/types' @@ -44,8 +46,8 @@ export async function getTableRowsCount( filters, roleImpersonationState, enforceExactCount, - isUsingReadReplica = false, - }: TableRowsCountVariables & { isUsingReadReplica?: boolean }, + isReadOnlyContext = false, + }: TableRowsCountVariables & { isReadOnlyContext?: boolean }, signal?: AbortSignal ) { const entity = await prefetchTableEditor(queryClient, { @@ -65,7 +67,7 @@ export async function getTableRowsCount( table, filters: formattedFilters, enforceExactCount, - isUsingReadReplica, + isReadOnlyContext, }), roleImpersonationState ) @@ -103,6 +105,10 @@ export const useTableRowsCountQuery = ( identifier: readReplicaIdentifier, type, } = useConnectionStringForReadOps() + const { can: canSQLAdminWrite } = useAsyncCheckPermissions( + PermissionAction.TENANT_SQL_ADMIN_WRITE, + 'tables' + ) return useQuery({ queryKey: tableRowKeys.tableRowsCount(projectRef, { @@ -117,7 +123,7 @@ export const useTableRowsCountQuery = ( projectRef, connectionString, tableId, - isUsingReadReplica: type === 'replica', + isReadOnlyContext: type === 'replica' || !canSQLAdminWrite, ...args, }, signal diff --git a/packages/pg-meta/src/sql/studio/database/rows.ts b/packages/pg-meta/src/sql/studio/database/rows.ts index c4657bbe2a0..ad6e7517453 100644 --- a/packages/pg-meta/src/sql/studio/database/rows.ts +++ b/packages/pg-meta/src/sql/studio/database/rows.ts @@ -12,12 +12,13 @@ export const getTableRowsCountSql = ({ table, filters = [], enforceExactCount = false, - isUsingReadReplica = false, + isReadOnlyContext = false, }: { table: any filters?: Filter[] enforceExactCount?: boolean - isUsingReadReplica?: boolean + /** Skips using the count estimate function if true and fallsback to checking reltuples from pg_class */ + isReadOnlyContext?: boolean }): SafeSqlFragment => { if (!table) return safeSql`` @@ -59,7 +60,7 @@ export const getTableRowsCountSql = ({ ? (countBaseSql.slice(0, -1) as SafeSqlFragment) : countBaseSql - if (isUsingReadReplica) { + if (isReadOnlyContext) { const sql = safeSql` with approximation as ( select reltuples as estimate