Thread: type SERIAL in C host-struct
Hello, We're struggling with the following problem (here show in a simplified case). We have in a PG 11.4 database a table with two columns: SERIAL, VARCHAR(11). In the ESQL/C pgm the code is: EXEC SQL BEGIN DECLARE SECTION; ... struct { int ser; char name [11]; } host_struct; EXEC SQL END DECLARE SECTION; an INSERT with strcpy(host_struct.name, "Sigrid"); host_struct.ser = 0; EXEC SQL INSERT INTO lina VALUES (:host_struct); works but, sets the SERIAL column to 0; an INSERT with EXEC SQL INSERT INTO lina VALUES (DEFAULT, :host_struct.name); works correctly and increments the SERIAL on every INSERT: printf "select * from lina WHERE name = 'Sigrid';\n" | psql -Usisis -d newsisis lid | name -----+---------------------- 28 | Sigrid 29 | Sigrid 0 | Sigrid <*********** this was with host_struct.ser = 0; 30 | Sigrid 31 | Sigrid How the value for host_struct.ser must be given, as we do not want to name all the struct members in the INSERT statement(s), the real structs have plenty much columns, some ~30. Thanks matttias -- Matthias Apitz, ✉ guru@unixarea.de, http://www.unixarea.de/ +49-176-38902045 Public GnuPG key: http://www.unixarea.de/key.pub May, 9: Спаси́бо освободители! Thank you very much, Russian liberators!
El día jueves, noviembre 07, 2019 a las 12:39:39p. m. +0100, Matthias Apitz escribió: > > Hello, > > We're struggling with the following problem (here show in a simplified > case). > > We have in a PG 11.4 database a table with two columns: SERIAL, VARCHAR(11). > > In the ESQL/C pgm the code is: > > EXEC SQL BEGIN DECLARE SECTION; > ... > struct { > int ser; > char name [11]; > } host_struct; > EXEC SQL END DECLARE SECTION; > > an INSERT with > > strcpy(host_struct.name, "Sigrid"); > host_struct.ser = 0; > > EXEC SQL INSERT INTO lina VALUES (:host_struct); > > works but, sets the SERIAL column to 0; > > an INSERT with > > EXEC SQL INSERT INTO lina VALUES (DEFAULT, :host_struct.name); > > works correctly and increments the SERIAL on every INSERT: At the end of the day we came up with the following solution: strcpy(host_struct.name, "Sigrid"); EXEC SQL select nextval('lina_lid_seq') into :host_struct.ser; EXEC SQL INSERT INTO lina VALUES ( :host_struct ); which seems to work fine. Any comments about side effects? The layout of the table 'lina' is ( serial lid, varchar name ) Thanks, matthias -- Matthias Apitz, ✉ guru@unixarea.de, http://www.unixarea.de/ +49-176-38902045 Public GnuPG key: http://www.unixarea.de/key.pub "Glaube wenig, hinterfrage alles, denke selbst: Wie man Manipulationen durchschaut" "Believe little, scrutinise all, think by your own: How see through manipulations" ISBN-10: 386489218X
Attachment
On 2019-11-07 20:14:47 +0100, Matthias Apitz wrote: > At the end of the day we came up with the following solution: > > strcpy(host_struct.name, "Sigrid"); > EXEC SQL select nextval('lina_lid_seq') into :host_struct.ser; > > EXEC SQL INSERT INTO lina VALUES ( :host_struct ); > > which seems to work fine. Any comments about side effects? You are performing two queries instead of one, so you have to wait for one extra round trip. Not a problem if client and server are on the same network or you insert a few host_structs per second. May be a problem if client and server are in different datacenters and you want to do hundreds of inserts per second. hp -- _ | Peter J. Holzer | Story must make more sense than reality. |_|_) | | | | | hjp@hjp.at | -- Charles Stross, "Creative writing __/ | http://www.hjp.at/ | challenge!"
Attachment
El día sábado, noviembre 09, 2019 a las 04:31:53p. m. +0100, Peter J. Holzer escribió: > On 2019-11-07 20:14:47 +0100, Matthias Apitz wrote: > > At the end of the day we came up with the following solution: > > > > strcpy(host_struct.name, "Sigrid"); > > EXEC SQL select nextval('lina_lid_seq') into :host_struct.ser; > > > > EXEC SQL INSERT INTO lina VALUES ( :host_struct ); > > > > which seems to work fine. Any comments about side effects? > > You are performing two queries instead of one, so you have to wait for > one extra round trip. Not a problem if client and server are on the same > network or you insert a few host_structs per second. May be a problem if > client and server are in different datacenters and you want to do > hundreds of inserts per second. Thanks for the feedback. Client and server run both on the same Linux host. I found also the debug log of ESQL/C i.e. how to enable it with ECPGdebug(int on, FILE *stream); The resulting log is really fine for debugging our code: [26301]: ECPGdebug: set to 1 [26301]: ECPGconnect: opening database newsisis on localhost port 5432 for user sisis [26301]: prepare_common on line 49: name s_statename; query: "SELECT myint, mychar, mydate, myvchar, myblob FROM mytypes;" [26301]: ecpg_execute on line 52: query: declare c_statename cursor for SELECT myint, mychar, mydate, myvchar, myblob FROMmytypes;; with 0 parameter(s) on connection newsisis [26301]: ecpg_execute on line 52: using PQexec [26301]: ecpg_process_output on line 52: OK: DECLARE CURSOR [26301]: ecpg_execute on line 60: query: fetch in c_statename; with 0 parameter(s) on connection newsisis [26301]: ecpg_execute on line 60: using PQexec [26301]: ecpg_process_output on line 60: correctly got 1 tuples with 5 fields [26301]: ecpg_get_data on line 60: RESULT: 1 offset: 4; array: no [26301]: ecpg_get_data on line 60: RESULT: char offset: 8; array: no [26301]: ecpg_get_data on line 60: RESULT: 08.05.1945 offset: 8; array: no [26301]: ecpg_get_data on line 60: RESULT: освобождение offset: 81; array: no ... What is missing are timestamps in enough precision. I will add this to the code in postgresql-11.4/src/interfaces/ecpg/ecpglib/misc.c where the implementation of ecpg_log() is. Thanks matthias -- Matthias Apitz, ✉ guru@unixarea.de, http://www.unixarea.de/ +49-176-38902045 Public GnuPG key: http://www.unixarea.de/key.pub "Glaube wenig, hinterfrage alles, denke selbst: Wie man Manipulationen durchschaut" "Believe little, scrutinise all, think by your own: How see through manipulations" ISBN-10: 386489218X
El día sábado, noviembre 09, 2019 a las 07:45:31p. m. +0100, Matthias Apitz escribió: > Thanks for the feedback. Client and server run both on the same Linux > host. I found also the debug log of ESQL/C i.e. how to enable it with > > ECPGdebug(int on, FILE *stream); > > The resulting log is really fine for debugging our code: > > ... I added time stamps to the logging as: /tmp/ecpg.log: ... [18328] [12.11.2019 18:38:44:637]: ecpg_execute on line 120: query: insert into mytypes values ( $1 , $2 , $3 , $4 ,$5 ); with 5 parameter(s) on connection newsisis [18328] [12.11.2019 18:38:46:881]: ecpg_execute on line 120: using PQexecParams [18328] [12.11.2019 18:38:46:881]: ecpg_free_params on line 120: parameter 1 = 99 [18328] [12.11.2019 18:38:46:881]: ecpg_free_params on line 120: parameter 2 = [18328] [12.11.2019 18:38:46:881]: ecpg_free_params on line 120: parameter 3 = 2000-01-01 [18328] [12.11.2019 18:38:46:881]: ecpg_free_params on line 120: parameter 4 = [18328] [12.11.2019 18:38:46:881]: ecpg_free_params on line 120: parameter 5 = \x6c696e6520.... .... [18328] [12.11.2019 18:38:47:084]: ecpg_process_output on line 120: OK: INSERT 0 1 [18328] [12.11.2019 18:38:47:084]: ECPGtrans on line 126: action "commit"; connection "newsisis" [18328] [12.11.2019 18:38:47:260]: deallocate_one on line 0: name s_statename [18328] [12.11.2019 18:38:47:263]: ecpg_finish: connection newsisis closed The above shows an INSERT into a 'bytea' column of ~36 MByte (yes we have such large XML data for billing/accounting processes in the database). It takes ~0.2 sec to insert such a monster row. On INSERT/UPDATE the column data (XML) comes down from the application layer as a 'char *' pointer. I know with strlen(src) how long it is, I double its length and add 3 (for the "\x" in front and the '\0' at the end) and malloc the space for the host variable for INSERT/UPDATE and translate the octets to hex representation. When FETCH-ing such a column I do not know the resulting length of the bytea data for doing a malloc(). I could do before any FETCH a SELECT octet_length(myblob) FROM mytypes; but I do not know how expensive this would be. Any other idea to predict the needed space for the host variable on FETCH? matthias -- Matthias Apitz, ✉ guru@unixarea.de, http://www.unixarea.de/ +49-176-38902045 Public GnuPG key: http://www.unixarea.de/key.pub "Glaube wenig, hinterfrage alles, denke selbst: Wie man Manipulationen durchschaut" "Believe little, scrutinise all, think by your own: How see through manipulations" ISBN-10: 386489218X