Обсуждение: 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
Вложения
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!"
Вложения
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