diff -rcN ecpg/ChangeLog ecpg.mm/ChangeLog *** ecpg/ChangeLog Fri Jan 8 07:37:57 1999 --- ecpg.mm/ChangeLog Mon Jan 18 16:40:33 1999 *************** *** 371,374 **** --- 371,379 ---- - Synced preproc.y with gram.y for for-update clause and changes in handling of numerics + + Mon Jan 18 11:22:44 CET 1999 + + - Added INTERSECT, EXCEPT and UNION for Select statements + - Put keywords.c in sync again after forgettimg it the last time. - Set version to 2.4.6 diff -rcN ecpg/include/ecpglib.h ecpg.mm/include/ecpglib.h *** ecpg/include/ecpglib.h Tue Sep 1 13:02:44 1998 --- ecpg.mm/include/ecpglib.h Mon Jan 18 13:21:50 1999 *************** *** 1,4 **** ! #include #ifdef __cplusplus extern "C" --- 1,4 ---- ! #include #ifdef __cplusplus extern "C" diff -rcN ecpg/preproc/Makefile ecpg.mm/preproc/Makefile *** ecpg/preproc/Makefile Sun Jan 17 11:42:04 1999 --- ecpg.mm/preproc/Makefile Mon Jan 18 12:07:58 1999 *************** *** 3,9 **** MAJOR_VERSION=2 MINOR_VERSION=4 ! PATCHLEVEL=5 CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \ --- 3,9 ---- MAJOR_VERSION=2 MINOR_VERSION=4 ! PATCHLEVEL=6 CFLAGS+=-I../include -DMAJOR_VERSION=$(MAJOR_VERSION) \ -DMINOR_VERSION=$(MINOR_VERSION) -DPATCHLEVEL=$(PATCHLEVEL) \ diff -rcN ecpg/preproc/keywords.c ecpg.mm/preproc/keywords.c *** ecpg/preproc/keywords.c Tue Dec 22 20:55:26 1998 --- ecpg.mm/preproc/keywords.c Mon Jan 18 16:39:48 1999 *************** *** 7,13 **** * * * IDENTIFICATION ! * $Header: /usr/local/cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.7 1998/12/22 18:50:55 scrappy Exp $ * *------------------------------------------------------------------------- */ --- 7,13 ---- * * * IDENTIFICATION ! * $Header: /usr/local/cvsroot/pgsql/src/interfaces/ecpg/preproc/keywords.c,v 1.6 1998/10/03 02:33:36 thomas Exp $ * *------------------------------------------------------------------------- */ *************** *** 94,99 **** --- 94,101 ---- {"else", ELSE}, {"encoding", ENCODING}, {"end", END_TRANS}, + /***S*I***/ + {"except", EXCEPT}, {"execute", EXECUTE}, {"exists", EXISTS}, {"explain", EXPLAIN}, *************** *** 121,136 **** --- 123,142 ---- {"insensitive", INSENSITIVE}, {"insert", INSERT}, {"instead", INSTEAD}, + /***S*I***/ + {"intersect", INTERSECT}, {"interval", INTERVAL}, {"into", INTO}, {"is", IS}, {"isnull", ISNULL}, + {"isolation", ISOLATION}, {"join", JOIN}, {"key", KEY}, {"lancompiler", LANCOMPILER}, {"language", LANGUAGE}, {"leading", LEADING}, {"left", LEFT}, + {"level", LEVEL}, {"like", LIKE}, {"listen", LISTEN}, {"load", LOAD}, diff -rcN ecpg/preproc/preproc.y ecpg.mm/preproc/preproc.y *** ecpg/preproc/preproc.y Fri Jan 8 07:37:58 1999 --- ecpg.mm/preproc/preproc.y Mon Jan 18 12:03:32 1999 *************** *** 20,26 **** */ static int struct_level = 0; static char errortext[128]; ! static int QueryIsRule = 0; static enum ECPGttype actual_type[STRUCT_DEPTH]; static char *actual_storage[STRUCT_DEPTH]; --- 20,26 ---- */ static int struct_level = 0; static char errortext[128]; ! static int QueryIsRule = 0, ForUpdateNotAllowed = 0; static enum ECPGttype actual_type[STRUCT_DEPTH]; static char *actual_storage[STRUCT_DEPTH]; *************** *** 536,546 **** CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP, ! ELSE, END_TRANS, EXECUTE, EXISTS, EXTRACT, FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL, GRANT, GROUP, HAVING, HOUR_P, ! IN, INNER_P, INSENSITIVE, INSERT, INTERVAL, INTO, IS, ISOLATION, ! JOIN, KEY, LANGUAGE, LEADING, LEFT, LEVEL, LIKE, LOCAL, MATCH, MINUTE_P, MONTH_P, NAMES, NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC, OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P, --- 536,546 ---- CONSTRAINT, CREATE, CROSS, CURRENT, CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP, CURRENT_USER, CURSOR, DAY_P, DECIMAL, DECLARE, DEFAULT, DELETE, DESC, DISTINCT, DOUBLE, DROP, ! ELSE, END_TRANS, EXCEPT, EXECUTE, EXISTS, EXTRACT, FALSE_P, FETCH, FLOAT, FOR, FOREIGN, FROM, FULL, GRANT, GROUP, HAVING, HOUR_P, ! IN, INNER_P, INSENSITIVE, INSERT, INTERSECT, INTERVAL, INTO, IS, ! ISOLATION, JOIN, KEY, LANGUAGE, LEADING, LEFT, LEVEL, LIKE, LOCAL, MATCH, MINUTE_P, MONTH_P, NAMES, NATIONAL, NATURAL, NCHAR, NEXT, NO, NOT, NULLIF, NULL_P, NUMERIC, OF, ON, ONLY, OPTION, OR, ORDER, OUTER_P, *************** *** 608,614 **** %left '.' %left '[' ']' %nonassoc TYPECAST ! %left UNION %type Iconst Fconst Sconst TransactionStmt CreateStmt UserId %type CreateAsElement OptCreateAs CreateAsList CreateAsStmt --- 608,614 ---- %left '.' %left '[' ']' %nonassoc TYPECAST ! %left UNION INTERSECT EXCEPT %type Iconst Fconst Sconst TransactionStmt CreateStmt UserId %type CreateAsElement OptCreateAs CreateAsList CreateAsStmt *************** *** 630,636 **** %type opt_decimal Character character opt_varying opt_charset %type opt_collate Datetime datetime opt_timezone opt_interval %type numeric a_expr_or_null row_expr row_descriptor row_list ! %type SelectStmt union_clause select_list SubSelect result %type opt_table opt_union opt_unique sort_clause sortby_list %type sortby OptUseOp opt_inh_star relation_name_list name_list %type group_clause having_clause from_clause c_list --- 630,636 ---- %type opt_decimal Character character opt_varying opt_charset %type opt_collate Datetime datetime opt_timezone opt_interval %type numeric a_expr_or_null row_expr row_descriptor row_list ! %type SelectStmt SubSelect result %type opt_table opt_union opt_unique sort_clause sortby_list %type sortby OptUseOp opt_inh_star relation_name_list name_list %type group_clause having_clause from_clause c_list *************** *** 638,644 **** %type join_using where_clause relation_expr row_op sub_type %type opt_column_list insert_rest InsertStmt OptimizableStmt %type columnList DeleteStmt LockStmt UpdateStmt CursorStmt ! %type NotifyStmt columnElem copy_dirn SubUnion c_expr UnlistenStmt %type copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary %type opt_with_copy FetchStmt opt_direction fetch_how_many opt_portal_name %type ClosePortalStmt DestroyStmt VacuumStmt opt_verbose --- 638,644 ---- %type join_using where_clause relation_expr row_op sub_type %type opt_column_list insert_rest InsertStmt OptimizableStmt %type columnList DeleteStmt LockStmt UpdateStmt CursorStmt ! %type NotifyStmt columnElem copy_dirn c_expr UnlistenStmt %type copy_delimiter ListenStmt CopyStmt copy_file_name opt_binary %type opt_with_copy FetchStmt opt_direction fetch_how_many opt_portal_name %type ClosePortalStmt DestroyStmt VacuumStmt opt_verbose *************** *** 666,671 **** --- 666,672 ---- %type GrantStmt privileges operation_commalist operation %type cursor_clause opt_cursor opt_readonly opt_of opt_lmode %type case_expr when_clause_list case_default case_arg when_clause + %type select_w_o_sort %type ECPGWhenever ECPGConnect connection_target ECPGOpen open_opts %type indicator ECPGExecute ecpg_expr dotext *************** *** 2121,2127 **** OptStmtList: NOTHING { $$ = make1_str("nothing"); } | OptimizableStmt { $$ = $1; } | '[' OptStmtBlock ']' { $$ = cat3_str(make1_str("["), $2, make1_str("]")); } ! | '(' OptStmtBlock ')' { $$ = cat3_str(make1_str("("), $2, make1_str(")")); } ; OptStmtBlock: OptStmtMulti --- 2122,2131 ---- OptStmtList: NOTHING { $$ = make1_str("nothing"); } | OptimizableStmt { $$ = $1; } | '[' OptStmtBlock ']' { $$ = cat3_str(make1_str("["), $2, make1_str("]")); } ! /***S*I*D***/ ! /* We comment this out because it produces a shift / reduce conflict ! * with the select_w_o_sort rule */ ! /* | '(' OptStmtBlock ')' { $$ = cat3_str(make1_str("("), $2, make1_str(")")); }*/ ; OptStmtBlock: OptStmtMulti *************** *** 2132,2139 **** OptStmtMulti: OptStmtMulti OptimizableStmt ';' { $$ = cat3_str($1, $2, make1_str(";")); } ! | OptStmtMulti OptimizableStmt ! { $$ = cat2_str($1, $2); } | OptimizableStmt ';' { $$ = cat2_str($1, make1_str(";")); } ; --- 2136,2148 ---- OptStmtMulti: OptStmtMulti OptimizableStmt ';' { $$ = cat3_str($1, $2, make1_str(";")); } ! /***S*I***/ ! /* We comment the next rule because it seems to be redundant ! * and produces 16 shift/reduce conflicts with the new SelectStmt rule ! * needed for EXCEPT and INTERSECT. So far I did not notice any ! * violations by removing the rule! */ ! /* | OptStmtMulti OptimizableStmt ! { $$ = cat2_str($1, $2); }*/ | OptimizableStmt ';' { $$ = cat2_str($1, make1_str(";")); } ; *************** *** 2389,2397 **** * *****************************************************************************/ ! InsertStmt: INSERT INTO relation_name opt_column_list insert_rest { ! $$ = cat4_str(make1_str("insert into"), $3, $4, $5); } ; --- 2398,2412 ---- * *****************************************************************************/ ! /***S*I***/ ! /* This rule used 'opt_column_list' between 'relation_name' and 'insert_rest' ! * originally. When the second rule of 'insert_rest' was changed to use ! * the new 'SelectStmt' rule (for INTERSECT and EXCEPT) it produced a shift/red uce ! * conflict. So I just changed the rules 'InsertStmt' and 'insert_rest' to accept ! * the same statements without any shift/reduce conflicts */ ! InsertStmt: INSERT INTO relation_name insert_rest { ! $$ = cat3_str(make1_str("insert into"), $3, $4); } ; *************** *** 2403,2414 **** { $$ = make1_str("default values"); } ! | SELECT opt_unique res_target_list2 ! from_clause where_clause ! group_clause having_clause ! union_clause { ! $$ = cat4_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7, $8); } ; --- 2418,2434 ---- { $$ = make1_str("default values"); } ! | SelectStmt { ! $$ = $1 ! } ! | '(' columnList ')' VALUES '(' res_target_list2 ')' ! { ! $$ = make5_str(make1_str("("), $2, make1_str(") values ("), $6, make1_str(")")); ! } ! | '(' columnList ')' SelectStmt ! { ! $$ = make4_str(make1_str("("), $2, make1_str(")"), $4); } ; *************** *** 2546,2557 **** * CURSOR STATEMENTS * *****************************************************************************/ ! CursorStmt: DECLARE name opt_cursor CURSOR FOR ! SELECT opt_unique res_target_list2 ! from_clause where_clause ! group_clause having_clause ! union_clause sort_clause ! cursor_clause { struct cursor *ptr, *this; --- 2566,2572 ---- * CURSOR STATEMENTS * *****************************************************************************/ ! CursorStmt: DECLARE name opt_cursor CURSOR FOR SelectStmt cursor_clause { struct cursor *ptr, *this; *************** *** 2570,2576 **** /* initial definition */ this->next = cur; this->name = $2; ! this->command = cat4_str(cat5_str(cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for select"), $7), $8, $9, $10, $11), $12, $13, $14); this->argsinsert = argsinsert; this->argsresult = argsresult; argsinsert = argsresult = NULL; --- 2585,2591 ---- /* initial definition */ this->next = cur; this->name = $2; ! this->command = cat2_str(cat5_str(make1_str("declare"), mm_strdup($2), $3, make1_str("cursor for"), $6), $7); this->argsinsert = argsinsert; this->argsresult = argsresult; argsinsert = argsresult = NULL; *************** *** 2609,2662 **** * *****************************************************************************/ ! SelectStmt: SELECT opt_unique res_target_list2 ! result from_clause where_clause ! group_clause having_clause ! union_clause sort_clause for_update_clause { ! $$ = cat3_str(cat5_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7, $8, $9), $10, $11); ! if (strlen($11) > 0) ! { ! if (strlen($9) > 0) ! yyerror("SELECT FOR UPDATE is not allowed with UNION clause"); ! if (strlen($7) > 0) ! yyerror("SELECT FOR UPDATE is not allowed with GROUP BY clause"); ! if (strlen($6) > 0) ! yyerror("SELECT FOR UPDATE is not allowed with HAVING clause"); ! } ! } ! ; ! ! SubSelect: SELECT opt_unique res_target_list2 ! from_clause where_clause ! group_clause having_clause ! union_clause ! { ! $$ =cat4_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7, $8); ! } ! ; ! union_clause: UNION opt_union select_list ! { ! $$ = cat3_str(make1_str("union"), $2, $3); } - | /*EMPTY*/ - { $$ = make1_str(""); } - ; ! select_list: select_list UNION opt_union SubUnion ! { ! $$ = cat4_str($1, make1_str("union"), $3, $4); ! } ! | SubUnion ! { $$ = $1; } ; ! SubUnion: SELECT opt_unique res_target_list2 ! from_clause where_clause ! group_clause having_clause { ! $$ = cat3_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7); } ; --- 2624,2683 ---- * *****************************************************************************/ ! /***S*I***/ ! /* The new 'SelectStmt' rule adapted for the optional use of INTERSECT EXCEPT a nd UNION ! * accepts the use of '(' and ')' to select an order of set operations. ! */ ! SelectStmt: select_w_o_sort sort_clause for_update_clause { ! if (strlen($3) > 0 && ForUpdateNotAllowed != 0) ! yyerror("SELECT FOR UPDATE is not allowed in this context"); ! ForUpdateNotAllowed = 0; ! $$ = cat3_str($1, $2, $3); } ! /***S*I***/ ! /* This rule parses Select statements including UNION INTERSECT and EXCEPT. ! * '(' and ')' can be used to specify the order of the operations ! * (UNION EXCEPT INTERSECT). Without the use of '(' and ')' we want the ! * operations to be left associative. ! * ! * The sort_clause is not handled here! ! */ ! select_w_o_sort: '(' select_w_o_sort ')' ! { ! $$ = make3_str(make1_str("("), $2, make1_str(")")); ! } ! | SubSelect ! { ! $$ = $1; ! } ! | select_w_o_sort EXCEPT select_w_o_sort ! { ! $$ = cat3_str($1, make1_str("except"), $3); ! ForUpdateNotAllowed = 1; ! } ! | select_w_o_sort UNION opt_union select_w_o_sort ! { ! $$ = cat3_str($1, make1_str("union"), $3); ! ForUpdateNotAllowed = 1; ! } ! | select_w_o_sort INTERSECT opt_union select_w_o_sort ! { ! $$ = cat3_str($1, make1_str("intersect"), $3); ! ForUpdateNotAllowed = 1; ! } ; ! /***S*I***/ ! SubSelect: SELECT opt_unique res_target_list2 ! result from_clause where_clause ! group_clause having_clause { ! $$ = cat4_str(cat5_str(make1_str("select"), $2, $3, $4, $5), $6, $7, $8); ! if (strlen($7) > 0 || strlen($8) > 0) ! ForUpdateNotAllowed = 1; } ; *************** *** 4416,4424 **** yyerror(errortext); } ! if (strncmp($1, "unix", 4) == 0 && strncmp($2, "localhost", 9) != 0) { ! sprintf(errortext, "unix domain sockets only work on 'localhost'"); yyerror(errortext); } --- 4437,4445 ---- yyerror(errortext); } ! if (strncmp($1, "unix", 4) == 0 && strncmp($2 + 3, "localhost", 9) != 0) { ! sprintf(errortext, "unix domain sockets only work on 'localhost' but not on '%9.9s'", $2); yyerror(errortext); } diff -rcN ecpg/test/Makefile ecpg.mm/test/Makefile *** ecpg/test/Makefile Wed Aug 12 06:44:29 1998 --- ecpg.mm/test/Makefile Mon Jan 18 13:06:24 1999 *************** *** 1,18 **** all: test1 test2 perftest ! LDFLAGS=-g -I ../include -I ../../libpq -L../lib -lecpg -L../../libpq -lpq -lcrypt test1: test1.c test1.c: test1.pgc ! ../preproc/ecpg $? test2: test2.c test2.c: test2.pgc ! ../preproc/ecpg $? perftest: perftest.c perftest.c:perftest.pgc ! ../preproc/ecpg $? clean: /bin/rm test1 test2 perftest *.c log --- 1,18 ---- all: test1 test2 perftest ! LDFLAGS=-g -I /usr/local/pgsql/include -L/usr/local/pgsql/lib -lecpg -lpq -lcrypt test1: test1.c test1.c: test1.pgc ! /usr/local/pgsql/bin/ecpg $? test2: test2.c test2.c: test2.pgc ! /usr/local/pgsql/bin/ecpg $? perftest: perftest.c perftest.c:perftest.pgc ! /usr/local/pgsql/bin/ecpg $? clean: /bin/rm test1 test2 perftest *.c log diff -rcN ecpg/test/test2.pgc ecpg.mm/test/test2.pgc *** ecpg/test/test2.pgc Sat Oct 3 07:47:16 1998 --- ecpg.mm/test/test2.pgc Mon Jan 18 12:04:42 1999 *************** *** 30,43 **** ECPGdebug(1, dbgs); strcpy(msg, "connect"); ! exec sql connect to tcp:postgresql://localhost:5432/mm; strcpy(msg, "create"); exec sql create table meskes(name char(8), born integer, age smallint, married char(8)); strcpy(msg, "insert"); ! exec sql insert into meskes(name, born, age, married) values ('Petra', 19661202, 31, '19900404'); ! exec sql insert into meskes(name, born, age, married) values ('Michael', 19660117, 32, '19900404'); exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 7); exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4); exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 0); --- 30,43 ---- ECPGdebug(1, dbgs); strcpy(msg, "connect"); ! exec sql connect to unix:postgresql://localhost:5432/mm; strcpy(msg, "create"); exec sql create table meskes(name char(8), born integer, age smallint, married char(8)); strcpy(msg, "insert"); ! exec sql insert into meskes(name, born, age, married) values ('Petra', 19661202, 32, '19900404'); ! exec sql insert into meskes(name, born, age, married) values ('Michael', 19660117, 33, '19900404'); exec sql insert into meskes(name, born, age) values ('Carsten', 19910103, 7); exec sql insert into meskes(name, born, age) values ('Marc', 19930907, 4); exec sql insert into meskes(name, born, age) values ('Chris', 19970923, 0);