无状态与有状态查询

问题描述 投票:0回答:1

我在supabase postgres工作并编写了多个postgres函数

DROP FUNCTION IF EXISTS setup_auth_user;

CREATE OR REPLACE FUNCTION setup_auth_user(
    email_value TEXT,
    name_value TEXT,     
    password_value TEXT,
    wallet_address_value TEXT,
    private_key_value TEXT
) RETURNS user_info AS $$
DECLARE
    updated_user_info user_info;
BEGIN
    INSERT INTO user_info (user_state, email, name, password, updated_at)
    VALUES ('active'::user_state, email_value, name_value, password_value, now())
    RETURNING * INTO updated_user_info;

    insert into user_wallet_info (private_key, wallet_address, user_id)
    VALUES (private_key_value, wallet_address_value, updated_user_info.id);

    RETURN updated_user_info;
END;
$$ LANGUAGE plpgsql;

然后说这个

DROP FUNCTION IF EXISTS public.get_user_with_authenticator;

CREATE OR REPLACE FUNCTION public.get_user_with_authenticator(session_id_value text)
 RETURNS jsonb
 LANGUAGE sql
AS $function$
    SELECT jsonb_build_object(
        'email', u.email,
        'name', u.name,
        'id', u.id,
        'user_state', u.user_state,
        'credential_id', pa.credential_id,
        'credential_public_key', pa.credential_public_key,
        'counter', pa.counter,
        'transports', pa.transports,
        'challenge', p.passkey_challenge
    )
    FROM passkey_sessions AS p 
    LEFT JOIN user_info AS u ON u.email = p.email
    LEFT JOIN passkey_authenticator AS pa ON pa.id = u.authenticator_id
    WHERE p.session_id = session_id_value;
$function$;

我在后端调用插入函数,在前端调用

setup_auth_user
get_user_with_authenticator

为此我收到了这个反馈

使用无状态查询似乎比每次编辑函数时都必须创建/更新函数更容易调试。您也不需要迁移来更改查询。

有人可以解释一下无状态查询是什么意思吗?如果这是一个好主意?

postgresql plpgsql supabase
1个回答
0
投票

这听起来不像是反馈作者的问题,但我的理解是,statefulstateless之间的查询区别,虽然不一定是任何官方/广泛使用的术语,但指的是你的函数的事实 -必须先定义包装查询并将其呈现在数据库上,然后才能使用

select
调用它,而原始/未包装/直接/无状态查询不需要。

“无状态”查询只需在发出该查询的应用程序代码中维护。如果您使用函数包装器,则需要在应用程序中维护使用

select
调用它的代码,以及数据库中的定义,并且要更改数据库,您需要迁移。当您更改某些内容时,您需要在两个位置更新代码,如果有大量配置为由迁移触发的前后步骤(备份、验证、完整性检查、测试),其中之一可能会很复杂/具有侵入性。如果直接使用查询,只需更改查询即可。

功能包装有一些优点,如果你来这里是为了弹药来反击这个反馈:

  1. 查询逻辑被抽象掉,只留下一个调用,最好有一个描述性的、富有表现力的名称。
  2. 该函数可以在多个地方重用,类似于准备好的语句或带有占位符的查询字符串(如果您喜欢 SQL 注入)。如果可以的话,您不需要在多个位置复制相同的大查询。
  3. 每当查询目标对象发生变化,或者查询本身被 linter 优化、重构、纠正时,所有函数调用都保持不变。
  4. 您正在减少 SQL 语法与应用程序语言的混合。您可以在设计或配置为理解 SQL 的工具中读取和处理 SQL,而无需尝试检测或捕获出现在其他语言字符串中的 SQL。这与 1 和 2 一起使用。
  5. 您的迁移是纯 SQL 脚本,您可能也有处理这些脚本的工具。通过将查询与 SQL 代码库的其余部分放在一起,您可以一次性处理所有这些。在定义它引用的所有对象的地方维护查询也可能更容易,并且发现对表的更改需要级联到包装广泛使用的针对它的查询的函数。
© www.soinside.com 2019 - 2024. All rights reserved.