Обсуждение: Strange DOMAIN behavior

Поиск
Список
Период
Сортировка

Strange DOMAIN behavior

От
Alex Ignatov
Дата:
Hello everyone!!!
Got strange DOMAIN behavior in the following plpgsql code:

postgres=# DROP DOMAIN lexema_str CASCADE;
DROP DOMAIN
postgres=# CREATE DOMAIN lexema_str TEXT DEFAULT 'abc';
CREATE DOMAIN
postgres=# DO $$
postgres$# DECLARE
postgres$#    lex lexema_str;
postgres$# BEGIN
postgres$#    RAISE NOTICE 'lex = %', lex;
postgres$# END;
postgres$# $$;
NOTICE:  lex = <NULL>
DO

But i expect that lex = abc!

So default value of DOMAIN type is not set in pgplsql block but:

postgres=# DROP DOMAIN lexema_str CASCADE;
DROP DOMAIN
postgres=# CREATE DOMAIN lexema_str TEXT DEFAULT 'abc' NOT NULL;
CREATE DOMAIN
postgres=# DO $$
postgres$# DECLARE
postgres$#    lex lexema_str;
postgres$# BEGIN
postgres$#    RAISE NOTICE 'lex = %', lex;
postgres$# END;
postgres$# $$;
ERROR:  domain lexema_str does not allow null values
CONTEXT:  PL/pgSQL function inline_code_block line 4 during statement 
block local variable initialization

So constraints in DOMAIN type work in pgplsql !

Is this correct behavior??




-- 
Alex Ignatov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company


---
This email has been checked for viruses by Avast antivirus software.
https://www.avast.com/antivirus




Strange DOMAIN behavior

От
"David G. Johnston"
Дата:
On Thursday, July 9, 2015, Alex Ignatov <a.ignatov@postgrespro.ru> wrote:
Hello everyone!!!
Got strange DOMAIN behavior in the following plpgsql code:

But i expect that lex = abc!

So default value of DOMAIN type is not set in pgplsql block but:

Is this correct behavior??


If you read the create domain sql command documentation carefully the default clause is only used when inserting into a table that has a column of the domain type that is not explicitly provided a value.  Each language deals with domains differently and the behavior you expect is not currently implemented in pl/pgsql.  If you want a default inside the procedure you need to declare one explicitly.

David J.

Re: Strange DOMAIN behavior

От
Alex Ignatov
Дата:
Thank you for your reply.
In fact i want to use domains in the following case:

DROP DOMAIN lexema_str CASCADE;
CREATE DOMAIN lexema_str TEXT DEFAULT 'abc' NOT NULL;
DROP TYPE lexema_test CASCADE;
CREATE TYPE lexema_test AS (
   lex  lexema_str,
   lex2 BIGINT
);
DROP TABLE ttt;
CREATE TABLE ttt (
   a lexema_test,
   b BIGINT
);
INSERT INTO ttt (b) VALUES (1);
SELECT *
FROM ttt;
 a | b
---+---
   | 1
(1 row)

 a.lex is null  again not 'abc' as I expected like in plpgsql.

All i want is to have default values in composite types. Feature that Oracle have.
I thought that with domain type it should be possible.





On 09.07.2015 15:49, David G. Johnston wrote:
On Thursday, July 9, 2015, Alex Ignatov <a.ignatov@postgrespro.ru> wrote:
Hello everyone!!!
Got strange DOMAIN behavior in the following plpgsql code:

But i expect that lex = abc!

So default value of DOMAIN type is not set in pgplsql block but:

Is this correct behavior??


If you read the create domain sql command documentation carefully the default clause is only used when inserting into a table that has a column of the domain type that is not explicitly provided a value.  Each language deals with domains differently and the behavior you expect is not currently implemented in pl/pgsql.  If you want a default inside the procedure you need to declare one explicitly.

David J.

-- 
Alex Ignatov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company




Avast logo

This email has been checked for viruses by Avast antivirus software.
www.avast.com


Re: Strange DOMAIN behavior

От
"David G. Johnston"
Дата:
On Thu, Jul 9, 2015 at 10:10 AM, Alex Ignatov <a.ignatov@postgrespro.ru> wrote:
Thank you for your reply.
In fact i want to use domains in the following case:

DROP DOMAIN lexema_str CASCADE;
CREATE DOMAIN lexema_str TEXT DEFAULT 'abc' NOT NULL;
DROP TYPE lexema_test CASCADE;
CREATE TYPE lexema_test AS (
   lex  lexema_str,
   lex2 BIGINT
);
DROP TABLE ttt;
CREATE TABLE ttt (
   a lexema_test,
   b BIGINT
);
INSERT INTO ttt (b) VALUES (1);
SELECT *
FROM ttt;
 a | b
---+---
   | 1
(1 row)

 a.lex is null  again not 'abc' as I expected like in plpgsql.

All i want is to have default values in composite types. Feature that Oracle have.
I thought that with domain type it should be possible.


Please don't top-post.

