Обсуждение: ECPG bug: "unterminated quoted identifier"

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

ECPG bug: "unterminated quoted identifier"

От
1250kv
Дата:
Hello
I have code:

void main()
{
  char *foo = "aaa\"bbb";
  EXEC SQL char *bar = "aaa\"bbb";
}

ecpg --version
ecpg (PostgreSQL) 13.0 (Ubuntu 13.0-1.pgdg20.04+1)

ecpg sample.pgc -o 1.c
sample .pgc:10: ERROR: unterminated quoted identifier

Re: ECPG bug: "unterminated quoted identifier"

От
"David G. Johnston"
Дата:
On Tue, Oct 20, 2020 at 9:47 AM 1250kv <1250kv@gmail.com> wrote:
Hello
I have code:

void main()
{
  char *foo = "aaa\"bbb";
  EXEC SQL char *bar = "aaa\"bbb";
}

ecpg --version
ecpg (PostgreSQL) 13.0 (Ubuntu 13.0-1.pgdg20.04+1)

ecpg sample.pgc -o 1.c
sample .pgc:10: ERROR: unterminated quoted identifier

General usage questions regarding PostgreSQL and ECPG should be sent to the -general list.

What are you expecting to be the result of that?

David J.

Re: ECPG bug: "unterminated quoted identifier"

От
Tom Lane
Дата:
1250kv <1250kv@gmail.com> writes:
> void main()
> {
>   char *foo = "aaa\"bbb";
>   EXEC SQL char *bar = "aaa\"bbb";
> }

> ecpg sample.pgc -o 1.c
> sample .pgc:10: ERROR: unterminated quoted identifier

I don't really see a bug there.  While I'm not an ecpg expert by
any means, I'd expect the EXEC SQL section to parse quoted strings
according to SQL rules not C rules.  And under SQL, that's not
what you do to write a valid quoted identifier.

            regards, tom lane



Re: ECPG bug: "unterminated quoted identifier"

От
1250kv
Дата:
I have expected that host-variable bar the variable will be assigned the value 'aaa"bbb'
similarly if this value were obtained from a query:

#include <stdio.h>
int main()
{
    EXEC SQL char *foo;
    foo = (char *) malloc(5);

    EXEC SQL SELECT 'aaa"bbb' INTO :foo;

    printf("%s\n", foo);
    return 0;
}

Result:
aaa"bbb  

On Tue, Oct 20, 2020 at 7:57 PM David G. Johnston <david.g.johnston@gmail.com> wrote:
On Tue, Oct 20, 2020 at 9:47 AM 1250kv <1250kv@gmail.com> wrote:
Hello
I have code:

void main()
{
  char *foo = "aaa\"bbb";
  EXEC SQL char *bar = "aaa\"bbb";
}

ecpg --version
ecpg (PostgreSQL) 13.0 (Ubuntu 13.0-1.pgdg20.04+1)

ecpg sample.pgc -o 1.c
sample .pgc:10: ERROR: unterminated quoted identifier

General usage questions regarding PostgreSQL and ECPG should be sent to the -general list.

What are you expecting to be the result of that?

David J.

Re: ECPG bug: "unterminated quoted identifier"

От
1250kv
Дата:
When I assign the value "aaa\"bbb" to the non-host variable foo and then assign the value of foo to the host-variable bar there no error:

int main()
{
  char *foo = "aaa\"bbb";
  printf("%s\n", foo);
 
  EXEC SQL char *bar = foo;
  printf("%s\n", bar);

  return 0;
}

Result:
aaa"bbb
aaa"bbb

On Tue, Oct 20, 2020 at 8:23 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
1250kv <1250kv@gmail.com> writes:
> void main()
> {
>   char *foo = "aaa\"bbb";
>   EXEC SQL char *bar = "aaa\"bbb";
> }

> ecpg sample.pgc -o 1.c
> sample .pgc:10: ERROR: unterminated quoted identifier

I don't really see a bug there.  While I'm not an ecpg expert by
any means, I'd expect the EXEC SQL section to parse quoted strings
according to SQL rules not C rules.  And under SQL, that's not
what you do to write a valid quoted identifier.

                        regards, tom lane

Re: ECPG bug: "unterminated quoted identifier"

От
Tom Lane
Дата:
1250kv <1250kv@gmail.com> writes:
>   EXEC SQL char *bar = foo;

I think it's pure luck that that doesn't throw an error.
You should not be using the EXEC SQL prefix for something
that isn't a SQL command.

Anyway, the problem you're hitting here is that as soon as you
say EXEC SQL, the syntax rules for quoted strings change.
This is not well documented, and I think it's got some bugs
in itself [1], but "EXEC SQL char *bar = "aaa\"bbb";" is just
wrong.  You can't use C literal syntax inside a SQL code
segment, whether or not the command would work otherwise.

            regards, tom lane

[1] https://www.postgresql.org/message-id/673825.1603223178%40sss.pgh.pa.us



Re: ECPG bug: "unterminated quoted identifier"

