/* * PROGRAM: Language Preprocessor * MODULE: gpre.h * DESCRIPTION: Common header modules * * The contents of this file are subject to the Interbase Public * License Version 1.0 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy * of the License at http://www.Inprise.com/IPL.html * * Software distributed under the License is distributed on an * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express * or implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code was created by Inprise Corporation * and its predecessors. Portions created by Inprise Corporation are * Copyright (C) Inprise Corporation. * * All Rights Reserved. * Contributor(s): ______________________________________. * * Revision 1.3 2000/11/27 09:26:13 fsg * Fixed bugs in gpre to handle PYXIS forms * and allow edit.e and fred.e to go through * gpre without errors (and correct result). * * This is a partial fix until all * PYXIS datatypes are adjusted in frm_trn.c * * removed some compiler warnings too * * Revision 1.2 2000/11/16 15:54:29 fsg * Added new switch -verbose to gpre that will dump * parsed lines to stderr * * Fixed gpre bug in handling row names in WHERE clauses * that are reserved words now (DATE etc) * (this caused gpre to dump core when parsing tan.e) * * Fixed gpre bug in handling lower case table aliases * in WHERE clauses for sql dialect 2 and 3. * (cause a core dump in a test case from C.R. Zamana) * * 2002.02.15 Sean Leyne - Code Cleanup, removed obsolete ports: * - "IMP" and "HP9000 s300" * * 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "UNIXWARE" port * 2002.10.27 Sean Leyne - Code Cleanup, removed obsolete "Ultrix" port * * 2002.10.28 Sean Leyne - Completed removal of obsolete "DGUX" port * 2002.10.28 Sean Leyne - Completed removal of obsolete "SGI" port * 2002.10.28 Sean Leyne - Completed removal of obsolete "HP700" port * * 2002.10.30 Sean Leyne - Removed support for obsolete "PC_PLATFORM" define * * Stephen W. Boyd - Added support for new features. */ #ifndef GPRE_GPRE_H #define GPRE_GPRE_H #include // offsetof #include #include "dyn_consts.h" #include "../jrd/common.h" #include "../jrd/ibase.h" #include "../jrd/constants.h" #ifdef GPRE_FORTRAN #if defined AIX || defined AIX_PPC || defined __sun #ifndef BOOT_BUILD #define FTN_BLK_DATA #endif #endif #endif static const char* const CONST_STR = "const "; const int MAX_SYM_SIZE = 512; // max length of symbol + terminator const int NAME_SIZE = 32; const int MAX_CURSOR_SIZE = 64; const int MAX_REF_SIZE = 32; // references are generated by gpre const int ERROR_LENGTH = 256; const int MAX_DATABASES = 32; const int MAX_EVENT_SIZE = 16; // event names use 15 chars from old docs. // Values for SQL dialects. #include "../dsql/sqlda_pub.h" // Language options enum lang_t { lang_undef, lang_internal, lang_pascal, lang_fortran, //lang_epascal, lang_cobol, lang_c, lang_ada, lang_cxx, lang_scxx, lang_cplusplus, lang_cpp, lang_internal_cxx }; #ifdef GPRE_COBOL // Cobol dialect options enum cob_t { cob_vms, // VMS cob_ansi, // ANSI-85 cob_rmc // RM/Cobol }; #endif //___________________________________________________________________ // Test if input language is cpp based. // // The lang_internal is used to compile some internal stuff without // reference to a database. Previously it was based on lang_c (but even then // if you look carefully there are some areas where lang_c is specifically // treated and lang_internal would be ignored). // Now the base language used for lang_internal is cpp, so we have this // inline function to tell if language is cpp. // Internally the sw_language variable is set to lang_cxx for the // c++ source files, cxx, cpp, cplusplus, so we only need to test lang_cxx // and lang_internal. // bool isLangCpp(lang_t lang); #ifdef GPRE_COBOL bool isAnsiCobol(cob_t dialect); #endif // Structure used by Fortran to determine whether or not // an array has been declared in a subroutine. #ifdef GPRE_FORTRAN struct adl { ULONG adl_gds_ident; // Identifier of array for which Gpre has // generated a declaration in main or a subroutine adl* adl_next; // Next declared array identifier }; const size_t ADL_LEN = sizeof(adl); // database block data, for generating block data section in fussy fortran struct dbd { enum {dbd_size = 128}; TEXT dbd_name[dbd_size]; // database name }; #endif // Dimension block, used for arrays // Note: this structure is being phased out. Please use the // repeating tail on the ARY structure instead struct dim { int dim_number; // Dimension number i (i=1 to n) SLONG dim_lower; // Lower bound SLONG dim_upper; // Upper bound dim* dim_next; // Information for dimension i+1 dim* dim_previous; // Information for dimension i-1 }; const size_t DIM_LEN = sizeof(dim); struct gpre_file { SLONG fil_length; // File length in pages SLONG fil_start; // Starting page TEXT *fil_name; // File name gpre_file* fil_next; // next file USHORT fil_shadow_number; // shadow number if part of shadow USHORT fil_flags; }; enum fil_flags_vals { FIL_manual = 1, // Manual shadow //FIL_raw = 2, // On raw device; unused FIL_conditional = 4 // Conditional shadow }; const size_t FIL_LEN = sizeof(gpre_file); // filter block struct gpre_filter { TEXT *fltr_name; const TEXT *fltr_entry_point; const TEXT *fltr_module_name; SSHORT fltr_input_type; SSHORT fltr_output_type; }; const size_t FLTR_LEN = sizeof(gpre_filter); // General Syntax node, produced by parser // CVC: several node types are unused!!! enum nod_t { nod_nothing = 0, nod_field = 1, nod_literal, nod_value, nod_and, nod_or, nod_not, nod_eq, nod_equiv, nod_ne, nod_ge, nod_le, nod_gt, nod_lt, nod_containing, nod_matches, nod_any, nod_unique, nod_plus, nod_times, nod_divide, nod_minus, nod_negate, //nod_msg, //nod_for, //nod_send, //nod_receive, //nod_block, //nod_select, //nod_boolean, nod_projection, nod_sort, nod_store, nod_modify, nod_erase, //nod_if, nod_assignment, //nod_rse, //nod_first, //nod_relation, //nod_end, //nod_label, //nod_leave, //nod_loop, nod_max, nod_min, nod_count, nod_total, nod_average, nod_list, nod_deferred, nod_missing, nod_between, nod_union, //nod_map, nod_starting, nod_like, nod_agg_count, nod_agg_max, nod_agg_min, nod_agg_total, nod_agg_average, nod_aggregate, nod_from, nod_null, nod_asterisk, nod_map_ref, nod_user_name, nod_upcase, nod_sleuth, nod_event_init, nod_udf, nod_array, nod_index, nod_via, nod_join_inner, nod_join_left, nod_join_right, nod_join_full, nod_join, nod_concatenate, nod_cast, nod_dom_value, nod_ansi_any, nod_gen_id, //nod_set_generator, nod_merge, nod_plan_expr, nod_plan_item, nod_natural, nod_index_order, nod_ansi_all, nod_extract, nod_current_date, nod_current_time, nod_current_timestamp, nod_lowcase, nod_nullif, nod_current_connection, nod_current_role, nod_current_transaction, nod_coalesce, nod_case, nod_case1, nod_substring, nod_LASTNOD // Leave this debugging gpre_nod last }; struct gpre_nod { nod_t nod_type; // node type USHORT nod_count; // number of sub-items gpre_nod* nod_arg[1]; // argument }; inline size_t NOD_LEN(const size_t cnt) { return sizeof(gpre_nod) + (cnt ? cnt - 1 : 0) * sizeof(gpre_nod*); } struct set_dialect { USHORT sdt_dialect; // Dialect value as specified by SET stmt }; const size_t SDT_LEN = sizeof(set_dialect); // Set generator block struct set_gen { TEXT* sgen_name; USHORT sgen_dialect; SLONG sgen_value; SINT64 sgen_int64value; }; const size_t SGEN_LEN = sizeof(set_gen); // STRing block - holds a null terminated string typedef struct str { TEXT str_string[1]; // pretty simple, no? } *STR; inline size_t STR_LEN(const size_t size) { return sizeof(str) + size; } // SQL WHENEVER BLOCK enum swe_condition_vals { SWE_error, SWE_warning, SWE_not_found, SWE_max }; struct swe { swe* swe_next; // Next in chain swe_condition_vals swe_condition; // Condition USHORT swe_length; // Length of label TEXT swe_label[1]; // Label }; // Text block struct gpre_txt { ULONG txt_position; USHORT txt_length; }; const size_t TXT_LEN = sizeof(gpre_txt); // User name -- used for SQL GRANT/REVOKE struct gpre_usn { gpre_usn* usn_next; const SCHAR* usn_name; USHORT usn_dyn; // describes the type of user via a dyn-verb, // i.e. gds__dyn_grant_user/view/proc/trig }; const size_t USN_LEN = sizeof(gpre_usn); // value block, used to store a set of values struct gpre_value { gpre_value* val_next; // next value in list const TEXT* val_value; // value }; const size_t VAL_LEN = sizeof(gpre_value); // Array information block. Used to hold info about an array field. // Note: the dimension (dim) block used to hold dimension information. // The preferred mechanism is the repeating tail on the array block. struct ary { USHORT ary_dtype; // data type of array int ary_dimension_count; // Number of dimensions in this array dim* ary_dimension; // Linked list of range info for each dimension SLONG ary_size; // Size of the array ULONG ary_ident; // Array identifier bool ary_declared; // True if a declaration already was generated struct ary_repeat { SLONG ary_lower; SLONG ary_upper; } ary_rpt[MAX_ARRAY_DIMENSIONS]; }; // CVC: The count is ignored, the array is hardcoded at 16. const size_t ARY_LEN = sizeof(ary); // Trigger block // Note: This structure will need expansion later. Currently its // use is to create a trigger for CHECK constraints which always // abort on error struct gpre_trg { //str* trg_name; // unused USHORT trg_type; // Type of trigger str* trg_source; // source for trigger gpre_nod* trg_boolean; // boolean expression, for trigger str* trg_message; // Message the trigger prints }; const size_t TRG_LEN = sizeof(gpre_trg); // Beware the numbers cannot change enum gpre_trg_types { PRE_STORE_TRIGGER = 1, //POST_STORE_TRIGGER = 2, PRE_MODIFY_TRIGGER = 3, POST_MODIFY_TRIGGER = 4, //PRE_ERASE_TRIGGER = 5, POST_ERASE_TRIGGER = 6 }; // Linked list stack stuff struct gpre_lls { gpre_nod* lls_object; // object on stack gpre_lls* lls_next; // next item on stack }; const size_t LLS_LEN = sizeof(gpre_lls); // Constraint block, used to hold information about integrity constraints struct cnstrt { str* cnstrt_name; // Name of constraint USHORT cnstrt_type; // Type of constraint gpre_lls* cnstrt_fields; // list of fields USHORT cnstrt_fkey_def_type; // extended foreign key definition str* cnstrt_referred_rel; // referred relation, if foreign key gpre_lls* cnstrt_referred_fields; // optional list of fields from referred relation cnstrt* cnstrt_next; // next contraint for field or relation gpre_txt* cnstrt_text; // source for CHECK constraints gpre_nod* cnstrt_boolean; // boolean expression, for CHECK constraints USHORT cnstrt_flags; // see below }; const size_t CNSTRT_LEN = sizeof(cnstrt); // Values for cnstrt_fkey_def_type enum cnstrt_fkey_def_type_vals { REF_UPDATE_ACTION = 0x0001, REF_UPD_CASCADE = 0x0002, REF_UPD_SET_DEFAULT = 0x0004, REF_UPD_SET_NULL = 0x0008, REF_UPD_NONE = 0x0010, REF_UPDATE_MASK = 0x001E, REF_DELETE_ACTION = 0x0020, REF_DEL_CASCADE = 0x0040, REF_DEL_SET_DEFAULT = 0x0080, REF_DEL_SET_NULL = 0x0100, REF_DEL_NONE = 0x0200, REF_DELETE_MASK = 0x03C0 }; // Values for cnstrt_type enum cnstrt_type_vals { CNSTRT_NOT_NULL = 1, CNSTRT_PRIMARY_KEY, CNSTRT_UNIQUE, CNSTRT_FOREIGN_KEY, CNSTRT_CHECK }; // Values for cnstrt_flags enum cnstrt_flags_vals { //CNSTRT_DEFERRABLE = 1, //CNSTRT_INITIALLY_DEFERRED = 2, CNSTRT_delete = 4 }; // Grant/revoke block typedef struct prv { USHORT prv_privileges; // holds privileges being granted or revoked const SCHAR* prv_username; // user having privileges granted or revoked USHORT prv_user_dyn; // the dyn-verb to be used with prv_username // i.e. gds__dyn_grant_user/proc/trig/view str* prv_relation; // relation on which we're doing grant/revoke USHORT prv_object_dyn; // the dyn-verb to be used with prv_relation // i.e. gds__dyn_rel/proc_name gpre_lls* prv_fields; // fields on which we're doing grant/revoke prv* prv_next; // next grant/revoke block (with different user) } *PRV; const size_t PRV_LEN = sizeof(prv); enum priv_types { PRV_no_privs = 0, // no privileges being granted or revoked PRV_select = 1, // select privilege being granted or revoked PRV_insert = 2, // insert privilege being granted or revoked PRV_delete = 4, // delete privilege being granted or revoked PRV_update = 8, // update privilege being granted or revoked PRV_execute = 16, // execute privilege being granted or revoked PRV_references = 32, // reference privilege PRV_grant_option= 64, // privilege to grant privileges being granted PRV_all = 128 // all privileges being granted/revoked }; // statistic block. Used for all statistics commands typedef struct sts { str* sts_name; // object name USHORT sts_flags; // Miscellaneous flags } *STS; const size_t STS_LEN = sizeof(sts); enum sts_flags_vals { STS_index = 1 // Object is an index }; // Computed field block typedef struct cmpf { gpre_txt* cmpf_text; // source for computed field gpre_nod* cmpf_boolean; // expression, for computed field } *CMPF; const size_t CMPF_LEN = sizeof(cmpf); // ***************** end of tree top ********************** // Forward declarations struct gpre_ctx; struct gpre_fld; struct gpre_rel; class gpre_req; class ref; enum act_t { ACT_any, ACT_alter_database, ACT_alter_domain, ACT_alter_index, ACT_alter_table, ACT_at_end, //ACT_average, ACT_b_declare, ACT_basedon, ACT_blob_cancel, ACT_blob_close, ACT_blob_create, ACT_blob_for, ACT_blob_handle, ACT_blob_open, //ACT_block_data, ACT_close, ACT_commit, ACT_commit_retain_context, ACT_create_database, ACT_create_domain, ACT_create_generator, ACT_create_index, ACT_create_shadow, ACT_create_table, ACT_create_view, ACT_cursor, ACT_database, ACT_declare_filter, ACT_declare_udf, //ACT_delete, ACT_disconnect, ACT_drop_database, ACT_drop_domain, ACT_drop_filter, ACT_drop_index, ACT_drop_shadow, ACT_drop_table, ACT_drop_udf, ACT_drop_view, ACT_dyn_close, ACT_dyn_cursor, //ACT_dyn_declare, ACT_dyn_describe, ACT_dyn_describe_input, ACT_dyn_execute, ACT_dyn_fetch, ACT_dyn_grant, ACT_dyn_immediate, ACT_dyn_insert, ACT_dyn_open, ACT_dyn_prepare, ACT_dyn_revoke, ACT_dyn_statement, ACT_endblob, ACT_e_declare, ACT_enderror, ACT_endfor, ACT_endmodify, ACT_endstore, ACT_endstore_special, ACT_erase, ACT_event_init, ACT_event_wait, ACT_fetch, ACT_finish, ACT_function, ACT_for, ACT_get_segment, ACT_hctef, ACT_insert, ACT_loop, //ACT_max, //ACT_min, ACT_modify, ACT_on_error, ACT_open, ACT_prepare, ACT_procedure, ACT_put_segment, ACT_ready, ACT_release, ACT_rfinish, ACT_rollback, ACT_rollback_retain_context, ACT_routine, ACT_segment, ACT_segment_length, ACT_s_end, ACT_s_fetch, ACT_s_start, ACT_select, ACT_start, ACT_statistics, ACT_store, ACT_store2, //ACT_total, ACT_update, ACT_variable, ACT_clear_handles, ACT_type_number, // let's avoid confusion with act.act_type ACT_noop, ACT_get_slice, ACT_put_slice, ACT_sql_dialect, ACT_LASTACT // leave this debugging ACT last }; // Action block, used to make action points in source struct act { SLONG act_position; // position in input stream SLONG act_length; // length to be commented out act_t act_type; // type of action act* act_next; // next action in request act* act_rest; // remaining actions in module act* act_error; // on-error action (maybe) act* act_pair; // begin/end action (maybe) gpre_req* act_request; // parent request ref* act_object; // dependent on action type swe* act_whenever; // SQL whenever blocks USHORT act_flags; // flags that affect the action USHORT act_count; // used to hold begin/end count for routines }; enum act_flags_vals { ACT_mark = 1, // action is mark only - no comment ACT_first = 2, // action is first on line. No FTN continuation ACT_break = 4, // module boundary break ACT_sql = 8, // action is SQL statement ACT_decl = 16, // action is a PASCAL forward or extern routine ACT_main = 32, // action is the main routine in the program/module ACT_back_token = 128 // end of action marked by prior token }; const size_t ACT_LEN = sizeof(act); // Symbol block, also used for hash table enum sym_t { SYM_keyword, SYM_context, SYM_database, SYM_relation, SYM_field, SYM_variable, // it's tested in sql.cpp but it's never activated SYM_stream, SYM_cursor, SYM_delimited_cursor, SYM_index, SYM_blob, //SYM_statement, SYM_dyn_cursor, SYM_type, SYM_udf, SYM_username, SYM_procedure, SYM_charset, SYM_collate, SYM_generator, SYM_dummy, SYM_LASTSYM // Leave this debugging sym last }; struct gpre_sym { const char* sym_string; // address of asciz string sym_t sym_type; // symbol type USHORT sym_keyword; // keyword number, if keyword gpre_ctx* sym_object; // general pointer to object gpre_sym* sym_collision; // collision pointer gpre_sym* sym_homonym; // homonym pointer SCHAR sym_name[1]; // space for name, if necessary }; const size_t SYM_LEN = sizeof(gpre_sym); // Blob block. Used for blob calls class blb { public: gpre_req* blb_request; // parent request blb* blb_next; // next blob in request ref* blb_reference; // field reference for blob field gpre_sym* blb_symbol; // Blob context variable ULONG blb_ident; // Blob handle ULONG blb_buff_ident; // Ident of segment buffer ULONG blb_len_ident; // Ident of segment length ULONG blb_seg_length; // Segment length of blob USHORT blb_flags; // Misc and various blobs #ifdef GPRE_FORTRAN USHORT blb_top_label; // fortran label for top of request USHORT blb_btm_label; // fortran label for request exit #endif USHORT blb_bpb_length; // Length of blob parameter block USHORT blb_bpb_ident; // Ident for blob parameter block USHORT blb_type; // Blob type (0 = default segmented) SSHORT blb_const_from_type; // Constant value for subtype from which this blob is to be filtered //TEXT *blb_var_from_type; // Variable whose value is the subtype from which this blob is to be filtered SSHORT blb_const_to_type; // Constant value for subtype to which this blob is to be filtered //TEXT *blb_var_to_type; // Variable whose value is the subtype to which this blob is to be filtered USHORT blb_from_charset; // charset to translate from USHORT blb_to_charset; // charset to translate to UCHAR blb_bpb[24]; }; const size_t BLB_LEN = sizeof(blb); enum blb_flags_vals { //BLB_create = 1, // unused BLB_symbol_released = 2 }; // Reserved relation lock block struct rrl { rrl* rrl_next; // next locked relation UCHAR rrl_lock_level; // lock level (SHARE, PROT, EXC UCHAR rrl_lock_mode; // lock mode (READ/WRITE) gpre_rel* rrl_relation; // relation block }; const size_t RRL_LEN = sizeof(rrl); // forward declarations struct tpb; struct gpre_prc; // Database block, more or less the granddaddy struct gpre_dbb { gpre_dbb* dbb_next; // next database in program gpre_rel* dbb_relations; // relations in database gpre_prc* dbb_procedures; // procedures in database #ifdef GPRE_COBOL USHORT dbb_id; // database id in program #endif USHORT dbb_flags; // Misc flag bytes gpre_sym* dbb_name; // database name FB_API_HANDLE dbb_handle; // OUR db handle FB_API_HANDLE dbb_transaction; // default transaction rrl* dbb_rrls; // temporary list of relation locks const tpb* dbb_tpbs; // real tpbs for this db const TEXT* dbb_filename; const TEXT* dbb_runtime; const TEXT* dbb_c_user; // compiletime user name const TEXT* dbb_c_password; // compiletime password const TEXT* dbb_c_sql_role; // compiletime SQL role const TEXT* dbb_r_user; // runtime user name const TEXT* dbb_r_password; // runtime password const TEXT* dbb_r_sql_role; // runtime SQL role const TEXT* dbb_c_lc_messages; // compiletime user natural language const TEXT* dbb_c_lc_ctype; // compiletime user character set const TEXT* dbb_r_lc_messages; // runtime user natural language const TEXT* dbb_r_lc_ctype; // runtime user character set const TEXT* dbb_def_charset; // charset for CREATE DATABASE SSHORT dbb_know_subtype; // Use a charset subtype id on messages SSHORT dbb_char_subtype; // subtype to use for all SCHAR messages FB_API_HANDLE dbb_field_request; FB_API_HANDLE dbb_flds_request; //FB_API_HANDLE dbb_relation_request; FB_API_HANDLE dbb_procedure_request; FB_API_HANDLE dbb_udf_request; FB_API_HANDLE dbb_trigger_request; FB_API_HANDLE dbb_proc_prms_request; FB_API_HANDLE dbb_proc_prm_fld_request; FB_API_HANDLE dbb_index_request; FB_API_HANDLE dbb_type_request; FB_API_HANDLE dbb_array_request; FB_API_HANDLE dbb_dimension_request; FB_API_HANDLE dbb_domain_request; //FB_API_HANDLE dbb_generator_request; FB_API_HANDLE dbb_view_request; FB_API_HANDLE dbb_primary_key_request; int dbb_scope; // scope of the database handle #ifdef NOT_USED_OR_REPLACED int dbb_allocation; #endif int dbb_pagesize; int dbb_buffercount; ULONG dbb_length; // Length of database in pages, if known gpre_file* dbb_logfiles; #ifdef FLINT_CACHE // In practice, never used. gpre_file* dbb_cache_file; #endif gpre_file* dbb_files; }; const size_t DBB_LEN = sizeof(gpre_dbb); enum dbb_flags_valss { //DBB_no_arrays = 1, // Obsolete: used for databases before IB4 DBB_sqlca = 2, // Created as default for a sqlca DBB_in_trans = 4, // included in this transaction // DBB_drop_log = 8, DBB_log_serial = 16 // DBB_log_default = 32, // DBB_cascade = 64, // only set but not used // DBB_drop_cache = 128, // only set but not used // DBB_create_database = 256, // unused // DBB_v3 = 512 // Database is V3; not supported anymore in FB2.5 }; enum dbb_scope_vals { //DBB_GLOBAL, DBB_EXTERN = 1, DBB_STATIC }; // TPB block struct tpb { tpb* tpb_tra_next; // next TPB for this transaction const tpb* tpb_dbb_next; // next TPB for this database gpre_dbb* tpb_database; // gpre_dbb of this part of the transaction USHORT tpb_length; // length of actual TPB ULONG tpb_ident; // unique part of name for this TPB UCHAR tpb_string[1]; // actual TPB }; inline size_t TPB_LEN(const size_t tpb_string_len) { return sizeof(tpb) + tpb_string_len; } // Procedure structure struct gpre_prc { gpre_sym* prc_symbol; // symbol for relation SSHORT prc_id; // procedure id gpre_sym* prc_owner; // owner of procedure, if any gpre_dbb* prc_database; // parent database gpre_prc* prc_next; // next procedure in database, a linked list is created with // head in database->dbb_procedures, but never used gpre_fld* prc_inputs; // linked list of input parameters gpre_fld* prc_outputs; // linked list of output parameters SSHORT prc_in_count; // count of input parameters SSHORT prc_out_count; // count of output parameters SSHORT prc_flags; // procedure flags }; const size_t PRC_LEN = sizeof(gpre_prc); enum prc_flags_vals { PRC_scanned = 1 }; // Maps used by union and global aggregates struct mel { mel* mel_next; // Next element in map gpre_nod* mel_expr; // Expression //ref* mel_reference; // unused gpre_ctx* mel_context; USHORT mel_position; // Position in map }; struct map { gpre_ctx* map_context; // Pseudo context for map mel* map_elements; // Map elements USHORT map_count; // Number of things in map }; // Record selection expresion syntax node struct gpre_rse { //USHORT rse_type; // node type, UNUSED 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 gpre_nod* rse_into; // list of output variables gpre_nod* rse_union; // if union, list of sub-rses gpre_nod* rse_group_by; // list of grouping fields gpre_nod* rse_plan; // user-specified access plan map* rse_map; // map for aggregates gpre_rse* rse_aggregate; // Aggregate rse nod_t rse_join_type; // Join type USHORT rse_flags; // flags USHORT rse_count; // number of relations gpre_ctx* rse_context[1]; // context block }; inline size_t RSE_LEN(const size_t cnt) { return sizeof(gpre_rse) + (cnt ? cnt - 1 : 0) * sizeof (int*); // CVC: The statement below avoids problem with cnt==0 but at the // cost of a possible run-time memory error. //return offsetof(gpre_rse, rse_context) + nItems * sizeof(int*); } enum rse_flags_vals { RSE_singleton = 1, RSE_for_update = 2, RSE_with_lock = 4 }; // Relation block, not to be confused with siblings or in-laws struct gpre_rel { USHORT rel_id; // relation id gpre_fld* rel_fields; // linked list of known fields gpre_fld* rel_dbkey; // linked list of known fields gpre_sym* rel_symbol; // symbol for relation gpre_dbb* rel_database; // parent database gpre_rel* rel_next; // next relation in database bool rel_meta; // if true, created for a metadata operation gpre_rse* rel_view_rse; gpre_txt* rel_view_text; // source for VIEW definition gpre_sym* rel_owner; // owner of relation, if any cnstrt* rel_constraints; // linked list of constraints defined during a meta operation TEXT *rel_ext_file; // external file name USHORT rel_flags; }; const size_t REL_LEN = sizeof(gpre_rel); enum rel_flags_vals { REL_view_check = 1 // View created with check option }; // Index block. Used for DDL INDEX commands struct gpre_index { gpre_sym* ind_symbol; // index name gpre_rel* ind_relation; // relation name gpre_fld* ind_fields; // list of fields USHORT ind_flags; // Miscellaneous flags }; const size_t IND_LEN = sizeof(gpre_index); enum ind_flags_vals { IND_dup_flag = 1, // if false, duplicates not allowed // IND_meta = 2, // if true, created for a metadata operation; set but not used IND_descend = 4, // if true, a descending-order index IND_active = 8, // activate index IND_inactive = 16 // de-activate index }; // Symbolic names for international text types // (either collation or character set name) // International symbol struct intlsym { gpre_dbb* intlsym_database; gpre_sym* intlsym_symbol; // Hash symbol for intlsym intlsym* intlsym_next; USHORT intlsym_type; // what type of name USHORT intlsym_flags; SSHORT intlsym_ttype; // id of implementation SSHORT intlsym_charset_id; SSHORT intlsym_collate_id; USHORT intlsym_bytes_per_char; TEXT intlsym_name[2]; }; const size_t INTLSYM_LEN = sizeof(intlsym); // values used in intlsym_type enum intlsym_type_vals { INTLSYM_collation = 1, INTLSYM_charset = 2 }; // values used in intlsym_flags // Field block. Fields are what farms and databases are all about struct gpre_fld { USHORT fld_dtype; // data type of field FLD_LENGTH fld_length; // field length in bytes SSHORT fld_scale; // scale factor USHORT fld_id; // field id in meta data USHORT fld_flags; // Misc flags USHORT fld_seg_length; // Segment length for blobs USHORT fld_position; // Field position in relation USHORT fld_precision; // Field precision SSHORT fld_sub_type; // Field sub-type gpre_fld* fld_next; // next field in relation gpre_fld* fld_array; // array element if field is array gpre_rel* fld_relation; // relation gpre_prc* fld_procedure; // procedure gpre_sym* fld_symbol; // symbol for field gpre_sym* fld_global; // symbol for global field ary* fld_array_info; // Dimension and range information about an array field gpre_nod* fld_default_value;// field's default value gpre_txt* fld_default_source; // source for field default value gpre_index* fld_index; // If CREATE TABLE, specifies field with the unique constraint cnstrt* fld_constraints; // linked list of constraints defined during a meta operation intlsym* fld_character_set; // character set for SQL declared field intlsym* fld_collate; // collation clause for SQL declared field cmpf* fld_computed; // computed field definition USHORT fld_char_length; // field length in CHARACTERS SSHORT fld_charset_id; // Field character set id for text SSHORT fld_collate_id; // Field collation id for text SSHORT fld_ttype; // ID of text type's implementation }; const size_t FLD_LEN = sizeof(gpre_fld); enum fld_flags_vals { FLD_blob = 1, FLD_text = 2, //FLD_stream_blob = 4, // unused FLD_dbkey = 8, FLD_not_null = 32, // if CREATE TABLE specifies not null FLD_delete = 64, // if ALTER TABLE specifies delete of field FLD_meta = 128, // if true, created for a metadata operation FLD_national = 256, // uses SQL "NATIONAL" character set FLD_charset = 512, // field has a specific character set FLD_computed = 1024, // field is computed FLD_meta_cstring= 2048 // field is being defined as cstring by the user. }; enum fun_t { FUN_value, FUN_reference, FUN_descriptor, FUN_blob_struct, FUN_scalar_array }; // Port block struct gpre_port { USHORT por_msg_number; // message number within request ULONG por_ident; // ident in source int por_length; // length of port in bytes ref* por_references; // linked list of field references gpre_port* por_next; // next port in request USHORT por_count; // number of items in port }; const size_t POR_LEN = sizeof(gpre_port); // Slice description block struct slc { gpre_req* slc_parent_request; // request for blob id gpre_fld* slc_field; // database array field gpre_nod* slc_array; // user defined array ref* slc_field_ref; // array field reference USHORT slc_dimensions; // dimensions USHORT slc_parameters; // number of parameters struct slc_repeat { gpre_nod* slc_lower; gpre_nod* slc_upper; } slc_rpt[1]; }; inline size_t SLC_LEN(const size_t count) { return sizeof(slc) + sizeof(slc::slc_repeat) * (count ? count - 1 : 0); } // Request block, corresponds to a single JRD request enum req_t { REQ_for, REQ_store, REQ_store2, REQ_insert, REQ_cursor, //REQ_select, // unused REQ_mass_update, REQ_any, //REQ_statistical, // unused REQ_ddl, REQ_create_database, REQ_slice, REQ_ready, REQ_procedure, REQ_set_generator, REQ_LASTREQUEST // Leave this debugging gpre_req last }; class gpre_req { public: req_t req_type; // request type ULONG req_ident; // ident for request handle //USHORT req_act_flag; // activity flag ident, if used; unused int req_length; // blr length of request UCHAR *req_base; // base of blr string during generation UCHAR *req_blr; // raw blr string SCHAR *req_handle; // request handle const TEXT* req_trans; // transaction handle const SCHAR* req_request_level; // request level expression USHORT req_level; // access level USHORT req_count; // number of ports in request USHORT req_internal; // next internal context number //USHORT req_labels; // next available label; unused #ifdef GPRE_FORTRAN USHORT req_top_label; // fortran label for top of request USHORT req_btm_label; // fortran label for request exit #endif gpre_nod* req_node; // request definition tree gpre_dbb* req_database; // database act* req_actions; // actions within request gpre_ctx* req_contexts; // contexts within request gpre_ctx* req_update; // update context for mass insert gpre_req* req_next; // next request in module or metadata action ref* req_values; // host values required ref* req_eof; // eof reference for FOR //ref* req_index; // index variable; unused ref* req_references; // fields referenced in context map* req_map; // map for aggregates, etc gpre_rse* req_rse; // record selection expression gpre_port* req_ports; // linked list of ports gpre_port* req_primary; // primary input or output port gpre_port* req_sync; // synchronization port gpre_port* req_vport; // port to send values in gpre_req* req_routine; // other requests in routine blb* req_blobs; // blobs in request slc* req_slice; // slice for request ref* req_array_references; // array fields referenced in context USHORT req_scope_level; // scope level for SQL subquery parsing USHORT req_in_aggregate; // now processing value expr for aggr USHORT req_in_select_list; // processing select list USHORT req_in_where_clause; // processing where clause USHORT req_in_having_clause; // processing having clause USHORT req_in_order_by_clause; // processing order by clause USHORT req_in_subselect; // processing a subselect clause ULONG req_flags; inline void add_end() { *req_blr++ = isc_dyn_end; } inline void add_byte(const int byte) { *req_blr++ = (SCHAR) (byte); } inline void add_word(const int word) { add_byte(word); add_byte(word >> 8); } inline void add_long(const long lg) { add_word(lg); add_word(lg >> 16); } inline void add_cstring(const char* string) { add_byte(strlen(string)); UCHAR c; while (c = *string++) { add_byte(c); } } }; enum req_flags_vals { REQ_exp_hand = 1, REQ_local = 2, // defined in an included routine REQ_sql_cursor = 1024, // request is an SQL cursor REQ_extend_dpb = 2048, // we need to extend dpb at runtime REQ_sql_declare_cursor = 4096, // request is declare cursor REQ_sql_blob_open = 8192, // request is SQL open blob cursor REQ_sql_blob_create = 16384, // request is SQL create blob cursor REQ_sql_database_dyn = 32768, // request is to generate DYN to add files o database REQ_blr_version4 = 65536 // request must generate blr_version4 }; const size_t REQ_LEN = sizeof(gpre_req); // Context block, used to define context symbols, etc. struct gpre_ctx { USHORT ctx_internal; // internal context number USHORT ctx_scope_level; // scope level for SQL alias subquery scoping gpre_req* ctx_request; // parent request gpre_ctx* ctx_next; // next context in request gpre_sym* ctx_symbol; // symbol for context gpre_rel* ctx_relation; // relation for context TEXT *ctx_alias; // holds SQL alias for passing to engine gpre_prc* ctx_procedure; // procedure for context gpre_nod* ctx_prc_inputs; // procedure input parameters gpre_rse* ctx_stream; // stream for context }; const size_t CTX_LEN = sizeof(gpre_ctx); // Field reference class ref { public: USHORT ref_ident; // identifier USHORT ref_level; // highest level of access USHORT ref_parameter; // parameter in port USHORT ref_id; // id of reference in union gpre_fld* ref_field; // field in question gpre_ctx* ref_context; // context for reference ref* ref_next; // next reference in context gpre_port* ref_port; // associated port ref* ref_source; // source reference for modified field ref* ref_null; // reference for null value ref* ref_master; // master field for null value ref* ref_friend; // value for variable gpre_nod* ref_expr; // expression, if node is expression const TEXT* ref_value; // value string if host language value gpre_value* ref_values; // linked list of values const TEXT* ref_null_value; // value string if host language value UCHAR* ref_sdl; // Raw slice description language for an array UCHAR* ref_sdl_base; // base of sdl string during generation int ref_sdl_length; // sdl length for this reference slc* ref_slice; // Slice, if field referenced is sliced ULONG ref_sdl_ident; // identifier of sdl structure #ifdef GPRE_FORTRAN USHORT ref_offset; // offset of field in port #endif USHORT ref_flags; SSHORT ref_ttype; // Character set type for literals inline void add_byte(const int byte) { *ref_sdl++ = (UCHAR) byte; } inline void add_word(const int word) { add_byte(word); add_byte(word >> 8); } inline void add_long(const long lg) { add_word(lg); add_word(lg >> 16); } }; enum ref_flags_vals { //REF_union = 1, // Pseudo field for union, never set //REF_pseudo = 2, // Other pseudo field (probably for forms), unused REF_null = 4, // Only here cause of related null reference REF_fetch_array = 8, // Need to fetch full array REF_literal = 16, // Reference is to a constant REF_ttype = 32, // Reference contains character set spec REF_array_elem = 64, // Reference to an array element REF_sql_date = 128, // Reference is to a date constant REF_sql_time = 256, // Reference is to a time constant REF_timestamp = 512 // Reference is to a timestamp constant }; const size_t REF_LEN = sizeof(ref); // *************** start of tree roots **************** // Based on block. Used for based on clause struct bas { gpre_fld* bas_field; // database field referenced gpre_lls* bas_variables; // list of variables based on above str* bas_db_name; // database name if present and required str* bas_rel_name; // relation name if no db statement str* bas_fld_name; // field if no db statement USHORT bas_flags; char bas_terminator[2]; // terminating character }; const size_t BAS_LEN = sizeof(bas); enum bas_flags_vals { BAS_segment = 1, // Based on a blob segment length BAS_ambiguous = 2 // Ambiguous reference to segment }; // declare udf block struct decl_udf { const TEXT *decl_udf_name; const TEXT *decl_udf_entry_point; const TEXT *decl_udf_module_name; gpre_fld* decl_udf_arg_list; gpre_fld* decl_udf_return_type; USHORT decl_udf_return_mode; // BY VALUE or BY REFERENCE SSHORT decl_udf_return_parameter; }; const size_t DECL_UDF_LEN = sizeof(decl_udf); // Dynamic statement block, used for dynamic SQL struct dyn { gpre_dbb* dyn_database; // Database involved gpre_sym* dyn_statement_name; // Name of dynamic statement gpre_sym* dyn_cursor_name; // Cursor name const TEXT* dyn_trans; // Transaction handle TEXT *dyn_string; // Dynamic string or variable name TEXT *dyn_sqlda; // Name of SQLDA structure, if any TEXT *dyn_sqlda2; // Name of second SQLDA structure, if any gpre_nod* dyn_using; // dependent on action type }; const size_t DYN_LEN = sizeof(dyn); // Start transaction block struct gpre_tra { gpre_tra* tra_next; // next transaction TEXT *tra_handle; // this handle USHORT tra_flags; // transaction options tpb* tra_tpb; // TPB's for this transaction int tra_db_count; // number of db's and TPB's }; const size_t TRA_LEN = sizeof(gpre_tra); // values for tra_flags enum tra_flags_vals { TRA_ro = 1, TRA_nw = 2, TRA_con = 4, TRA_rrl = 8, TRA_inc = 16, TRA_read_committed = 32, TRA_autocommit = 64, TRA_rec_version = 128, TRA_no_auto_undo = 256 }; const int MAX_TRA_OPTIONS = 8; // act_object block for SQL database commands. struct mdbb { gpre_dbb* mdbb_database; gpre_req* mdbb_dpb_request; //gpre_req* mdbb_dpb_extend_request; // unused }; // Open cursor block struct open_cursor { gpre_sym* opn_cursor; // Symbol block of cursor const TEXT* opn_trans; // Transaction handle ref* opn_using; // Using variables }; const size_t OPN_LEN = sizeof(open_cursor); // Ready block struct rdy { gpre_req* rdy_request; // dpb message & info rdy* rdy_next; gpre_dbb* rdy_database; #ifdef GPRE_COBOL USHORT rdy_id; // id for unique string variable- MPEXL COB #endif TEXT *rdy_filename; }; const size_t RDY_LEN = sizeof(rdy); // Enumerated field type block struct field_type { gpre_sym* typ_symbol; // Actual symbol, set but never used gpre_fld* typ_field; // Owner SSHORT typ_value; // Value of type }; const size_t TYP_LEN = sizeof(field_type); // User Defined Function struct udf { gpre_dbb* udf_database; gpre_sym* udf_symbol; // Function name or query name USHORT udf_args; // Number of arguments USHORT udf_flags; // udf flags USHORT udf_dtype; // Return data type SSHORT udf_scale; // Return scale USHORT udf_length; // Return length USHORT udf_sub_type; // Return sub-type USHORT udf_charset_id; // Return character set USHORT udf_ttype; // Return text type USHORT udf_type; // Function type gpre_fld* udf_inputs; // List of udf input arguments TEXT udf_function[1]; // Function name }; const size_t UDF_LEN = sizeof(udf); enum udf_type_vals { UDF_value, UDF_boolean }; enum udf_flags_vals { UDF_scanned = 1 }; // Update block -- used for (at least) MODIFY struct upd { USHORT upd_level; // reference level gpre_req* upd_request; // parent request ref* upd_references; // references under modify gpre_ctx* upd_source; // context being modified gpre_ctx* upd_update; // update context gpre_port* upd_port; // port for update //upd* upd_outer; // outer modify, if any; unused gpre_nod* upd_assignments; // assignments to port //ref* upd_array_references; // array references under modify; unused }; const size_t UPD_LEN = sizeof(upd); #include "../jrd/dsc.h" #include "parse.h" // GPRE wide globals struct GpreGlobals { bool sw_auto; bool sw_sql; bool sw_raw; bool sw_cstring; bool sw_dyn_using; bool sw_ids; bool sw_case; bool sw_external; bool sw_version; bool sw_d_float; bool sw_no_qli; USHORT sw_sql_dialect; bool sw_know_interp; USHORT sw_server_version; USHORT sw_ods_version; bool override_case; bool dialect_specified; bool trusted_auth; SSHORT sw_interp; USHORT compiletime_db_dialect; gpre_dbb* isc_databases; const TEXT* default_user; const TEXT* default_password; const TEXT* default_lc_ctype; gpre_req* requests; gpre_lls* events; FILE *out_file; lang_t sw_language; int errors_global; act* global_functions; intlsym* text_subtypes; #ifdef GPRE_ADA TEXT ada_package[MAXPATHLEN]; const TEXT* ada_null_address; // ada_flags fields definition int ADA_create_database; // the flag is set when there is a // create database SQL statement in // user program, and is used to // generate additional "with" and // "function" declarations USHORT ada_flags; #endif #ifdef GPRE_COBOL cob_t sw_cob_dialect; const TEXT* sw_cob_dformat; #endif #ifdef GPRE_FORTRAN // from gpre.cpp UCHAR fortran_labels[1024]; dbd global_db_list[MAX_DATABASES]; USHORT global_db_count; #endif const TEXT* ident_pattern; const TEXT* long_ident_pattern; const TEXT* utility_name; const TEXT* count_name; const TEXT* slack_name; const TEXT* transaction_name; const TEXT* database_name; tok prior_token; // from par.cpp act* cur_routine; // from sql.cpp const TEXT* module_lc_ctype; // from parse.h tok token_global; }; extern GpreGlobals gpreGlob; #ifndef fb_assert #ifdef DEV_BUILD #undef fb_assert #define fb_assert(ex) {if (!(ex)) {CPR_assert (__FILE__, __LINE__);}} #else // DEV_BUILD #undef fb_assert #define fb_assert(ex) #endif // DEV_BUILD #endif // fb_assert #define assert_IS_REQ(x) fb_assert(!(x) || ((x)->req_type >= 0 && (x)->req_type < REQ_LASTREQUEST)) //#define assert_IS_SYM(x) fb_assert(!(x) || ((x)->sym_type >= 0 && (x)->sym_type < SYM_LASTSYM)) #define assert_IS_NOD(x) fb_assert(!(x) || ((x)->nod_type >= 1 && (x)->nod_type < nod_LASTNOD)) //#define assert_IS_ACT(x) fb_assert(!(x) || ((x)->act_type >= 0 && (x)->act_type < ACT_LASTACT)) class gpre_exception: public Firebird::LongJump { char msg[MAXPATHLEN << 1]; public: gpre_exception() { msg[0] = 0; } gpre_exception(const char* errmsg) { strncpy(msg, errmsg, sizeof(msg)); msg[sizeof(msg) - 1] = 0; } const char* what() const throw() { return msg[0] ? msg : "gpre_exception"; } }; #endif // GPRE_GPRE_H