So even though ​there is no default specified for column a you expect there to be a non-null value even though the column was omitted from the insert statement?  I doubt that such a change in behavior would be accepted.

​As far as I know the less-redundant way to accomplish your goal is to create a constructor function for the type (CREATE FUNCTION default_type() RETURNS type) and call it where you need to interject a default.

CREATE TABLE ttt ( a lexema_test DEFAULT ROW(default_type(), NULL)::lexema_test​ )

There likely isn't any hard reasons behind the lack of capabilities wrt. defaults and composites/domains; its just that no one has been bothered enough to affect change.

David J.

Re: Strange DOMAIN behavior

От
Alex Ignatov
Дата:


On 09.07.2015 17:23, David G. Johnston wrote:
On Thu, Jul 9, 2015 at 10:10 AM, Alex Ignatov <a.ignatov@postgrespro.ru> wrote:
Thank you for your reply.
In fact i want to use domains in the following case:

DROP DOMAIN lexema_str CASCADE;
CREATE DOMAIN lexema_str TEXT DEFAULT 'abc' NOT NULL;
DROP TYPE lexema_test CASCADE;
CREATE TYPE lexema_test AS (
   lex  lexema_str,
   lex2 BIGINT
);
DROP TABLE ttt;
CREATE TABLE ttt (
   a lexema_test,
   b BIGINT
);
INSERT INTO ttt (b) VALUES (1);
SELECT *
FROM ttt;
 a | b
---+---
   | 1
(1 row)

 a.lex is null  again not 'abc' as I expected like in plpgsql.

All i want is to have default values in composite types. Feature that Oracle have.
I thought that with domain type it should be possible.


Please don't top-post.

So even though ​there is no default specified for column a you expect there to be a non-null value even though the column was omitted from the insert statement?  I doubt that such a change in behavior would be accepted.

​As far as I know the less-redundant way to accomplish your goal is to create a constructor function for the type (CREATE FUNCTION default_type() RETURNS type) and call it where you need to interject a default.

CREATE TABLE ttt ( a lexema_test DEFAULT ROW(default_type(), NULL)::lexema_test​ )

There likely isn't any hard reasons behind the lack of capabilities wrt. defaults and composites/domains; its just that no one has been bothered enough to affect change.

David J.

Sorry for top-post.
It is sad but constructor function for composite type doesn't work in declare block. For example:

CREATE OR REPLACE FUNCTION new_lexema()
   RETURNS lexema AS $body$
DECLARE
   lex lexema;
BEGIN
   lex=ROW ('tt',0);
   RETURN lex;
END;
$body$
LANGUAGE PLPGSQL
SECURITY DEFINER;

DROP FUNCTION lexema_test( );
CREATE OR REPLACE FUNCTION lexema_test()
   RETURNS VOID AS $body$
DECLARE
   lex lexema :=new_lexema();
BEGIN
END;
$body$
LANGUAGE PLPGSQL
SECURITY DEFINER;

Then I got:
ERROR:  default value for row or record variable is not supported
LINE 17:    lex lexema :=new_lexema();





-- 
Alex Ignatov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company




Avast logo

This email has been checked for viruses by Avast antivirus software.
www.avast.com


Re: Strange DOMAIN behavior

От
"David G. Johnston"
Дата:
On Thu, Jul 9, 2015 at 12:42 PM, Alex Ignatov <a.ignatov@postgrespro.ru> wrote:
DROP FUNCTION lexema_test( );
CREATE OR REPLACE FUNCTION lexema_test()
   RETURNS VOID AS $body$
DECLARE
   lex lexema :=new_lexema();
BEGIN
END;
$body$
LANGUAGE PLPGSQL
SECURITY DEFINER;

Then I got:
ERROR:  default value for row or record variable is not supported
LINE 17:    lex lexema :=new_lexema();


​Undocumented limitation :(

While slightly more verbose you simply need to:

DECLARE lex lexema;
BEGIN
lex := new_lexema();
[...]

David J.

Re: Strange DOMAIN behavior

От
Alex Ignatov
Дата:


On 09.07.2015 19:50, David G. Johnston wrote:
On Thu, Jul 9, 2015 at 12:42 PM, Alex Ignatov <a.ignatov@postgrespro.ru> wrote:
DROP FUNCTION lexema_test( );
CREATE OR REPLACE FUNCTION lexema_test()
   RETURNS VOID AS $body$
DECLARE
   lex lexema :=new_lexema();
BEGIN
END;
$body$
LANGUAGE PLPGSQL
SECURITY DEFINER;

Then I got:
ERROR:  default value for row or record variable is not supported
LINE 17:    lex lexema :=new_lexema();



​Undocumented limitation :(

While slightly more verbose you simply need to:

DECLARE lex lexema;
BEGIN
lex := new_lexema();
[...]

David J.

Thats sad =(. But it is not so gracefully to initialize composite type in the begin block as it would be in declare block %).
Thank you for yours answers!
-- 
Alex Ignatov
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company




Avast logo

This email has been checked for viruses by Avast antivirus software.
www.avast.com