Hi hackers,

I found a code validation bug in master branch.

Now, ecpg does not support 'EXEC SQL COPY ... FROM STDIN ... ;' and
code for warning it exits.

https://github.com/postgres/postgres/blob/7b27f5fd36cb3270e8ac25aefd73b552663d1392/src/interfaces/ecpg/preproc/ecpg.addons#L242-L245
---
ECPG: addon CopyStmt COPY opt_binary qualified_name opt_column_list
copy_from opt_program copy_file_name copy_delimiter opt_with
copy_options where_clause
if (strcmp(@6, "from") == 0 &&
(strcmp(@7, "stdin") == 0 || strcmp(@7, "stdout") == 0))
mmerror(PARSE_ERROR, ET_WARNING, "COPY FROM STDIN is not implemented");
---

But it is not working.
ecpg command fails to notice though code like above exits on pgc code.


# COPY ... FROM STDIN code
ryo@DESKTOP-IOASPN6:~/work/postgres/src$ cat copy_from_should_be_warned.pgc
#include <stdio.h>
#include <stdlib.h>

EXEC SQL WHENEVER SQLERROR CALL die();
EXEC SQL WHENEVER NOT FOUND DO BREAK;

void
die(void)
{
    fprintf(stderr, "%s\n", sqlca.sqlerrm.sqlerrmc);
    exit(1);
}

int
main(void)
{
    EXEC SQL BEGIN DECLARE SECTION;
    const char *target = "postgres@localhost:5432";
    const char *user = "ryo";
    const char *passwd = "";
    EXEC SQL END DECLARE SECTION;

    EXEC SQL CONNECT TO :target USER :user USING :passwd;
    EXEC SQL COPY name_age_list FROM STDIN;
    EXEC SQL COMMIT;
    EXEC SQL DISCONNECT ALL;

    return 0;
}
-----

I executed ecpg command for above code.

ryo@DESKTOP-IOASPN6:~/work/postgres/src$ ../master/bin/ecpg
copy_from_should_be_warned.pgc
ryo@DESKTOP-IOASPN6:~/work/postgres/src$

But there was no warning and generaged c source.

So, I wrote patch.
the patch changes @6 on code above to @5.
Checked variable was wrong.

After apply patch, warning is shown.
(c source is generated as before)

ryo@DESKTOP-IOASPN6:~/work/postgres/src$ ../master/bin/ecpg
copy_from_should_be_warned.pgc
copy_from_should_be_warned.pgc:24: WARNING: COPY FROM STDIN is not implemented
ryo@DESKTOP-IOASPN6:~/work/postgres/src$

--
Best regards,
Ryo Kanbayashi
kanbayashi....@gmail.com
https://github.com/ryogrid
ryo@DESKTOP-IOASPN6:~/work/postgres$ git log
commit 7b27f5fd36cb3270e8ac25aefd73b552663d1392 (HEAD -> master, origin/master, 
origin/HEAD)
Author: Peter Eisentraut <pe...@eisentraut.org>
Date:   Wed Jan 8 09:20:01 2025 +0100

    plpgsql: pure parser and reentrant scanner

ryo@DESKTOP-IOASPN6:~/work/postgres$ uname -a
Linux DESKTOP-IOASPN6 5.15.167.4-microsoft-standard-WSL2 #1 SMP Tue Nov 5 
00:21:55 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

ryo@DESKTOP-IOASPN6:~/work/postgres$ gcc --version
gcc (Ubuntu 10.5.0-1ubuntu1~20.04) 10.5.0
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ryo@DESKTOP-IOASPN6:~/work/postgres$ bison --version
bison (GNU Bison) 3.5.1
Written by Robert Corbett and Richard Stallman.                                 
                                                                                
                                                      Copyright (C) 2020 Free 
Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

ryo@DESKTOP-IOASPN6:~/work/postgres$ lex --version
flex 2.6.4

# local postgres install dir
ryo@DESKTOP-IOASPN6:~/work/postgres$ ls master/
bin  data  include  lib  share

# COPY ... FROM STDIN code
ryo@DESKTOP-IOASPN6:~/work/postgres/src$ cat copy_from_should_be_warned.pgc
#include <stdio.h>
#include <stdlib.h>

EXEC SQL WHENEVER SQLERROR CALL die();
EXEC SQL WHENEVER NOT FOUND DO BREAK;

void
die(void)
{
    fprintf(stderr, "%s\n", sqlca.sqlerrm.sqlerrmc);
    exit(1);
}

int
main(void)
{
    EXEC SQL BEGIN DECLARE SECTION;
    const char *target = "postgres@localhost:5432";
    const char *user = "ryo";
    const char *passwd = "";
    EXEC SQL END DECLARE SECTION;

    EXEC SQL CONNECT TO :target USER :user USING :passwd;
    EXEC SQL COPY name_age_list FROM STDIN;
    EXEC SQL COMMIT;
    EXEC SQL DISCONNECT ALL;

    return 0;
}


# before apply patch -> No Warning
ryo@DESKTOP-IOASPN6:~/work/postgres/src$ ../master/bin/ecpg 
copy_from_should_be_warned.pgc
ryo@DESKTOP-IOASPN6:~/work/postgres/src$

# after apply patch -> Warning is shown
ryo@DESKTOP-IOASPN6:~/work/postgres/src$ ../master/bin/ecpg 
copy_from_should_be_warned.pgc
copy_from_should_be_warned.pgc:24: WARNING: COPY FROM STDIN is not implemented
ryo@DESKTOP-IOASPN6:~/work/postgres/src$

# COPY ... FROM filename code
ryo@DESKTOP-IOASPN6:~/work/postgres/src$ cat copy_from_ok.pgc
#include <stdio.h>
#include <stdlib.h>

