Загрузка...

Операция...

Supabase Admin

Подключение


SQL Настройка

Для работы панели выполните SQL скрипт в вашем Supabase проекте (SQL Editor):


-- SQL скрипты для Supabase Admin Panel

-- 1. Функция для тестирования соединения
CREATE OR REPLACE FUNCTION test_connection_schema()
RETURNS TABLE (schema_name information_schema.sql_identifier) AS $$
BEGIN
    RETURN QUERY SELECT s.schema_name FROM information_schema.schemata s LIMIT 1;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 2. Функция для получения списка пользовательских таблиц
CREATE OR REPLACE FUNCTION get_public_user_tables()
RETURNS TABLE (table_name information_schema.sql_identifier) AS $$
BEGIN
    RETURN QUERY
    SELECT t.table_name
    FROM information_schema.tables t
    WHERE t.table_schema = 'public'
      AND t.table_type = 'BASE TABLE'
      AND t.table_name NOT LIKE 'pg_%'
      AND t.table_name NOT LIKE 'sql_%'
      AND t.table_name NOT IN (
        'supabase_migrations', 'pg_stat_statements', 'pg_stat_statements_info',
        'spatial_ref_sys', 'geography_columns', 'geometry_columns'
      )
    ORDER BY t.table_name;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 3. Функция для поиска данных в таблице (с пагинацией)
CREATE OR REPLACE FUNCTION search_table_data(
    p_table_name TEXT,
    p_search_text TEXT,
    p_limit INT,
    p_offset INT
)
RETURNS SETOF JSON -- Возвращает строки в формате JSON
AS $$
DECLARE
    searchable_cols TEXT[];
    where_clause TEXT := '1=1';
    search_word TEXT;
    query TEXT;
    order_by_col TEXT;
BEGIN
    -- Находим все колонки, в которых можно искать (текстовые и json/jsonb)
    SELECT array_agg(column_name::TEXT)
    INTO searchable_cols
    FROM information_schema.columns
    WHERE table_schema = 'public'
      AND table_name = p_table_name
      AND (
        data_type IN ('character varying', 'text', 'character') OR
        udt_name IN ('json', 'jsonb')
      );

    -- Если есть поисковый текст и колонки для поиска
    IF p_search_text IS NOT NULL AND p_search_text != '' AND array_length(searchable_cols, 1) > 0 THEN
        where_clause := '';
        -- Для каждого слова в поисковом запросе
        FOREACH search_word IN ARRAY string_to_array(p_search_text, ' ')
        LOOP
            IF search_word != '' THEN
                IF where_clause != '' THEN
                    where_clause := where_clause || ' AND ';
                END IF;
                -- Строим OR условие для одного слова по всем колонкам
                where_clause := where_clause || '(' || array_to_string(
                    ARRAY(
                        SELECT format('%I::text ILIKE %L', col_name, '%' || search_word || '%')
                        FROM unnest(searchable_cols) AS col_name
                    ),
                    ' OR '
                ) || ')';
            END IF;
        END LOOP;
    END IF;

    -- Находим первичный ключ для стабильной сортировки
    SELECT kcu.column_name INTO order_by_col
    FROM information_schema.table_constraints AS tc
    JOIN information_schema.key_column_usage AS kcu
        ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
    WHERE tc.constraint_type = 'PRIMARY KEY'
    AND tc.table_schema = 'public' AND tc.table_name = p_table_name
    LIMIT 1;

    -- Если первичный ключ не найден, используем первую колонку таблицы как запасной вариант
    IF order_by_col IS NULL THEN
        SELECT column_name INTO order_by_col
        FROM information_schema.columns
        WHERE table_schema = 'public' AND table_name = p_table_name
        ORDER BY ordinal_position
        LIMIT 1;
    END IF;

    -- Строим и выполняем безопасный динамический запрос с правильной сортировкой
    query := format(
        'SELECT to_json(t.*) FROM public.%I AS t WHERE %s ORDER BY t.%I LIMIT %s OFFSET %s',
        p_table_name,
        where_clause,
        order_by_col, -- Используем найденную колонку для сортировки
        p_limit,
        p_offset
    );

    RETURN QUERY EXECUTE query;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

-- 4. Функция для подсчета строк при поиске
CREATE OR REPLACE FUNCTION search_table_count(
    p_table_name TEXT,
    p_search_text TEXT
)
RETURNS INT
AS $$
DECLARE
    searchable_cols TEXT[];
    where_clause TEXT := '1=1';
    search_word TEXT;
    query TEXT;
    row_count INT;
BEGIN
    -- Логика определения колонок и построения WHERE такая же, как в search_table_data
    SELECT array_agg(column_name::TEXT)
    INTO searchable_cols
    FROM information_schema.columns
    WHERE table_schema = 'public'
      AND table_name = p_table_name
      AND (
        data_type IN ('character varying', 'text', 'character') OR
        udt_name IN ('json', 'jsonb')
      );

    IF p_search_text IS NOT NULL AND p_search_text != '' AND array_length(searchable_cols, 1) > 0 THEN
        where_clause := '';
        FOREACH search_word IN ARRAY string_to_array(p_search_text, ' ')
        LOOP
            IF search_word != '' THEN
                IF where_clause != '' THEN
                    where_clause := where_clause || ' AND ';
                END IF;
                where_clause := where_clause || '(' || array_to_string(
                    ARRAY(
                        SELECT format('%I::text ILIKE %L', col_name, '%' || search_word || '%')
                        FROM unnest(searchable_cols) AS col_name
                    ),
                    ' OR '
                ) || ')';
            END IF;
        END LOOP;
    END IF;

    query := format('SELECT count(*) FROM public.%I WHERE %s', p_table_name, where_clause);
    EXECUTE query INTO row_count;
    RETURN row_count;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;


-- Выдаем права на все функции
GRANT EXECUTE ON FUNCTION public.test_connection_schema() TO service_role;
GRANT EXECUTE ON FUNCTION public.get_public_user_tables() TO service_role;
GRANT EXECUTE ON FUNCTION public.search_table_data(TEXT, TEXT, INT, INT) TO service_role;
GRANT EXECUTE ON FUNCTION public.search_table_count(TEXT, TEXT) TO service_role;
                    

Панель:

Таблицы (схема: public)

Buckets (Хранилище)

Files in Bucket

Имя Размер Изменен Полный путь

Table Data