ECPG bug: "unterminated quoted identifier"

Started by 1250kvover 5 years ago9 messagesbugs
Jump to latest
#11250kv
1250kv@gmail.com

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

#2David G. Johnston
david.g.johnston@gmail.com
In reply to: 1250kv (#1)
Re: ECPG bug: "unterminated quoted identifier"

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.

#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: 1250kv (#1)
Re: ECPG bug: "unterminated quoted identifier"

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

#41250kv
1250kv@gmail.com
In reply to: David G. Johnston (#2)
Re: ECPG bug: "unterminated quoted identifier"

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:

Show quoted text

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.

#51250kv
1250kv@gmail.com
In reply to: Tom Lane (#3)
Re: ECPG bug: "unterminated quoted identifier"

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:

Show quoted text

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

#6Tom Lane
tgl@sss.pgh.pa.us
In reply to: 1250kv (#5)
Re: ECPG bug: "unterminated quoted identifier"

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]/messages/by-id/673825.1603223178@sss.pgh.pa.us, 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]: /messages/by-id/673825.1603223178@sss.pgh.pa.us

#71250kv
1250kv@gmail.com
In reply to: Tom Lane (#6)
Re: ECPG bug: "unterminated quoted identifier"

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:

Show quoted text

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]
/messages/by-id/673825.1603223178@sss.pgh.pa.us

#8Tom Lane
tgl@sss.pgh.pa.us
In reply to: 1250kv (#7)
Re: ECPG bug: "unterminated quoted identifier"

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

#91250kv
1250kv@gmail.com
In reply to: Tom Lane (#8)
Re: ECPG bug: "unterminated quoted identifier"

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:
/messages/by-id/CA+4qtLett6CMxojrwn+yQq7qmN8SMOM3eZQ8yQG9D5tCuF-vKw@mail.gmail.com

On Wed, Oct 21, 2020 at 4:12 AM Tom Lane <tgl@sss.pgh.pa.us> wrote:

Show quoted text

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