EXEC SQL WHENEVER SQLERROR CALL die();
EXEC SQL WHENEVER NOT FOUND DO BREAK;

void
die(void)
{
    fprintf(stderr, "%s\n", sqlca.sqlerrm.sqlerrmc);
    exit(1);
}

int
main(void)
{
    EXEC SQL BEGIN DECLARE SECTION;
    const char *target = "postgres@localhost:5432";
    const char *user = "ryo";
    const char *passwd = "";
    EXEC SQL END DECLARE SECTION;

    EXEC SQL CONNECT TO :target USER :user USING :passwd;
    EXEC SQL COPY name_age_list FROM 
'/home/ryo/work/postgres/src/test_ecpg.out';
    EXEC SQL COMMIT;
    EXEC SQL DISCONNECT ALL;

    return 0;
}

# after apply patch -> No Warning (no difference before applying patch)
ryo@DESKTOP-IOASPN6:~/work/postgres/src$ ../master/bin/ecpg copy_from_ok.pgc
ryo@DESKTOP-IOASPN6:~/work/postgres/src$

# applying patch -> regression tests are passed
ryo@DESKTOP-IOASPN6:~/work/postgres/src/interfaces/ecpg$ make check
PATH="/home/ryo/work/postgres/tmp_install/usr/local/bin:/home/ryo/work/postgres/src/interfaces/ecpg/test:$PATH"
 LD_LIBRARY_PATH="/home/ryo/work/postgres/tmp_install/usr/local/lib" 
INITDB_TEMPLATE='/home/ryo/work/postgres'/tmp_install/initdb-template  
./pg_regress --expecteddir=. --dbname=ecpg1_regression,ecpg2_regression 
--create-role=regress_ecpg_user1,regress_ecpg_user2  
--temp-instance=./tmp_check  --bindir=    --schedule=./ecpg_schedule 
sql/twophase
# initializing database system by copying initdb template
# using temp instance on port 65312 with PID 1593657
ok 1         - compat_informix/dec_test                    3 ms
ok 2         - compat_informix/charfuncs                   1 ms
ok 3         - compat_informix/rfmtdate                    1 ms
ok 4         - compat_informix/rfmtlong                    1 ms
ok 5         - compat_informix/rnull                      16 ms
ok 6         - compat_informix/sqlda                      16 ms
ok 7         - compat_informix/describe                   14 ms
ok 8         - compat_informix/test_informix              16 ms
ok 9         - compat_informix/test_informix2              8 ms
ok 10        - compat_informix/intoasc                     1 ms
ok 11        - compat_oracle/char_array                   10 ms
ok 12        - connect/test2                              13 ms
ok 13        - connect/test3                               8 ms
ok 14        - connect/test4                               3 ms
ok 15        - connect/test5                              40 ms
ok 16        - pgtypeslib/dt_test                          6 ms
ok 17        - pgtypeslib/dt_test2                         1 ms
ok 18        - pgtypeslib/num_test                         7 ms
ok 19        - pgtypeslib/num_test2                        3 ms
ok 20        - pgtypeslib/nan_test                        19 ms
ok 21        - preproc/array_of_struct                     7 ms
ok 22        - preproc/pointer_to_struct                   8 ms
ok 23        - preproc/autoprep                           20 ms
ok 24        - preproc/comment                             3 ms
ok 25        - preproc/cursor                             30 ms
ok 26        - preproc/define                              8 ms
ok 27        - preproc/init                                1 ms
ok 28        - preproc/strings                             6 ms
ok 29        - preproc/type                                6 ms
ok 30        - preproc/variable                           10 ms
ok 31        - preproc/outofscope                         14 ms
ok 32        - preproc/whenever                           12 ms
ok 33        - preproc/whenever_do_continue               14 ms
ok 34        - sql/array                                  16 ms
ok 35        - sql/binary                                  8 ms
ok 36        - sql/bytea                                  15 ms
ok 37        - sql/code100                                13 ms
ok 38        - sql/copystdout                              7 ms
ok 39        - sql/createtableas                           9 ms
ok 40        - sql/define                                  8 ms
ok 41        - sql/desc                                   11 ms
ok 42        - sql/sqlda                                  21 ms
ok 43        - sql/describe                               26 ms
ok 44        - sql/dynalloc                                9 ms
ok 45        - sql/dynalloc2                               9 ms
ok 46        - sql/dyntest                                23 ms
ok 47        - sql/execute                                10 ms
ok 48        - sql/fetch                                  10 ms
ok 49        - sql/func                                   14 ms
ok 50        - sql/indicators                             27 ms
ok 51        - sql/oldexec                                11 ms
ok 52        - sql/quote                                  11 ms
ok 53        - sql/show                                    5 ms
ok 54        - sql/sqljson                                11 ms
ok 55        - sql/sqljson_jsontable                       4 ms
ok 56        - sql/insupd                                  8 ms
ok 57        - sql/parser                                 10 ms
ok 58        - sql/prepareas                              20 ms
ok 59        - sql/declare                                19 ms
ok 60        - thread/thread                              49 ms
ok 61        - thread/thread_implicit                     58 ms
ok 62        - thread/prep                               121 ms
ok 63        - thread/alloc                              101 ms
ok 64        - thread/descriptor                          37 ms
ok 65        - sql/twophase                                8 ms
1..65
# All 65 tests passed.
make[1]: Leaving directory '/home/ryo/work/postgres/src/interfaces/ecpg/test'

Attachment: copy_from_ok.pgc
Description: Binary data

Attachment: copy_from_should_be_warned.pgc
Description: Binary data

Attachment: copy_from_stdin_no_warning.patch
Description: Binary data

Reply via email to