Build Version : T2.1.0.16188 Firebird 2.1 Beta 1 (writeBuildNum.sh,v 1.16345 2007/07/29 07:30:44 robocop Exp ) Update of /cvsroot/firebird/firebird2/src/gpre In directory sc8-pr-cvs17:/tmp/cvs-serv21433/src/gpre Modified Files: cme.cpp fbrmclib.cpp gpre.cpp gpre.h gpreswi.h hsh.h par.cpp rmc.cpp sqe.cpp words.h Log Message: Commit GPRE enhancements on behalf of Stephen Boyd. This batch of changes includes: - Support for FIRST/SKIP clauses - Support for CURRENT_CONNECTION, CURRENT_ROLE, CURRENT_TRANSACTION and CURRENT_USER context variables - Changed the BLR generated for RM/Cobol programs to use blr_cstring rather than blr_text so that CHAR and VARCHAR fields are not written as "fixed length" fields from Cobol programs. Incoming CHAR and VARCHAR fields are right filled with spaces inbound to the Cobol program and stripped of trailing spaces outbound. Index: cme.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/cme.cpp,v retrieving revision 1.39 retrieving revision 1.40 diff -b -U3 -r1.39 -r1.40 --- cme.cpp 11 Nov 2006 02:47:05 -0000 1.39 +++ cme.cpp 29 Jul 2007 07:30:42 -0000 1.40 @@ -24,6 +24,9 @@ // // // 2006.10.12 Stephen W. Boyd - Added support for WITH LOCK subclause. +// 2007.05.23 Stephen W. Boyd - Added support for FIRST/SKIP clauses. +// 2007.06.15 Stephen W. Boyd - Added support for CURRENT_CONNECTION, CURRENT_ROLE, +// CURRENT_TRANSACTION and CURRENT_USER //____________________________________________________________ // // @@ -44,6 +47,7 @@ #include "../gpre/prett_proto.h" #include "../jrd/dsc_proto.h" #include "../gpre/msc_proto.h" +#include "../jrd/misc_func_ids.h" static void cmp_array(GPRE_NOD, gpre_req*); static void cmp_array_element(GPRE_NOD, gpre_req*); @@ -62,6 +66,7 @@ static void stuff_sdl_number(const SLONG, REF); const int USER_LENGTH = 32; +const int ROLE_LENGTH = 32; //#define STUFF(blr) *request->req_blr++ = (UCHAR) (blr) //#define STUFF_WORD(blr) STUFF (blr); STUFF (blr >> 8) //#define STUFF_CSTRING(blr) stuff_cstring (request, blr) @@ -130,6 +135,7 @@ { nod_current_date, blr_current_date }, { nod_current_time, blr_current_time }, { nod_current_timestamp, blr_current_timestamp }, + { nod_current_role, blr_current_role }, { nod_any, 0 } }; @@ -336,6 +342,22 @@ request->add_word(element->mel_position); return; } + + case nod_current_connection: + request->add_byte(blr_internal_info); + request->add_byte(blr_literal); + request->add_byte(blr_long); + request->add_byte(0); + request->add_long(internal_connection_id); + return; + + case nod_current_transaction: + request->add_byte(blr_internal_info); + request->add_byte(blr_literal); + request->add_byte(blr_long); + request->add_byte(0); + request->add_long(internal_transaction_id); + return; } const op_table* nod2blr_operator; @@ -994,6 +1016,19 @@ f->fld_charset_id = CS_ASCII; return; + case nod_current_connection: + case nod_current_transaction: + f->fld_dtype = dtype_long; + f->fld_length = sizeof(SLONG); + return; + + case nod_current_role: + f->fld_dtype = dtype_text; + f->fld_ttype = ttype_ascii; + f->fld_charset_id = CS_ASCII; + f->fld_length = ROLE_LENGTH; + return; + default: CPR_error("CME_get_dtype: node type not supported"); } @@ -1158,6 +1193,18 @@ CME_expr(selection->rse_first, request); } + if (selection->rse_sqlfirst) + { + request->add_byte(blr_first); + CME_expr(selection->rse_sqlfirst->nod_arg[0], request); + } + + if (selection->rse_sqlskip) + { + request->add_byte(blr_skip); + CME_expr(selection->rse_sqlskip->nod_arg[0], request); + } + if (selection->rse_boolean) { request->add_byte(blr_boolean); Index: fbrmclib.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/fbrmclib.cpp,v retrieving revision 1.1 retrieving revision 1.2 diff -b -U3 -r1.1 -r1.2 --- fbrmclib.cpp 10 Nov 2006 07:52:52 -0000 1.1 +++ fbrmclib.cpp 29 Jul 2007 07:30:42 -0000 1.2 @@ -165,6 +165,8 @@ RM_PROTO(rmc_ctod); RM_PROTO(rmc_ftoc); RM_PROTO(rmc_ctof); +RM_PROTO(rmc_ctos); +RM_PROTO(rmc_stoc); #ifdef __cplusplus } #endif @@ -1516,8 +1518,43 @@ return (0); } +// Convert a Cobol alpha (PIC X) field to a C string. This is done by trimming trailing spaces +// and adding the trailing '\0'. +EXPORT RM_ENTRY(rmc_ctos) +{ + char* dest = (char*) arg_vector[-1].a_address; + const int dlen = arg_vector[-1].a_length; + const char* src = (char*) arg_vector[0].a_address; + const int slen = arg_vector[0].a_length; + + int i = slen - 1; + while (src[i] == ' ' && i >= 0) + --i; + + int len = ((i + 1) < dlen) ? i + 1 : dlen - 1; + memmove(dest, src, len); + dest[len] = '\0'; + + return (0); +} +// Convert a C string to a Cobol alpha (PIC X) field. This is done by copying the original +// string and padding on the right with spaces. +EXPORT RM_ENTRY(rmc_stoc) +{ + char* dest = (char*) arg_vector[-1].a_address; + const int dlen = arg_vector[-1].a_length; + const char* src = (char*) arg_vector[0].a_address; + const int slen = arg_vector[0].a_length; + + memset(dest, ' ', dlen); + int len = (slen <= dlen) ? slen : dlen; + memmove(dest, src, len); + + return (0); +} + +static char* banner = "Firebird Embedded SQL Interface"; -static char *banner = "Firebird Embedded SQL Interface"; #ifdef __cplusplus extern "C" { @@ -1604,5 +1641,7 @@ { "rmc_ctod", rmc_ctod, "rmc_ctod" }, { "rmc_ftoc", rmc_ftoc, "rmc_ftoc" }, { "rmc_ctof", rmc_ctof, "rmc_ctof" }, + { "rmc_ctos", rmc_ctos, "rmc_ctos" }, + { "rmc_stoc", rmc_stoc, "RMC_stoc" }, { NULL, NULL, NULL } }; Index: gpre.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/gpre.cpp,v retrieving revision 1.84 retrieving revision 1.85 diff -b -U3 -r1.84 -r1.85 --- gpre.cpp 25 Apr 2007 14:10:19 -0000 1.84 +++ gpre.cpp 29 Jul 2007 07:30:42 -0000 1.85 @@ -643,6 +643,7 @@ case IN_SW_GPRE_RMCOBOL: gpreGlob.sw_cob_dialect = cob_rmc; + gpreGlob.sw_cstring = true; gen_routine = RMC_action; break; Index: gpre.h =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/gpre.h,v retrieving revision 1.87 retrieving revision 1.88 diff -b -U3 -r1.87 -r1.88 --- gpre.h 7 Apr 2007 08:47:45 -0000 1.87 +++ gpre.h 29 Jul 2007 07:30:42 -0000 1.88 @@ -61,6 +61,10 @@ * causing problems with Cobol programs since the QLI and Cobol reserved word * lists intersect. * Stephen W. Boyd 21.Mar.2007 + * + * 2007.05.23 Stephen W. Boyd - Added support for SQL "first n" and "skip n" clauses + * 2007.06.15 Stephen W. Boyd - Added support for CURRENT_CONNECTION, CURRENT_ROLE, + * CURRENT_TRANSACTION and CURRENT_USER context variables. */ #ifndef GPRE_GPRE_H @@ -262,7 +266,7 @@ nod_natural, nod_index_order, nod_ansi_all, nod_extract, nod_current_date, nod_current_time, nod_current_timestamp, - nod_lowcase, + nod_lowcase, nod_current_connection, nod_current_role, nod_current_transaction, nod_LASTNOD /* Leave this debugging GPRE_NOD last */ } NOD_T; @@ -914,6 +918,8 @@ USHORT rse_type; /* node type */ gpre_nod* rse_boolean; /* boolean expression, if present */ gpre_nod* rse_first; /* "first n" clause, if present */ + gpre_nod* rse_sqlfirst; /* SQL "first n" clause if present */ + gpre_nod* rse_sqlskip; /* SQL "skip n" clause if present */ gpre_nod* rse_reduced; /* projection clause, if present */ gpre_nod* rse_sort; /* sort clause, if present */ gpre_nod* rse_fields; /* list of fields */ Index: gpreswi.h =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/gpreswi.h,v retrieving revision 1.16 retrieving revision 1.17 diff -b -U3 -r1.16 -r1.17 --- gpreswi.h 7 Apr 2007 08:47:45 -0000 1.16 +++ gpreswi.h 29 Jul 2007 07:30:42 -0000 1.17 @@ -114,10 +114,9 @@ * deliver dates to Cobol programs */ IN_SW_GPRE_DATE_FMT, - /* - * Added to allow QLI processing the be suppressed. QLI and COBOL reserved word lists - * intersect and since QLI reserved words are recognized no matter where the occur in the + * Added to allow QLI processing to be suppressed. QLI and COBOL reserved word lists + * intersect and since QLI reserved words are recognized no matter where they occur in the * source stream this was causing bogus errors while parsing COBOL programs. */ IN_SW_NO_QLI, Index: hsh.h =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/hsh.h,v retrieving revision 1.6 retrieving revision 1.7 diff -b -U3 -r1.6 -r1.7 --- hsh.h 24 Nov 2004 09:09:04 -0000 1.6 +++ hsh.h 29 Jul 2007 07:30:42 -0000 1.7 @@ -15,6 +15,10 @@ * * All Rights Reserved. * Contributor(s): ______________________________________. + * + * 2007.05.23 Stephen W. Boyd - Added SKIP keyword + * 2007.06.15 Stephen W. Boyd - Added CURRENT_CONNECTION, CURRENT_ROLE, + * CURRENT_TRANSACTION and CURRENT_USER keywords */ /* Sort this file with "sort -b +1 +0" */ @@ -443,4 +447,9 @@ {"WORK", KW_WORK}, {"WRITE", KW_WRITE}, {"YEAR", KW_YEAR}, - {"YEARDAY", KW_YEARDAY} + {"YEARDAY", KW_YEARDAY}, + {"SKIP", KW_SKIP}, + {"CURRENT_CONNECTION", KW_CURRENT_CONNECTION}, + {"CURRENT_ROLE", KW_CURRENT_ROLE}, + {"CURRENT_TRANSACTION", KW_CURRENT_TRANSACTION}, + {"CURRENT_USER", KW_CURRENT_USER} Index: par.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/par.cpp,v retrieving revision 1.64 retrieving revision 1.65 diff -b -U3 -r1.64 -r1.65 --- par.cpp 29 Mar 2007 07:16:16 -0000 1.64 +++ par.cpp 29 Jul 2007 07:30:42 -0000 1.65 @@ -362,6 +362,8 @@ return NULL; } + if (! gpreGlob.sw_no_qli) + { for (; symbol; symbol = symbol->sym_homonym) { switch (symbol->sym_type) @@ -421,6 +423,7 @@ break; } } + } cur_statement = NULL; CPR_token(); Index: rmc.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/rmc.cpp,v retrieving revision 1.3 retrieving revision 1.4 diff -b -U3 -r1.3 -r1.4 --- rmc.cpp 1 Apr 2007 13:04:13 -0000 1.3 +++ rmc.cpp 29 Jul 2007 07:30:42 -0000 1.4 @@ -22,6 +22,9 @@ // Contributor(s): ______________________________________. // New module by Stephen W. Boyd 31.Aug.2006 // +// Modified by Stephen W. Boyd 31.May.2007 +// Added support for ISC_TIME & ISC_DATE values +// #include "firebird.h" #include <stdio.h> #include "../jrd/common.h" @@ -710,19 +713,67 @@ value = gen_name(temp, reference->ref_source, true); else value = reference->ref_value; - if (!reference->ref_master || (reference->ref_flags & REF_literal)) { + if (!reference->ref_master || (reference->ref_flags & REF_literal)) + { if ((reference->ref_field->fld_dtype == dtype_date) && (strlen(gpreGlob.sw_cob_dformat) != 0)) + { sprintf(output_buffer, "%sCALL \"rmc_dtoc\" USING %s, %s, \"%s\"\n", names[COLUMN], variable, value, gpreGlob.sw_cob_dformat); - else { + } + else + { + if ((reference->ref_field->fld_dtype == dtype_sql_date) && + (strlen(gpreGlob.sw_cob_dformat) != 0)) + { + sprintf(output_buffer, + "%sCALL \"rmc_dtoc\" USING ISC-TEMP-QUAD, %s, \"%s\"\n", + names[COLUMN], + value, + gpreGlob.sw_cob_dformat); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sMOVE ISC-TEMP-QUAD-HIGH TO %s\n", + names[COLUMN], + variable); + } + else + { + if ((reference->ref_field->fld_dtype == dtype_sql_time) && + (strlen(gpreGlob.sw_cob_dformat) != 0)) + { + sprintf(output_buffer, + "%sCALL \"rmc_dtoc\" USING ISC-TEMP-QUAD, %s, \"%s\"\n", + names[COLUMN], + value, + gpreGlob.sw_cob_dformat); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sMOVE ISC-TEMP-QUAD-LOW TO %s\n", + names[COLUMN], + variable); + } + else + { + if (reference->ref_field->fld_dtype == dtype_cstring) + { + sprintf(output_buffer, + "%sCALL \"rmc_stoc\" USING %s GIVING %s\n", + names[COLUMN], + value, + variable); + } + else + { sprintf(output_buffer, "%sMOVE %s TO %s\n", names[COLUMN], value, variable); - switch (reference->ref_field->fld_dtype) { + + switch (reference->ref_field->fld_dtype) + { case dtype_short: case dtype_long: RMC_print_buffer(output_buffer, false); @@ -744,7 +795,11 @@ } } } - else { + } + } + } + else + { sprintf(output_buffer, "%sIF %s < 0 THEN\n", names[COLUMN], value); RMC_print_buffer(output_buffer, false); @@ -776,13 +831,15 @@ const gpre_fld* field = source->ref_field; gen_name(s, source, true); - if (field->fld_array_info) { + if (field->fld_array_info) + { source->ref_value = reference->ref_value; gen_get_or_put_slice(action, source, true); return; } - if ((field->fld_dtype == dtype_date) && (strlen(gpreGlob.sw_cob_dformat) != 0)) { + if ((field->fld_dtype == dtype_date) && (strlen(gpreGlob.sw_cob_dformat) != 0)) + { sprintf(output_buffer, "%sCALL \"rmc_ctod\" USING %s, %s, \"%s\"\n", names[COLUMN], @@ -791,8 +848,61 @@ gpreGlob.sw_cob_dformat); RMC_print_buffer(output_buffer, false); } - else { - switch (field->fld_dtype) { + else + { + if ((field->fld_dtype == dtype_sql_date) && (strlen(gpreGlob.sw_cob_dformat) != 0)) + { + sprintf(output_buffer, + "%sMOVE ZERO TO ISC-TEMP-QUAD-LOW\n", + names[COLUMN]); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sMOVE %s TO ISC-TEMP-QUAD-HIGH\n", + names[COLUMN], + s); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sCALL \"rmc_ctod\" USING %s, ISC-TEMP-QUAD, \"%s\"\n", + names[COLUMN], + reference->ref_value, + gpreGlob.sw_cob_dformat); + RMC_print_buffer(output_buffer, false); + } + else + { + if ((field->fld_dtype == dtype_sql_time) && (strlen(gpreGlob.sw_cob_dformat) != 0)) + { + sprintf(output_buffer, + "%sMOVE ZERO TO ISC-TEMP-QUAD-HIGH\n", + names[COLUMN]); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sMOVE %s TO ISC-TEMP-QUAD-LOW\n", + names[COLUMN], + s); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sCALL \"rmc_ctod\" USING %s, ISC-TEMP-QUAD, \"%s\"\n", + names[COLUMN], + reference->ref_value, + gpreGlob.sw_cob_dformat); + RMC_print_buffer(output_buffer, false); + } + else + { + if (field->fld_dtype == dtype_cstring) + { + sprintf(output_buffer, + "%sCALL \"rmc_ctos\" USING %s GIVING %s\n", + names[COLUMN], + s, + reference->ref_value); + RMC_print_buffer(output_buffer, false); + } + else + { + switch (field->fld_dtype) + { case dtype_short: case dtype_long: sprintf(output_buffer, @@ -817,10 +927,14 @@ names[COLUMN], s, reference->ref_value); RMC_print_buffer(output_buffer, false); } + } + } + } // Pick up NULL value if one is there - if (reference = reference->ref_null) { + if (reference = reference->ref_null) + { sprintf(output_buffer, "%sMOVE %s TO %s\n", names[COLUMN], gen_name(s, reference, true), reference->ref_value); @@ -839,11 +953,14 @@ { TEXT s[MAX_REF_SIZE]; - for (; reference; reference = reference->ref_next) { + for (; reference; reference = reference->ref_next) + { if (!reference->ref_value) continue; + gen_name(s, reference, true); - if ((reference->ref_field->fld_dtype == dtype_date) && (strlen(gpreGlob.sw_cob_dformat) != 0)) { + if ((reference->ref_field->fld_dtype == dtype_date) && (strlen(gpreGlob.sw_cob_dformat) != 0)) + { sprintf(output_buffer, "%sCALL \"rmc_ctod\" USING %s, %s, \"%s\"\n", names[COLUMN], @@ -852,9 +969,62 @@ gpreGlob.sw_cob_dformat); RMC_print_buffer(output_buffer, false); } - else { + else + { + if ((reference->ref_field->fld_dtype == dtype_sql_date) && (strlen(gpreGlob.sw_cob_dformat) != 0)) + { + sprintf(output_buffer, + "%sMOVE ZERO TO ISC-TEMP-QUAD-LOW\n", + names[COLUMN]); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sMOVE %s TO ISC-TEMP-QUAD-HIGH\n", + names[COLUMN], + s); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sCALL \"rmc_ctod\" USING %s, ISC-TEMP-QUAD, \"%s\"\n", + names[COLUMN], + reference->ref_value, + gpreGlob.sw_cob_dformat); + RMC_print_buffer(output_buffer, false); + } + else + { + if ((reference->ref_field->fld_dtype == dtype_sql_time) && (strlen(gpreGlob.sw_cob_dformat) != 0)) + { + sprintf(output_buffer, + "%sMOVE ZERO TO ISC-TEMP-QUAD-HIGH\n", + names[COLUMN]); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sMOVE %s TO ISC-TEMP-QUAD-LOW\n", + names[COLUMN], + s); + RMC_print_buffer(output_buffer, false); + sprintf(output_buffer, + "%sCALL \"rmc_ctod\" USING %s, ISC-TEMP-QUAD, \"%s\"\n", + names[COLUMN], + reference->ref_value, + gpreGlob.sw_cob_dformat); + RMC_print_buffer(output_buffer, false); + } + else + { + if (reference->ref_field->fld_dtype == dtype_cstring) + { + sprintf(output_buffer, + "%sCALL \"rmc_ctos\" USING %s GIVING %s\n", + names[COLUMN], + s, + reference->ref_value); + RMC_print_buffer(output_buffer, false); + } + else + { if ((reference->ref_field->fld_dtype == dtype_short) || - (reference->ref_field->fld_dtype == dtype_long)) { + (reference->ref_field->fld_dtype == dtype_long)) + { sprintf(output_buffer, "%sCALL \"rmc_ctob\" USING %s GIVING %s\n", names[COLUMN], @@ -867,6 +1037,9 @@ RMC_print_buffer(output_buffer, false); } } + } + } + } } @@ -974,6 +1147,15 @@ fprintf(gpreGlob.out_file, "%sPIC X(%d)", names[COLUMN], strlen(gpreGlob.sw_cob_dformat)); break; + case dtype_sql_date: + case dtype_sql_time: + if (strlen(gpreGlob.sw_cob_dformat) == 0) + fprintf(gpreGlob.out_file, "%sPIC S9(10)%s", names[COLUMN], USAGE_BINARY4); + else { + fprintf(gpreGlob.out_file, "%sPIC X(%d)", names[COLUMN], strlen(gpreGlob.sw_cob_dformat)); + } + break; + case dtype_blob: fprintf(gpreGlob.out_file, "%sPIC S9(19)%s", names[COLUMN], USAGE_BINARY8); break; @@ -1560,6 +1742,9 @@ printa(COLUMN8, false, "01 %s PIC S9(10) %s EXTERNAL.", names[ISC_SQLCODE], USAGE_BINARY4); + printa(COLUMN8, false, "01 ISC-TEMP-QUAD."); + printa(COLUMN12, false, "03 ISC-TEMP-QUAD-HIGH PIC S9(10) %s.", USAGE_BINARY4); + printa(COLUMN12, false, "03 ISC-TEMP-QUAD-LOW PIC S9(10) %s.", USAGE_BINARY4); bool all_static = true; bool all_extern = true; @@ -3824,6 +4009,13 @@ strcat(p, "."); break; + case dtype_sql_date: + case dtype_sql_time: + strcpy(p, "PIC S9(10)"); + strcat(p, USAGE_BINARY4); + strcat(p, "."); + break; + case dtype_quad: sprintf(p, "PIC S9(%d)", 19 + field->fld_array->fld_scale); while (*p) @@ -4000,6 +4192,16 @@ (field->fld_dtype == dtype_real) ? USAGE_BINARY4 : USAGE_BINARY8); break; + case dtype_sql_date: + case dtype_sql_time: + fprintf(gpreGlob.out_file, + "%s03 %s%d PIC S9(10) %s.\n", + COLUMN12, + names[isc_a_pos], + reference->ref_ident, + USAGE_BINARY4); + break; + default: { TEXT s[ERROR_LENGTH]; Index: sqe.cpp =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/sqe.cpp,v retrieving revision 1.44 retrieving revision 1.45 diff -b -U3 -r1.44 -r1.45 --- sqe.cpp 1 Jun 2007 16:05:02 -0000 1.44 +++ sqe.cpp 29 Jul 2007 07:30:42 -0000 1.45 @@ -35,6 +35,9 @@ // TMN (Mike Nordell) 11.APR.2001 - Reduce compiler warnings // // 2006.10.12 Stephen W. Boyd - Added support for FOR UPDATE WITH LOCK +// 2007.05.23 Stephen W. Boyd - Added support for FIRST / SKIP clauses +// 2007.06.15 Stephen W. Boyd - Added support for CURRENT_CONNECTION, CURRENT_ROLE, +// CURRENT_TRANSACTION and CURRENT_USER context variables. // //____________________________________________________________ // @@ -2663,6 +2666,46 @@ } +bool SQE_resolve_fields(GPRE_NOD fields, + gpre_req* request, + gpre_rse* selection) +{ + bool aggregate = false; + + gpre_nod** ptr = fields->nod_arg; + int count = fields->nod_count; + for (int i = 0; i < count; i++) + { + gpre_nod* node = ptr[i]; + if (node->nod_type == nod_asterisk) { + const int old_count = count; + fields = explode_asterisk(fields, i, selection); + count = fields->nod_count; + i += count - old_count; + ptr = fields->nod_arg; + } + else { + aggregate |= SQE_resolve(node, NULL, selection); + pair(node, 0); + switch (node->nod_type) + { + case nod_agg_count: + case nod_agg_max: + case nod_agg_min: + case nod_agg_average: + case nod_agg_total: + if ((node->nod_arg[1]) && + (request->req_database->dbb_flags & DBB_v3)) + { + selection->rse_reduced = + MSC_unary(nod_sort, node->nod_arg[1]); + } + break; + } + } + } + return aggregate; +} //____________________________________________________________ // // Parse the SQL equivalent of a record selection expression -- @@ -2708,39 +2751,9 @@ bool aggregate = false; - if (fields) { - gpre_nod** ptr = fields->nod_arg; - count = fields->nod_count; - for (int i = 0; i < count; i++) - { - gpre_nod* node = *(ptr + i); - if (node->nod_type == nod_asterisk) { - const int old_count = count; - fields = explode_asterisk(fields, i, select); - count = fields->nod_count; - i += count - old_count; - ptr = fields->nod_arg; - } - else { - aggregate |= SQE_resolve(node, 0, select); - pair(node, 0); - switch (node->nod_type) { - case nod_agg_count: - case nod_agg_max: - case nod_agg_min: - case nod_agg_average: - case nod_agg_total: - if ((node->nod_arg[1]) && - (request->req_database->dbb_flags & DBB_v3)) - { - select->rse_reduced = - MSC_unary(nod_sort, node->nod_arg[1]); - } - break; - } - } - } - } + if (fields) + aggregate = SQE_resolve_fields(fields, request, select); + select->rse_fields = fields; if (distinct) select->rse_reduced = fields; @@ -2816,6 +2829,21 @@ { assert_IS_REQ(request); + // Handle FIRST and SKIP clauses + gpre_nod* rse_first = NULL; + if (MSC_match(KW_FIRST)) + { + rse_first = MSC_node(nod_list, 1); + rse_first->nod_arg[0] = SQE_value(request, false, NULL, NULL); + } + + gpre_nod* rse_skip = NULL; + if (MSC_match(KW_SKIP)) + { + rse_skip = MSC_node(nod_list, 1); + rse_skip->nod_arg[0] = SQE_value(request, false, NULL, NULL); + } + // Handle the ALL and DISTINCT options const bool distinct = (!MSC_match(KW_ALL) && MSC_match(KW_DISTINCT)); @@ -2829,14 +2857,21 @@ // If this is not a declare cursor statement and an INTO list is present, // parse it. - gpre_nod* into_list; + gpre_nod* into_list = NULL; if (!(request->req_flags & REQ_sql_declare_cursor)) into_list = (MSC_match(KW_INTO)) ? SQE_list(SQE_variable, request, false) : NULL; - else - into_list = NULL; gpre_rse* select = par_rse(request, s_list, distinct); + + if (rse_first) + SQE_resolve_fields(rse_first, request, select); + select->rse_sqlfirst = rse_first; + + if (rse_skip) + SQE_resolve_fields(rse_skip, request, select); + select->rse_sqlskip = rse_skip; + if (select->rse_into = into_list) select->rse_flags |= RSE_singleton; @@ -3049,7 +3084,7 @@ return node; } -// Check for DATE constants +// Check for context variables // ** Begin date/time/timestamp * if (MSC_match(KW_CURRENT_DATE)) return MSC_node(nod_current_date, 0); @@ -3057,8 +3092,17 @@ return MSC_node(nod_current_time, 0); else if (MSC_match(KW_CURRENT_TIMESTAMP)) return MSC_node(nod_current_timestamp, 0); - // End date/time/timestamp * + else if (MSC_match(KW_CURRENT_CONNECTION)) + return MSC_node(nod_current_connection, 0); + else if (MSC_match(KW_CURRENT_ROLE)) + return MSC_node(nod_current_role, 0); + else if (MSC_match(KW_CURRENT_TRANSACTION)) + return MSC_node(nod_current_transaction, 0); + else if (MSC_match(KW_CURRENT_USER)) + return MSC_node(nod_user_name, 0); + +// End context variables * // Check for SQL II defined functions Index: words.h =================================================================== RCS file: /cvsroot/firebird/firebird2/src/gpre/words.h,v retrieving revision 1.6 retrieving revision 1.7 diff -b -U3 -r1.6 -r1.7 --- words.h 27 May 2005 22:42:16 -0000 1.6 +++ words.h 29 Jul 2007 07:30:42 -0000 1.7 @@ -15,6 +15,9 @@ * * All Rights Reserved. * Contributor(s): ______________________________________. + * + * 2007.05.23 Stephen W. Boyd - Added SKIP keyword + * 2007.06.15 Stephen W. Boyd - Added CURRENT_CONNECTION, CURRENT_ROLE, */ typedef enum kwwords { KW_none = 0, @@ -311,5 +314,10 @@ KW_WARNING, KW_WEEKDAY, KW_WHENEVER, KW_WIDTH, KW_WITH, KW_WORK, KW_WRITE, KW_YEAR, KW_YEARDAY, + KW_SKIP, + KW_CURRENT_CONNECTION, + KW_CURRENT_ROLE, + KW_CURRENT_TRANSACTION, + KW_CURRENT_USER, KW_max } KWWORDS; |