diff --git a/src/interfaces/ecpg/ChangeLog b/src/interfaces/ecpg/ChangeLog index c7e65abb3f..5206ec1f6a 100644 --- a/src/interfaces/ecpg/ChangeLog +++ b/src/interfaces/ecpg/ChangeLog @@ -2131,5 +2131,10 @@ Tu 29. Aug 14:21:31 CEST 2006 - Fixed parser and library to allow empty database names. - Streamlined connection name parsing. + +Su 3. Sep 14:21:29 CEST 2006 + + - Synced parser. + - Added another regression test and fixed tcp test. - Set ecpg library version to 5.2. - Set ecpg version to 4.2.1. diff --git a/src/interfaces/ecpg/preproc/keywords.c b/src/interfaces/ecpg/preproc/keywords.c index 3fd8d6d236..34060a088b 100644 --- a/src/interfaces/ecpg/preproc/keywords.c +++ b/src/interfaces/ecpg/preproc/keywords.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.75 2006/08/18 15:59:35 meskes Exp $ + * $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.76 2006/09/03 12:24:07 meskes Exp $ * *------------------------------------------------------------------------- */ @@ -81,6 +81,7 @@ static ScanKeyword ScanKeywords[] = { {"comment", COMMENT}, {"commit", COMMIT}, {"committed", COMMITTED}, + {"concurrently", CONCURRENTLY}, {"connection", CONNECTION}, {"constraint", CONSTRAINT}, {"constraints", CONSTRAINTS}, diff --git a/src/interfaces/ecpg/preproc/preproc.y b/src/interfaces/ecpg/preproc/preproc.y index 3bdd5d9912..9d4c611e00 100644 --- a/src/interfaces/ecpg/preproc/preproc.y +++ b/src/interfaces/ecpg/preproc/preproc.y @@ -1,4 +1,4 @@ -/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.334 2006/08/29 12:24:51 meskes Exp $ */ +/* $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/preproc.y,v 1.335 2006/09/03 12:24:07 meskes Exp $ */ /* Copyright comment */ %{ @@ -360,7 +360,7 @@ add_additional_variables(char *name, bool insert) CACHE CALLED CASCADE CASCADED CASE CAST CHAIN CHAR_P CHARACTER CHARACTERISTICS CHECK CHECKPOINT CLASS CLOSE CLUSTER COALESCE COLLATE COLUMN COMMENT COMMIT - COMMITTED CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB + COMMITTED CONCURRENTLY CONNECTION CONSTRAINT CONSTRAINTS CONVERSION_P CONVERT COPY CREATE CREATEDB CREATEROLE CREATEUSER CROSS CSV CURRENT_DATE CURRENT_ROLE CURRENT_TIME CURRENT_TIMESTAMP CURRENT_USER CURSOR CYCLE @@ -575,7 +575,7 @@ add_additional_variables(char *name, bool insert) %type reserved_keyword unreserved_keyword ecpg_interval opt_ecpg_using %type col_name_keyword func_name_keyword precision opt_scale %type ECPGTypeName using_list ECPGColLabelCommon UsingConst -%type inf_val_list inf_col_list using_descriptor into_descriptor +%type using_descriptor into_descriptor %type prepared_name struct_union_type_with_symbol OptConsTableSpace %type ECPGunreserved ECPGunreserved_interval cvariable opt_bit_field %type AlterOwnerStmt OptTableSpaceOwner CreateTableSpaceStmt @@ -587,6 +587,8 @@ add_additional_variables(char *name, bool insert) %type locked_rels_list opt_granted_by RevokeRoleStmt alterdb_opt_item using_clause %type GrantRoleStmt opt_asymmetric aggr_args aggr_args_list old_aggr_definition %type old_aggr_elem for_locking_items TableLikeOptionList TableLikeOption +%type update_target_lists_list set_opt update_target_lists_el update_col_list +%type update_value_list update_col_list_el %type s_struct_union_symbol @@ -1369,14 +1371,6 @@ ClosePortalStmt: CLOSE name { $$ = cat2_str(make_str("close"), $2); } ; -/***************************************************************************** - * - * QUERY : - * COPY [BINARY] FROM/TO - * [USING DELIMITERS ] - * - *****************************************************************************/ - CopyStmt: COPY opt_binary qualified_name opt_oids copy_from copy_file_name copy_delimiter opt_with copy_opt_list { @@ -1389,6 +1383,13 @@ CopyStmt: COPY opt_binary qualified_name opt_oids copy_from $$ = cat_str(9, make_str("copy"), $2, $3, $4, $5, $6, $7, $8, $9); } + | COPY select_with_parens TO copy_file_name opt_with copy_opt_list + { + if (strcmp($4, "stdin") == 0) + mmerror(PARSE_ERROR, ET_ERROR, "copy to stdin not possible.\n"); + + $$ = cat_str(6, make_str("copy"), $2, make_str("to"), $4, $5, $6); + } ; copy_from: TO { $$ = make_str("to"); } @@ -2331,15 +2332,22 @@ opt_granted_by: GRANTED BY RoleId { $$ = cat2_str(make_str("granted by"), $3); /***************************************************************************** * * QUERY: - * create index on - * [ using ] "(" ( | using ] )+ ")" - * [ tablespace ] [ where ] + * QUERY: CREATE INDEX + * + * Note: we can't factor CONCURRENTLY into a separate production without + * making it a reserved word. + * + * Note: we cannot put TABLESPACE clause after WHERE clause unless we are + * willing to make TABLESPACE a fully reserved word. * *****************************************************************************/ IndexStmt: CREATE index_opt_unique INDEX index_name ON qualified_name access_method_clause '(' index_params ')' opt_definition OptTableSpace where_clause { $$ = cat_str(13, make_str("create"), $2, make_str("index"), $4, make_str("on"), $6, $7, make_str("("), $9, make_str(")"), $11, $12, $13); } + | CREATE index_opt_unique INDEX CONCURRENTLY index_name ON qualified_name + access_method_clause '(' index_params ')' opt_definition OptTableSpace where_clause + { $$ = cat_str(13, make_str("create"), $2, make_str("index concurrently"), $5, make_str("on"), $7, $8, make_str("("), $10, make_str(")"), $12, $13, $14); } ; index_opt_unique: UNIQUE { $$ = make_str("unique"); } @@ -3166,13 +3174,17 @@ opt_nowait: NOWAIT { $$ = make_str("nowait"); } *****************************************************************************/ UpdateStmt: UPDATE relation_expr_opt_alias - SET update_target_list + SET set_opt from_clause where_clause returning_clause {$$ = cat_str(7, make_str("update"), $2, make_str("set"), $4, $5, $6, $7); } ; +set_opt: + update_target_list { $$ = $1; } + | update_target_lists_list { $$ = $1; } + ; /***************************************************************************** * @@ -3433,6 +3445,35 @@ values_item: a_expr { $$ = $1; } | DEFAULT { $$ = make_str("DEFAULT"); } ; +update_target_lists_list: + update_target_lists_el { $$ = $1; } + | update_target_lists_list ',' update_target_lists_el { $$ = cat_str(3, $1, make_str(","), $3); } + ; + +update_target_lists_el: + '(' update_col_list ')' '=' '(' update_value_list ')' + { + $$ = cat_str(5, make_str("("), $2, make_str(")=("), $6, make_str(")")); + } + ; + +update_col_list: + update_col_list_el { $$ = $1; } + | update_col_list ',' update_col_list_el { $$ = cat_str(3, $1, make_str(","), $3); } + ; + +update_col_list_el: + ColId opt_indirection + { + $$ = cat2_str($1, $2); + } + ; + +update_value_list: + values_item { $$ = $1; } + | update_value_list ',' values_item { $$ = cat_str(3, $1, make_str(","), $3); } + ; + /***************************************************************************** * * clauses common to all Optimizable Stmts: @@ -4337,6 +4378,7 @@ target_el: a_expr AS ColLabel /* Target list as found in UPDATE table SET ... */ update_target_list: update_target_list ',' update_target_el { $$ = cat_str(3, $1, make_str(","),$3); } + /* INFORMIX workaround, no longer needed | '(' inf_col_list ')' '=' '(' inf_val_list ')' { struct inf_compat_col *ptrc; @@ -4360,12 +4402,12 @@ update_target_list: update_target_list ',' update_target_el vals = cat_str( 3, vals, ptrv->val, make_str(")") ); } $$ = cat_str( 3, cols, make_str("="), vals ); - } + } */ | update_target_el { $$ = $1; } ; -inf_col_list: ColId opt_indirection +/* inf_col_list: ColId opt_indirection { struct inf_compat_col *ptr = mm_alloc(sizeof(struct inf_compat_col)); @@ -4402,6 +4444,7 @@ inf_val_list: a_expr informix_val = ptr; } ; +*/ update_target_el: ColId opt_indirection '=' a_expr { $$ = cat_str(4, $1, $2, make_str("="), $4); } @@ -6216,6 +6259,7 @@ ECPGunreserved_con: ABORT_P { $$ = make_str("abort"); } | COMMENT { $$ = make_str("comment"); } | COMMIT { $$ = make_str("commit"); } | COMMITTED { $$ = make_str("committed"); } + | CONCURRENTLY { $$ = make_str("concurrently"); } /* | CONNECTION { $$ = make_str("connection"); }*/ | CONSTRAINTS { $$ = make_str("constraints"); } | CONVERSION_P { $$ = make_str("conversion"); } diff --git a/src/interfaces/ecpg/test/expected/connect-test1.c b/src/interfaces/ecpg/test/expected/connect-test1.c index 61119dd6fd..9ae85bff6d 100644 --- a/src/interfaces/ecpg/test/expected/connect-test1.c +++ b/src/interfaces/ecpg/test/expected/connect-test1.c @@ -56,7 +56,7 @@ main(void) #line 27 "test1.pgc" - { ECPGconnect(__LINE__, 0, "@localhost" , NULL,NULL , "main", 0); } + { ECPGconnect(__LINE__, 0, "@localhost" , "connectdb" , NULL , "main", 0); } #line 29 "test1.pgc" { ECPGdisconnect(__LINE__, "main");} @@ -70,7 +70,7 @@ main(void) #line 33 "test1.pgc" - { ECPGconnect(__LINE__, 0, "@localhost:55432" , NULL,NULL , "main", 0); } + { ECPGconnect(__LINE__, 0, "@localhost:55432" , "connectdb" , NULL , "main", 0); } #line 35 "test1.pgc" { ECPGdisconnect(__LINE__, "main");} @@ -84,7 +84,7 @@ main(void) #line 39 "test1.pgc" - { ECPGconnect(__LINE__, 0, ":55432" , NULL,NULL , "main", 0); } + { ECPGconnect(__LINE__, 0, ":55432" , "connectdb" , NULL , "main", 0); } #line 41 "test1.pgc" { ECPGdisconnect(__LINE__, "main");} diff --git a/src/interfaces/ecpg/test/expected/connect-test1.stderr b/src/interfaces/ecpg/test/expected/connect-test1.stderr index 9668223f7a..11596cc1ca 100644 --- a/src/interfaces/ecpg/test/expected/connect-test1.stderr +++ b/src/interfaces/ecpg/test/expected/connect-test1.stderr @@ -15,7 +15,7 @@ THE PORT NUMBER MIGHT HAVE BEEN CHANGED BY THE REGRESSION SCRIPT [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGconnect: opening database on localhost port +[NO_PID]: ECPGconnect: opening database on localhost port for user connectdb [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 @@ -23,7 +23,7 @@ THE PORT NUMBER MIGHT HAVE BEEN CHANGED BY THE REGRESSION SCRIPT [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGconnect: opening database on localhost port 55432 +[NO_PID]: ECPGconnect: opening database on localhost port 55432 for user connectdb [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 @@ -31,7 +31,7 @@ THE PORT NUMBER MIGHT HAVE BEEN CHANGED BY THE REGRESSION SCRIPT [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 -[NO_PID]: ECPGconnect: opening database on port 55432 +[NO_PID]: ECPGconnect: opening database on port 55432 for user connectdb [NO_PID]: sqlca: code: 0, state: 00000 [NO_PID]: ecpg_finish: Connection main closed. [NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-update.c b/src/interfaces/ecpg/test/expected/sql-update.c new file mode 100644 index 0000000000..39e4ddd6f6 --- /dev/null +++ b/src/interfaces/ecpg/test/expected/sql-update.c @@ -0,0 +1,140 @@ +/* Processed by ecpg (4.2.1) */ +/* These include files are added by the preprocessor */ +#include +#include +#include +#include +/* End of automatic include section */ + +#line 1 "update.pgc" +#include +#include +#include + + +#line 1 "regression.h" + + + + + + +#line 5 "update.pgc" + + +int main(int argc, char* argv[]) { + /* exec sql begin declare section */ + + +#line 9 "update.pgc" + int i1 [ 3 ] , i2 [ 3 ] ; +/* exec sql end declare section */ +#line 10 "update.pgc" + + + ECPGdebug(1, stderr); + { ECPGconnect(__LINE__, 0, "regress1" , NULL,NULL , NULL, 0); } +#line 13 "update.pgc" + + + /* exec sql whenever sql_warning sqlprint ; */ +#line 15 "update.pgc" + + /* exec sql whenever sqlerror sqlprint ; */ +#line 16 "update.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, "create table test ( a int , b int ) ", ECPGt_EOIT, ECPGt_EORT); +#line 18 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 18 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 18 "update.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, "insert into test ( a , b ) values( 1 , 1 ) ", ECPGt_EOIT, ECPGt_EORT); +#line 20 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 20 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 20 "update.pgc" + + { ECPGdo(__LINE__, 0, 1, NULL, "insert into test ( a , b ) values( 2 , 2 ) ", ECPGt_EOIT, ECPGt_EORT); +#line 21 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 21 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 21 "update.pgc" + + { ECPGdo(__LINE__, 0, 1, NULL, "insert into test ( a , b ) values( 3 , 3 ) ", ECPGt_EOIT, ECPGt_EORT); +#line 22 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 22 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 22 "update.pgc" + + + { ECPGdo(__LINE__, 0, 1, NULL, "update test set a = a + 1 ", ECPGt_EOIT, ECPGt_EORT); +#line 24 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 24 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 24 "update.pgc" + + { ECPGdo(__LINE__, 0, 1, NULL, "update test set ( a , b )=( 5 , 5 ) where a = 4 ", ECPGt_EOIT, ECPGt_EORT); +#line 25 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 25 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 25 "update.pgc" + + { ECPGdo(__LINE__, 0, 1, NULL, "update test set a = 4 where a = 3 ", ECPGt_EOIT, ECPGt_EORT); +#line 26 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 26 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 26 "update.pgc" +; + + { ECPGdo(__LINE__, 0, 1, NULL, "select a , b from test order by a", ECPGt_EOIT, + ECPGt_int,(i1),(long)1,(long)3,sizeof(int), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, + ECPGt_int,(i2),(long)1,(long)3,sizeof(int), + ECPGt_NO_INDICATOR, NULL , 0L, 0L, 0L, ECPGt_EORT); +#line 28 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 28 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 28 "update.pgc" + + + printf("test\na b\n%d %d\n%d %d\n%d %d\n", i1[0], i2[0], i1[1], i2[1], i1[2], i2[2]); + + { ECPGdisconnect(__LINE__, "ALL"); +#line 32 "update.pgc" + +if (sqlca.sqlwarn[0] == 'W') sqlprint(); +#line 32 "update.pgc" + +if (sqlca.sqlcode < 0) sqlprint();} +#line 32 "update.pgc" + + + return 0; +} diff --git a/src/interfaces/ecpg/test/expected/sql-update.stderr b/src/interfaces/ecpg/test/expected/sql-update.stderr new file mode 100644 index 0000000000..eab4a86c0d --- /dev/null +++ b/src/interfaces/ecpg/test/expected/sql-update.stderr @@ -0,0 +1,50 @@ +[NO_PID]: ECPGdebug: set to 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGconnect: opening database regress1 on port +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 18: QUERY: create table test ( a int , b int ) on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 18 Ok: CREATE TABLE +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 20: QUERY: insert into test ( a , b ) values( 1 , 1 ) on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 20 Ok: INSERT 0 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 21: QUERY: insert into test ( a , b ) values( 2 , 2 ) on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 21 Ok: INSERT 0 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 22: QUERY: insert into test ( a , b ) values( 3 , 3 ) on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 22 Ok: INSERT 0 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 24: QUERY: update test set a = a + 1 on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 24 Ok: UPDATE 3 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 25: QUERY: update test set ( a , b )=( 5 , 5 ) where a = 4 on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 25 Ok: UPDATE 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 26: QUERY: update test set a = 4 where a = 3 on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 26 Ok: UPDATE 1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 28: QUERY: select a , b from test order by a on connection regress1 +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGexecute line 28: Correctly got 3 tuples with 2 fields +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_data line 28: RESULT: 2 offset: -1 array: Yes +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_data line 28: RESULT: 4 offset: -1 array: Yes +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_data line 28: RESULT: 5 offset: -1 array: Yes +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_data line 28: RESULT: 1 offset: -1 array: Yes +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_data line 28: RESULT: 2 offset: -1 array: Yes +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ECPGget_data line 28: RESULT: 5 offset: -1 array: Yes +[NO_PID]: sqlca: code: 0, state: 00000 +[NO_PID]: ecpg_finish: Connection regress1 closed. +[NO_PID]: sqlca: code: 0, state: 00000 diff --git a/src/interfaces/ecpg/test/expected/sql-update.stdout b/src/interfaces/ecpg/test/expected/sql-update.stdout new file mode 100644 index 0000000000..a861f3ea2d --- /dev/null +++ b/src/interfaces/ecpg/test/expected/sql-update.stdout @@ -0,0 +1,5 @@ +test +a b +2 1 +4 2 +5 5 diff --git a/src/interfaces/ecpg/test/sql/Makefile b/src/interfaces/ecpg/test/sql/Makefile index 4ec2befcc7..381ff6bc6c 100644 --- a/src/interfaces/ecpg/test/sql/Makefile +++ b/src/interfaces/ecpg/test/sql/Makefile @@ -13,6 +13,7 @@ TESTS = define define.c \ indicators indicators.c \ quote quote.c \ show show.c \ + update update.c \ copystdout copystdout.c all: $(TESTS) diff --git a/src/interfaces/ecpg/test/sql/update.pgc b/src/interfaces/ecpg/test/sql/update.pgc new file mode 100644 index 0000000000..c406c3aba2 --- /dev/null +++ b/src/interfaces/ecpg/test/sql/update.pgc @@ -0,0 +1,35 @@ +#include +#include +#include + +EXEC SQL INCLUDE ../regression; + +int main(int argc, char* argv[]) { + EXEC SQL BEGIN DECLARE SECTION; + int i1[3], i2[3]; + EXEC SQL END DECLARE SECTION; + + ECPGdebug(1, stderr); + EXEC SQL CONNECT TO REGRESSDB1; + + EXEC SQL WHENEVER SQLWARNING SQLPRINT; + EXEC SQL WHENEVER SQLERROR SQLPRINT; + + EXEC SQL CREATE TABLE test(a int, b int); + + EXEC SQL INSERT INTO test (a,b) values (1, 1); + EXEC SQL INSERT INTO test (a,b) values (2, 2); + EXEC SQL INSERT INTO test (a,b) values (3, 3); + + EXEC SQL UPDATE test set a=a+1; + EXEC SQL UPDATE test set (a,b)=(5,5) where a = 4; + EXEC SQL UPDATE test set a=4 where a=3;; + + EXEC SQL SELECT a,b into :i1,:i2 from test order by a; + + printf("test\na b\n%d %d\n%d %d\n%d %d\n", i1[0], i2[0], i1[1], i2[1], i1[2], i2[2]); + + EXEC SQL DISCONNECT ALL; + + return 0; +}