От
1250kv
Дата:
>>You can't use C literal syntax inside a SQL code
>>segment, whether or not the command would work otherwise.
I have come across cases in which there is a need to use nested double quotes inside C string literal.
This is necessary for correct access to database objects whose names contain uppercase characters.

CREATE FUNCTION "My_Func"(IN p_i INTEGER)
RETURNS INTEGER
AS
$BODY$
BEGIN
  RETURN p_i + 1;
END;
$BODY$
LANGUAGE  plpgsql;

int main()
{
  EXEC SQL int i;

  EXEC SQL EXECUTE IMMEDIATE "DO $$\n\
  BEGIN\n\
    :i := embeddedc.\"My_Func\"(:i);\n\
  END\n\
  $$";

  return 0;
}

Result: ERROR: syntax error at or near "My_Func"

I have discovered another workaround (in addition to what I showed earlier): \" could be replaced with \x22.

However, I believe that this is a bug in the ECPG lexical analyzer.

On Tue, Oct 20, 2020 at 11:10 PM Tom Lane <tgl@sss.pgh.pa.us> wrote:
1250kv <1250kv@gmail.com> writes:
>   EXEC SQL char *bar = foo;

I think it's pure luck that that doesn't throw an error.
You should not be using the EXEC SQL prefix for something
that isn't a SQL command.

Anyway, the problem you're hitting here is that as soon as you
say EXEC SQL, the syntax rules for quoted strings change.
This is not well documented, and I think it's got some bugs
in itself [1], but "EXEC SQL char *bar = "aaa\"bbb";" is just
wrong.  You can't use C literal syntax inside a SQL code
segment, whether or not the command would work otherwise.

                        regards, tom lane

[1] https://www.postgresql.org/message-id/673825.1603223178%40sss.pgh.pa.us

Re: ECPG bug: "unterminated quoted identifier"

От
Tom Lane
Дата:
1250kv <1250kv@gmail.com> writes:
> I have come across cases in which there is a need to use nested double
> quotes inside C string literal.

>   EXEC SQL EXECUTE IMMEDIATE "DO $$\n\
>   BEGIN\n\
>     :i := embeddedc.\"My_Func\"(:i);\n\
>   END\n\
>   $$";

I'd be interested to understand why you feel the need to write that,
and not just

 EXEC SQL DO $$
  BEGIN
    :i := embeddedc."My_Func"(:i);
  END
  $$;

AFAICS, EXECUTE IMMEDIATE with a constant string isn't really useful
for anything.  (Note that if you mean those :i's as references to
your ECPG variable, I don't think that works in either syntax, since
it's inside a literal.)

            regards, tom lane



Re: ECPG bug: "unterminated quoted identifier"

От
1250kv
Дата:
> EXEC SQL DO
Thanks, it works!

> Note that if you mean those :i's as references to
> your ECPG variable, I don't think that works in either syntax, since
> it's inside a literal.)
Yes, you are right! I had to use a temporary table as a buffer in order to refer to host variable values in an anonymous block.

Thank you for helping me!

However, there is one another case when I have to use a C string literal with nested double quotes inside Embedded SQL.

I have a stored procedure with case sensitive name and INOUT parameter:

CREATE OR REPLACE PROCEDURE embeddedc."My_Proc_outparam"(INOUT p TEXT)
AS
$BODY$
BEGIN
    p := '222';
END;
$BODY$
LANGUAGE plpgsql;

When I call it from DB there is no issue:

DO
$BODY$
DECLARE
  t TEXT := 'qqq';
BEGIN
  CALL embeddedc."My_Proc_outparam"(t);
END;
$BODY$

But when I try to call this procedure from embedded SQL...
int main()
{
  EXEC SQL char foo[9];

  EXEC SQL CALL embeddedc."My_Proc_outparam"(:foo);

  return 0;
}
...an error occurs: "SQL error: too few arguments on line ..."

As far as I can see the Embedded SQL CALL statement does not support procedures with INOUT parameters.

To get around this limitation, I decided to use PREPARE .. FROM + EXECUTE.

But I ran into the situation that I described in here: https://www.postgresql.org/message-id/flat/CA%2B4qtLett6CMxojrwn%2ByQq7qmN8SMOM3eZQ8yQG9D5tCuF-vKw%40mail.gmail.com

On Wed, Oct 21, 2020 at 4:12 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:
1250kv <1250kv@gmail.com> writes:
> I have come across cases in which there is a need to use nested double
> quotes inside C string literal.

>   EXEC SQL EXECUTE IMMEDIATE "DO $$\n\
>   BEGIN\n\
>     :i := embeddedc.\"My_Func\"(:i);\n\
>   END\n\
>   $$";

I'd be interested to understand why you feel the need to write that,
and not just

 EXEC SQL DO $$
  BEGIN
    :i := embeddedc."My_Func"(:i);
  END
  $$;

AFAICS, EXECUTE IMMEDIATE with a constant string isn't really useful
for anything.  (Note that if you mean those :i's as references to
your ECPG variable, I don't think that works in either syntax, since
it's inside a literal.)

                        regards, tom lane