Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Christophe Pettus



> On Oct 18, 2022, at 19:18, gogala.mla...@gmail.com wrote:
> 
> Commit within a loop is an extremely bad idea.

This is an over-generalization.  There are many use-cases for this (if there 
were not, procedures wouldn't have been nearly as important a feature).

For example, if you are processing a large update (in the hundreds of thousands 
or more of rows), you often want to commit regularly so that other processes 
don't have to wait for the whole thing to finish due to row-level locks, and to 
give vacuum a chance to deal with the dead tuples.  Similarly, while inserting 
one row at a time and committing is usually not a great idea, it can make sense 
to do large inserts in batches.

Applications do this kind of thing all the time, very successfully; it was just 
that the loop was in the application rather than in the procedure.

High commit rates happen all the time, and they don't break PostgreSQL.  For 
example, an IoT application collecting sensor data and doing many inserts per 
second is also doing many commits per second, since each bare INSERT is in its 
own transaction.  PostgreSQL handles it just fine.



Re: Attaching database

2022-10-18 Thread Julien Rouhaud
Hi,

On Tue, Oct 18, 2022 at 10:06:40PM -0500, Igor Korot wrote:
> Hi, guys,
> After reading the documentation on
> https://www.postgresql.org/docs/current/postgres-fdw.html
> and checking the example I have a different question.
>
> The presentation in the link referenced doesn't explain how to get the
> table list on the
> remote server and the information on the specific table.
>
> The example tals about connection and creating a linked table, but it
> doesn't explain
> how to know the information about the tables on the remote
>
> Is it possible or I will have to know this beforehand?

In general it's up to you to make sure that the remote table definition matches
the local one.  You can use IMPORT FOREIGN SCHEMA (1) to automate this process,
but you will still have to make sure that any subsequent modification on the
remote table (added/removed column, changed datatype...) is also done on the
local foreign table.

> (Sorry for the top-posting).

This isn't really related to the previous discussion so it's quite ok, although
it's usually a good practice to trim the unwanted parts of the previous
message (in this case the whole previous message).

[1] https://www.postgresql.org/docs/current/sql-importforeignschema.html




Re: Attaching database

2022-10-18 Thread Igor Korot
Hi, guys,
After reading the documentation on
https://www.postgresql.org/docs/current/postgres-fdw.html
and checking the example I have a different question.

The presentation in the link referenced doesn't explain how to get the
table list on the
remote server and the information on the specific table.

The example tals about connection and creating a linked table, but it
doesn't explain
how to know the information about the tables on the remote

Is it possible or I will have to know this beforehand?

(Sorry for the top-posting).

Thank you.


On Sat, Oct 15, 2022 at 5:57 PM Alex Theodossis  wrote:
>
> Hi,
>
> you can only run inquires now on information_schema for the database you
> are connected to.
>
> If you are looking/searching in pg_database though, you can information
> globally.
>
> Something changed recently (I am using Dbeaver); I was able to attach to
> a single database and see all my databases; run queries, etc.
>
> With the latest update, now you have to have a separate connection to
> each database.
>
> Navicat now does the same thing, so my thinking is they must have
> changed the drivers.
>
> Regards,
>
> On 10/15/22 02:06, Julien Rouhaud wrote:
> > Hi,
> >
> > On Fri, Oct 14, 2022 at 11:16:44PM -0500, Igor Korot wrote:
> >> Sorry for resurrecting this old thread...
> >> If an attaching the DB creates new connection which will be cmpletely
> >> independent - how the INFORMATION_SCHEMA.table@table_catalog
> >> field is handled.
> >>
> >> Lets say I open connection to the DB (finance) and then attached another DB
> >> (finance_2021).
> >>
> >> So, when I call SELECT table_schema, table_name FROM 
> >> INFORMATION_SCHEMA.table
> >> I will get all tables from (finance) DB only.
> >> And to get all tables from (finance_2021) I need to make this catalog 
> >> current
> >> and reissue the query.
> >>
> >> Am I right?
> > No.  In postgres, databases are completely disjoint containers and once you
> > have a connection on a given database it will stay on that database, 
> > there's no
> > way around that.
> >
> > Using postgres_fdw allows you to create a local table that will point to
> > another table, possibly on another database or even another server, but it 
> > will
> > still be a (foreign) table, that has to be created in the current database 
> > in
> > the schema of your choice.
> >
> > Depending on your use case, maybe what you could do is create a finance_2021
> > schema, and create all the foreign tables you need in that schema pointing 
> > to
> > the finance_2021 database.  Any table existing in both "finance" and
> > "finance_2021" will then be visible in information_schema.tables, with a
> > different table_schema.  If you have multiple schemas in each database, then
> > find a way to make it work, maybe adding a _2021 suffix on each schema or
> > something like that.
> >
> > You can then maybe use the search_path (see
> > https://www.postgresql.org/docs/current/ddl-schemas.html#DDL-SCHEMAS-PATH) 
> > to
> > use by default one of the set of tables rather than the other.  But in any
> > case, it's only a workaround that has to be implemented on your client, as 
> > you
> > will always be connected on the same database, and see both set of object in
> > information_schema.
> >
> >
> --
> Alex Theodossis
> a...@dossi.info
> 347-514-5420
>
>
>




Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread gogala . mladen
On Tue, 2022-10-18 at 14:31 -0700, Christophe Pettus wrote:
> 
> Rather than have a loop inside the BEGIN / END, you could put the
> BEGIN EXCEPTION END inside the loop, catch the error, store the
> important parts of the exception in a variable, and then do the
> COMMIT after the END statement but before the next iteration of the
> loop.  A bit messier, but it gets the job done.

Commit within a loop is an extremely bad idea. Commit is an expensive
operation which includes incrementing the XID, which is global and not
local to the process. There is also a WAL write which has to be waited
on. Every commit implies at least one write operation. If that was not
the case, Postgres wouldn't be ACID compliant. There would be problem
with the "D". Commit within a loop will have many adverse effects on
the performance. Here is what Tom Kyte, who used to be a celebrity in
the world of Oracle, said on this topic:

https://asktom.oracle.com/pls/apex/f?p=100:11:0p11_question_id:4951966319022

Surprisingly enough, the argument in the article is mostly portable,
doesn't depend on the database type at all. Basically, transaction is a
logical unit of work. If 1000 rows need to be updated, it's better to
update them in a single transaction than in 1000 transactions. That is
particularly true for Postgres which doesn't have problems with the
undo tablespace and ORA-1555 "snapshot too old" error because of the
different architecture. Also, Oracle has a secret optimization: it
doesn't wait for commit, if the commit is issued within PL/SQL loop.
Your idea solves the syntactic problem with commits within PLPG/SQL
 loops but it doesn't solve other problems that such programming
causes. Commit within loop is a very bad idea. The best way to resolve
the problems with commit within the loop is to remove the programmer
trying to do that from the project. In my humble opinion, programmers
who do stuff like that should suffer unusual and cruel punishment.

PS:

I am sure, that if Tom Kyte would dare to make a suggestion on this
list, there would be someone who would try to explain "the Postgres
way" to him in a condescending manner. I've seen that before.


Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread gogala . mladen
On Tue, 2022-10-18 at 17:33 -0400, Tom Lane wrote:
> Bryn Llewellyn  writes:
> > x...@thebuild.com wrote:
> > > You can commit in a loop, but not in BEGIN / END block that has
> > > an exception handler: that creates a subtransaction for the
> > > duration of the BEGIN / END.
> 
> > This surprised me when I first started to use PG (after all those
> > years
> > with ORCL).
> 
> Really?  BEGIN with an exception block is a subtransaction because
> it's
> defined to roll back to the database state as of the start of the
> block
> if an exception occurs.  COMMIT in the middle fundamentally conflicts
> with that, I should think.  Does Oracle interpret that differently?
> 
> regards, tom lane
> 
> 

Hi Tom,
Yes, Oracle does interpret that differently. Bryn may correct me if I'm
wrong, but Oracle creates an implicit save point when it encounters
BEGIN. Exception handler doesn't necessarily roll things back. Oracle
behavior is not standard and PgSQL adheres to SQL standard better than
Oracle. However, being as pervasive as it is, Oracle is de facto
 standard.
Also, Oracle has something called "autonomous transaction" which, in
effect, means that a session can have two concurrent transactions open,
which is also non-standard:

https://docs.oracle.com/en/database/oracle/oracle-database/19/lnpls/AUTONOMOUS_TRANSACTION-pragma.html#GUID-AD33D949-081B-4CD3-A240-C29773E908C3

Amazon, lead by Kevin Closson, the guy who has famously designed Oracle
Exadata among other things, even came up with the recipe how to migrate
it to Postgres:

https://aws.amazon.com/blogs/database/migrating-oracle-autonomous-transactions-to-postgresql/

I am a bit skeptical toward that recipe and I usually prefer
programming solutions with opening another thread and sending a
message. BTW, speaking of Kevin, he has also written pgio, which is a
PostgreSQL version of his SLOB package. Kevin is the only retired
Oracle ACE in existence. BTW, Bryn also used to be an Oracle ACE.
Regards


Re: what's inherited

2022-10-18 Thread Laurenz Albe
On Tue, 2022-10-18 at 16:41 -0500, Ted Toth wrote:
> When I create a table that inherits from another table what all is
> inherited i.e. ownership, security policy, ...?

None of that, only the column definitione.

Yours,
Laurenz Albe




Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Laurenz Albe
On Tue, 2022-10-18 at 17:33 -0400, Tom Lane wrote:
> Bryn Llewellyn  writes:
> > x...@thebuild.com wrote:
> > > You can commit in a loop, but not in BEGIN / END block that has an 
> > > exception handler: that creates a subtransaction for the duration of the 
> > > BEGIN / END.
> 
> > This surprised me when I first started to use PG (after all those years
> > with ORCL).
> 
> Really?  BEGIN with an exception block is a subtransaction because it's
> defined to roll back to the database state as of the start of the block
> if an exception occurs.  COMMIT in the middle fundamentally conflicts
> with that, I should think.  Does Oracle interpret that differently?

Looks like Oracle doesn't care much about that:

SQL> CREATE TABLE mytab (id integer CHECK (id > 0));

Table created.

SQL> CREATE PROCEDURE committest IS
  2  BEGIN
  3 INSERT INTO mytab VALUES (42);
  4 COMMIT;
  5 INSERT INTO mytab VALUES (-42);
  6  EXCEPTION
  7 WHEN OTHERS THEN
  8NULL;
  9  END;
 10  /

Procedure created.

SQL> CALL committest();

Call completed.

SQL> SELECT * FROM mytab;

ID
--
42

I looks like Oracle allows you to randomly interfere with its transaction 
handling.
If you run commit and then enter an exception handler, it simply doesn't 
rollback.

Yours,
Laurenz Albe




what's inherited

2022-10-18 Thread Ted Toth
When I create a table that inherits from another table what all is
inherited i.e. ownership, security policy, ...?

Ted




Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Christophe Pettus



> On Oct 18, 2022, at 14:15, Bryn Llewellyn  wrote:
> Could the limitation be lifted by making tractable internal implementation 
> changes? Or is it rooted in profoundly deep features of the 
> architecture—meaning that it could never be lifted?

That is a very good question.  One of the issues (as I understand it) is to be 
able to continue to use the same connection in the event of an error.  Here's 
the scenario:

1. SELECT * FROM my_func();

2. my_func gets an error.  The connection is now in an error state.

3. So, catching the exception doesn't do you much good, because future 
operations will get an error.

This problem is solved by wrapping it in a savepoint, since rolling back to the 
savepoint will undo the error state of the connection.

There might be a way forward, but it's hard to get the proper semantics of an 
exception handler without doing something like that. 



Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Tom Lane
Bryn Llewellyn  writes:
> x...@thebuild.com wrote:
>> You can commit in a loop, but not in BEGIN / END block that has an exception 
>> handler: that creates a subtransaction for the duration of the BEGIN / END.

> This surprised me when I first started to use PG (after all those years
> with ORCL).

Really?  BEGIN with an exception block is a subtransaction because it's
defined to roll back to the database state as of the start of the block
if an exception occurs.  COMMIT in the middle fundamentally conflicts
with that, I should think.  Does Oracle interpret that differently?

regards, tom lane




Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Christophe Pettus



> On Oct 18, 2022, at 14:29, Ravi Krishna  wrote:
> 
> > You can commit in a loop, but not in BEGIN / END block that has an 
> > exception handler:
> > that creates a subtransaction for the duration of the BEGIN / END.
> 
> The reason I have to deal with error exception is that I want to ignore 
> failure on a table and move on to next table. 

Rather than have a loop inside the BEGIN / END, you could put the BEGIN 
EXCEPTION END inside the loop, catch the error, store the important parts of 
the exception in a variable, and then do the COMMIT after the END statement but 
before the next iteration of the loop.  A bit messier, but it gets the job done.



Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Ravi Krishna
> You can commit in a loop, but not in BEGIN / END block that has an exception 
> handler:> that creates a subtransaction for the duration of the BEGIN / END.
The reason I have to deal with error exception is that I want to ignore failure 
on a table and move on to next table. 
I thought I can trick it by moving the part of the code which executes dynamic 
sql and has exception handler in it,to a separate procedure.  This way I can 
keep the main procedure without exception handler.  It failed too withthe same 
error.  So that means this restriction is not at lexical level, but at 
execution level.This is so disappointing.  It seems there is no way I can copy 
each table and commit it individually and also capture error.


Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Bryn Llewellyn
> x...@thebuild.com wrote:
> 
>> s_ravikris...@aol.com wrote:
>> 
>> I am getting error at COMMIT -> cannot commit while a subtransaction is 
>> active...
> 
> You can commit in a loop, but not in BEGIN / END block that has an exception 
> handler: that creates a subtransaction for the duration of the BEGIN / END.

This surprised me when I first started to use PG (after all those years with 
ORCL). There are some use cases where this limitation is a nuisance. For 
example, if you want to implement the famous retry loop (with exponential 
backoff) for an error that is provoked at commit time... well, you have to do 
it in client-side code.

Could the limitation be lifted by making tractable internal implementation 
changes? Or is it rooted in profoundly deep features of the 
architecture—meaning that it could never be lifted?



Re: COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Christophe Pettus



> On Oct 18, 2022, at 13:14, Ravi Krishna  wrote:
> 
> I am getting error at COMMIT -> cannot commit while a subtransaction is 
> active.
> Is commit not possible in a loop

You can commit in a loop, but not in BEGIN / END block that has an exception 
handler: that creates a subtransaction for the duration of the BEGIN / END.



COMMIT IN STORED PROCEDURE WHILE IN A LOOP

2022-10-18 Thread Ravi Krishna
AWS Aurora based on PG 13

I am writing a sproc to copy a schema into another.  Here is the relevant 
portion of the code.
Basically I want to commit after every table is created.  In big schemas with 
hundreds of table I do not want to run entire operation in one transaction.

I am getting error at COMMIT -> cannot commit while a subtransaction is active.
Is commit not possible in a loop


 

BEGIN

  FOR object IN

    SELECT table_name::text FROM information_schema.TABLES WHERE table_schema = 
source_schema

  AND table_type = 'BASE TABLE'

  LOOP


  buffer := dest_schema || '.' || object;

  BEGIN

    sql_stmt := 'CREATE TABLE ' || buffer || ' (LIKE ' || 
source_schema || '.' || object;

    sql_stmt :=  sql_stmt || ' INCLUDING COMMENTS INCLUDING 
IDENTITY INCLUDING CONSTRAINTS INCLUDING DEFAULTS INCLUDING GENERATED INCLUDING 
INDEXES)' ;

    --RAISE NOTICE '%' , sql_stmt ;

    execute sql_stmt ;

    COMMIT;

    sql_stmt := 'INSERT INTO ' || buffer || ' OVERRIDING SYSTEM 
VALUE SELECT * FROM ' || source_schema || '.' || object ;

    --RAISE NOTICE '%' , sql_stmt ;

    execute sql_stmt ;

    COMMIT;

    EXCEPTION

    WHEN OTHERS THEN

    GET STACKED DIAGNOSTICS text_var1 = MESSAGE_TEXT,

    
text_var2 = PG_EXCEPTION_DETAIL,

    
text_var3 = PG_EXCEPTION_HINT;

 print_msg := 'ERROR:->' || text_var1 || '|' || text_var2 || '|' || 
text_var3 ;

 RAISE NOTICE '%' , print_msg ;

    END ;

  END LOOP;

END;





Re: byte-size of column values

2022-10-18 Thread Tom Lane
Dominique Devienne  writes:
> Hi. I'm surprised by the result for bit(3) and char, when calling
> pg_column_size().

> Why 6, instead of 1? The doc does mention 5-8 bytes overhead, but I
> expected those for varying bit, not fixed-sized bit typed values. How
> come?

Your expectation is incorrect.  Postgres always treats these types
as variable-length, whether or not the column has a length constraint.
Thus, there's always a header to store the actual length.  That can
be either 1 or 4 bytes (I think the doc you are looking at might be
a little out of date on that point).

Because of the popularity of variable-width character encodings,
a column declared as N characters wide isn't necessarily a fixed
number of bytes wide, making it a lot less useful than you might
think to have optimizations for fixed-width storage.  Between that
and the fact that most Postgres developers regard CHAR(N) as an
obsolete hangover from the days of punched cards, no such
optimizations have been attempted.

regards, tom lane




Re: byte-size of column values

2022-10-18 Thread David G. Johnston
On Tue, Oct 18, 2022 at 8:53 AM Dominique Devienne 
wrote:

> Hi. I'm surprised by the result for bit(3) and char, when calling
> pg_column_size().
>
> Why 6, instead of 1? The doc does mention 5-8 bytes overhead, but I
> expected those for varying bit, not fixed-sized bit typed values. How
> come?
>
>
The base type is what matters, if the length of the actual type is a
parameter (the (n) part) the underlying type must be variable, and thus has
a component that says how long the actually stored value is.


> How does one store as compactedly as possible several small enums, on
> millions of rows?
>

int2
David J.

p.s., pretend char doesn't even exist.


byte-size of column values

2022-10-18 Thread Dominique Devienne
Hi. I'm surprised by the result for bit(3) and char, when calling
pg_column_size().

Why 6, instead of 1? The doc does mention 5-8 bytes overhead, but I
expected those for varying bit, not fixed-sized bit typed values. How
come?

Similarly, why 2 for char? Is it linked to Unicode?
1 byte for the varying UTF-8 encoded length, then the (potentially)
multi-byte encoding?
(the very bit pattern of UTF-8 allows to infer the encoded length, so
storing the length explicitly is theoretically not even necessary)

Similarly, enums are always 4 bytes I read, despite rarely exceeding
cardinalities beyond a single byte can store.

How does one store as compactedly as possible several small enums, on
millions of rows?

And is the minimum column size always 2?

I'm sure many we call out "premature optimization", but isn't using 32
bits instead of 2, 3 (or 8, to round to a byte) wasteful, in disk
space, thus then ultimately energy? (OK, that last one is pushing it
:) ).

I'm sure there are reasons for the above. And I guess I'm curious
about them. Thanks, --DD

ddevienne=> create table foo (b3 bit(3), i2 int2, i4 int4, i8 int8, c char);
CREATE TABLE
ddevienne=> insert into foo values (b'101', 1002, 1004, 1008, 'C');
INSERT 0 1
ddevienne=> select pg_column_size(b3), pg_column_size(i2),
pg_column_size(i4), pg_column_size(i8), pg_column_size(c) from foo;
 pg_column_size | pg_column_size | pg_column_size | pg_column_size |
pg_column_size
++++
  6 |  2 |  4 |  8 |
   2
(1 row)