Re: Schema variables - new implementation for Postgres 15 - Mailing list pgsql-hackers

From Pavel Stehule
Subject Re: Schema variables - new implementation for Postgres 15
Date
Msg-id CAFj8pRB8kdWQCdN2X1_63c58+07Oy4Z+ruDK_xPTUP+Pe8R2Pw@mail.gmail.com
Whole thread Raw
In response to Re: Schema variables - new implementation for Postgres 15  (Peter Eisentraut <peter@eisentraut.org>)
Responses Re: Schema variables - new implementation for Postgres 15
Re: Schema variables - new implementation for Postgres 15
List pgsql-hackers


ne 2. 6. 2024 v 23:31 odesílatel Peter Eisentraut <peter@eisentraut.org> napsal:
>
> On 25.05.24 12:50, Pavel Stehule wrote:
> > It looks odd - It is not intuitive, it introduces new inconsistency
> > inside Postgres, or with solutions in other databases. No other database
> > has a similar rule, so users coming from Oracle, Db2, or MSSQL, Firebird
> > will be confused. Users that use PL/pgSQL will be confused.
>
> Do you have a description of what those other systems do?  Maybe you
> posted it already earlier?
>

I checked today

1. MySQL

MySQL knows 3 types of variables

global - the access syntax is @@varname - they are used like our GUC and only buildin system variables are supported

SET @@autocommit = off;
SELECT @@autocommit;

user defined variables - the access syntax is @varname - the behaviour is similar to psql variables, but they are server side

SET @x = 100;
SELECT @x;

local variables - only inside PL

CREATE PROCEDURE p1()
DECLARE x int;
BEGIN
  SET x = 100;
  SELECT x;
END;

variables has higher priority than column (like old plpgsql)

2. MSSQL

global variables - the access syntax is @@varname, they are used like GUC and little bit more - some state informations are there like @@ERROR, @@ROWCOUNT or @@IDENTITY

local variables - the access syntax is @varname, and should be declared before usage by DECLARE command. The scope is limited to batch or procedure or function, where DECLARE command was executed.

DECLARE @TestVariable AS VARCHAR(100)
SET @TestVariable = 'Think Green'
GO
PRINT @TestVariable

This script fails, because PRINT is executed in another batch. So I think so MSSQL doesn't support session variables

There are similar mechanisms like our custom GUC and usage current_setting and set_config functions. Generally, in this area is MSSQL very primitive

EXEC sp_set_session_context 'user_id', 4;  
SELECT SESSION_CONTEXT(N'user_id');

3. DB2

The "user defined global variables" are similar to my proposal. The differences are different access rights "READ, WRITE" x "SELECT, UPDATE". Because PostgreSQL has SET command for GUC, I introduced LET command (DB2 uses SET)

Variables are visible in all sessions, but value is private per session. Variables are not transactional. The usage is wider than my proposal. Then can be changed by commands SET, SELECT INTO or they can be used like OUT parameters of procedures. The search path (or some like that) is used for variables too, but the variables has less priority than tables/columns.

CREATE VARIABLE myCounter INT DEFAULT 01;
SELECT EMPNO, LASTNAME, CASE WHEN myCounter = 1 THEN SALARY ELSE NULL END FROM EMPLOYEE WHERE WORKDEPT = ’A00’;
SET myCounter = 29;

There are (I think) different kinds of variables - accessed by the function GETVARIABLE('name', 'default) - it looks very similar ro our GUC and `current_setting` function. These variables can be set by connection string, are of varchar type and 10 values are allowed. Built-in session variables (configuration) can be accessed by the function GETVARIABLE too.

SQL stored procedures supports declared local variables like PL/pgSQL

4. Firebird

Firebird has something like our custom GUC. But it allow nested routines - so some functionality of session variables can be emulated with local variable and nested routines (but outer variables can be used only in Firebird 5)

The variables are accessed by syntax :varname - like psql, but if I understand to diagrams, the char ':' is optional

5. SQL/PSM

Standard introduces a concept of modules that can be joined with schemas. The variables are like PLpgSQL, but only local - the only temp tables can be defined on module levels. These tables can be accessed only from routines assigned to modules. Modules are declarative versions of our extensions (if I understand well, I didn't find any implementation). It allows you to overwrite the search patch for routines assigned in the module. Variables are not transactional, the priority - variables/columns is not specified.

6. Oracle

Oracle PL/SQL allows the use of package variables. PL/SQL is +/- ADA language - and package variables are "global" variables. They are not directly visible from SQL, but Oracle allows reduced syntax for functions without arguments, so you need to write a wrapper

CREATE OR REPLACE PACKAGE my_package
AS
    FUNCTION get_a RETURN NUMBER;
END my_package;
/

CREATE OR REPLACE PACKAGE BODY my_package
AS
    a  NUMBER(20);

    FUNCTION get_a
    RETURN NUMBER
    IS
    BEGIN
      RETURN a;
    END get_a;
END my_package;

SELECT my_package.get_a FROM DUAL;

Inside SQL the higher priority has SQL, inside non SQL commands like CALL or some PL/SQL command, the higher priority has packages.

The Oracle allows both syntax for calling function with zero arguments so

SELECT my_package.get_a FROM DUAL;

or

SELECT my_package.get_a() FROM DUAL;

Then there is less risk reduction of collision. Package variables persist in session

Another possibility is using variables in SQL*Plus (looks like our psql variables, with possibility to define type on server side)

The variable should be declared by command VARIABLE and can be accessed by syntax :varname in session before usage (maybe this step is optional)

VARIABLE bv_variable_name VARCHAR2(30)

BEGIN
  :bv_variable_name := 'Some Value';
END;

SELECT column_name
FROM   table_name
WHERE  column_name = :bv_variable_name;

This is something between MSSQL and MYSQL session variables - but internally it is binding parameters - what I know, Postgres cannot set these parameters as result of some pg operation.

SQL*Plus is strange creature


Generally, the possible collision between variables and columns are solved by

a) special syntax - using prefix like @ or :
b) dedicated functions
c) variables has lower priority than columns

You can see, the RDBMS allows different types of session variables, different implementations. Usually one system allows more implementation of session variables. There is a possibility of emulation implementation between RDBMS, but security setting is possible only in Oracle or DB2.

Regards

Pavel






pgsql-hackers by date:

Previous
From: David Christensen
Date:
Subject: Re: [PATCH] psql: \dn+ to show size of each schema (and \dA+ for AMs)
Next
From: Masahiko Sawada
Date:
Subject: Revive num_dead_tuples column of pg_stat_progress_vacuum