📄 par.c
字号:
/* * PROGRAM: JRD Access Method * MODULE: par.c * DESCRIPTION: BLR Parser * * 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): ______________________________________. * 27-May-2001 Claudio Valderrama: par_plan() no longer uppercases * an index's name before doing a lookup of such index. * 2001.07.28: Added parse code for blr_skip to support LIMIT. *//*$Id: par.c,v 1.1 2001/10/13 10:22:56 dimitr Exp $*/#include "../jrd/ib_stdio.h"#include <string.h>#include "../jrd/common.h"#include <stdarg.h>#include "../jrd/jrd.h"#include "../jrd/gds.h"#include "../jrd/val.h"#include "../jrd/align.h"#include "../jrd/exe.h"#include "../jrd/lls.h"#include "../jrd/scl.h"#include "../jrd/all.h"#include "../jrd/req.h"#include "../jrd/blb.h"#include "../jrd/intl.h"#include "../jrd/met.h"#include "../jrd/all_proto.h"#include "../jrd/cmp_proto.h"#include "../jrd/cvt_proto.h"#include "../jrd/err_proto.h"#include "../jrd/fun_proto.h"#include "../jrd/gds_proto.h"#include "../jrd/met_proto.h"#include "../jrd/par_proto.h"#include "../jrd/thd_proto.h"/* blr type classes */#define OTHER 0#define STATEMENT 1#define BOOL 2#define VALUE 3#define TYPE_RSE 4#define RELATION 5#define ACCESS_TYPE 6#include "../jrd/blrtable.h"static CONST TEXT elements [][10] = { "", "statement", "boolean", "value", "RSE", "TABLE"};static CONST struct { CONST SCHAR *code_string; SLONG code_number;} FAR_VARIABLE codes [] = {#include "../jrd/codetext.h" NULL, 0};static void error (CSB, ...);static SSHORT find_proc_field (PRC, TEXT *);static NOD par_args (TDBB, CSB *, USHORT);static NOD par_cast (TDBB, CSB *);static XCP par_condition (TDBB, CSB *);static XCP par_conditions (TDBB, CSB *);static SSHORT par_context (CSB *, SSHORT *);static void par_dependency (TDBB, CSB *, SSHORT, SSHORT, TEXT *);static NOD par_exec_proc (TDBB, CSB *, SSHORT);static NOD par_fetch (TDBB, CSB *, NOD);static NOD par_field (TDBB, CSB *, SSHORT);static NOD par_function (TDBB, CSB *);static NOD par_literal (TDBB, register CSB *);static NOD par_map (TDBB, CSB *, USHORT);static NOD par_message (TDBB, CSB *);static NOD par_modify (TDBB, CSB *);static USHORT par_name (CSB *, TEXT *);static NOD par_plan (TDBB, CSB *);static NOD par_procedure (TDBB, CSB *, SSHORT);static void par_procedure_parms (TDBB, CSB *, PRC, NOD *, NOD *, USHORT);static NOD par_relation (TDBB, CSB *, SSHORT, BOOLEAN);static NOD par_rse (TDBB, CSB *, SSHORT);static NOD par_sort (TDBB, CSB *, BOOLEAN);static NOD par_stream (TDBB, CSB *);static NOD par_union (TDBB, CSB *);static USHORT par_word (CSB *);static NOD parse (TDBB, register CSB *, USHORT);static void syntax_error (CSB, CONST TEXT *);static void warning (CSB, ...);#define BLR_PEEK *((*csb)->csb_running)#define BLR_BYTE *((*csb)->csb_running)++#define BLR_PUSH ((*csb)->csb_running)--#define BLR_WORD par_word (csb)NOD PAR_blr ( TDBB tdbb, REL relation, UCHAR *blr, CSB view_csb, CSB *csb_ptr, REQ *request_ptr, BOOLEAN trigger, USHORT flags){/************************************** * * P A R _ b l r * ************************************** * * Functional description * Parse blr, returning a compiler scratch block with the results. * Caller must do pool handling. * **************************************/CSB csb;NOD node;SSHORT version, stream, count;struct csb_repeat *t1, *t2, *end;SET_TDBB (tdbb);if (!(csb_ptr && (csb = *csb_ptr))) { count = 5; if (view_csb) count += view_csb->csb_count; csb = (CSB) ALLOCDV (type_csb, count); csb->csb_count = count; csb->csb_g_flags |= flags; }/* If there is a request ptr, this is a trigger. Set up contexts 0 and 1 for the target relation */if (trigger) { stream = csb->csb_n_stream++; t1 = CMP_csb_element (&csb, 0); t1->csb_flags |= csb_used | csb_active | csb_trigger; t1->csb_relation = relation; t1->csb_stream = (UCHAR) stream; stream = csb->csb_n_stream++; t1 = CMP_csb_element (&csb, 1); t1->csb_flags |= csb_used | csb_active | csb_trigger; t1->csb_relation = relation; t1->csb_stream = (UCHAR) stream; }else { ++csb->csb_n_stream; csb->csb_rpt [0].csb_relation = relation; }csb->csb_running = csb->csb_blr = blr;if (view_csb) { t1 = view_csb->csb_rpt; end = t1 + view_csb->csb_n_stream; for (stream = 0; t1 < end; t1++, stream++) { t2 = CMP_csb_element (&csb, stream); t2->csb_relation = t1->csb_relation; t2->csb_stream = t1->csb_stream; } csb->csb_n_stream = view_csb->csb_n_stream; }version = *csb->csb_running++;if (version != blr_version4 && version != blr_version5) error (csb, gds__metadata_corrupt, gds_arg_gds, gds__wroblrver, gds_arg_number, (SLONG) blr_version4, gds_arg_number, (SLONG) version, 0);if (version == blr_version4) csb->csb_g_flags |= csb_blr_version4;node = parse (tdbb, &csb, OTHER);csb->csb_node = node;if (*csb->csb_running++ != (UCHAR) blr_eoc) syntax_error (csb, "end_of_command");if (request_ptr) *request_ptr = CMP_make_request (tdbb, &csb);if (csb_ptr) *csb_ptr = csb;else ALL_RELEASE (csb);return node;}int PAR_desc ( CSB *csb, DSC *desc){/************************************** * * P A R _ d e s c * ************************************** * * Functional description * Parse a BLR descriptor. Return the alignment requirements * of the datatype. * **************************************/USHORT dtype;desc->dsc_scale = 0;desc->dsc_sub_type = 0;desc->dsc_address = (UCHAR*) NULL_PTR;desc->dsc_flags = 0;switch (dtype = BLR_BYTE) { case blr_text: desc->dsc_dtype = dtype_text; desc->dsc_flags |= DSC_no_subtype; desc->dsc_length = BLR_WORD; INTL_ASSIGN_TTYPE (desc, ttype_dynamic); break; case blr_cstring: desc->dsc_dtype = dtype_cstring; desc->dsc_flags |= DSC_no_subtype; desc->dsc_length = BLR_WORD; INTL_ASSIGN_TTYPE (desc, ttype_dynamic); break; case blr_varying: desc->dsc_dtype = dtype_varying; desc->dsc_flags |= DSC_no_subtype; desc->dsc_length = BLR_WORD + sizeof (USHORT); INTL_ASSIGN_TTYPE (desc, ttype_dynamic); break; case blr_text2: desc->dsc_dtype = dtype_text; INTL_ASSIGN_TTYPE (desc, BLR_WORD); desc->dsc_length = BLR_WORD; break; case blr_cstring2: desc->dsc_dtype = dtype_cstring; INTL_ASSIGN_TTYPE (desc, BLR_WORD); desc->dsc_length = BLR_WORD; break; case blr_varying2: desc->dsc_dtype = dtype_varying; INTL_ASSIGN_TTYPE (desc, BLR_WORD); desc->dsc_length = BLR_WORD + sizeof (USHORT); break; case blr_short: desc->dsc_dtype = dtype_short; desc->dsc_length = sizeof (SSHORT); desc->dsc_scale = (int) BLR_BYTE; break; case blr_long: desc->dsc_dtype = dtype_long; desc->dsc_length = sizeof (SLONG); desc->dsc_scale = (int) BLR_BYTE; break; case blr_int64: desc->dsc_dtype = dtype_int64; desc->dsc_length = sizeof (SINT64); desc->dsc_scale = (int) BLR_BYTE; break; case blr_quad: desc->dsc_dtype = dtype_quad; desc->dsc_length = sizeof (GDS__QUAD); desc->dsc_scale = (int) BLR_BYTE; break; case blr_float: desc->dsc_dtype = dtype_real; desc->dsc_length = sizeof (float); break; case blr_timestamp: desc->dsc_dtype = dtype_timestamp; desc->dsc_length = sizeof (GDS__QUAD); break; case blr_sql_date: desc->dsc_dtype = dtype_sql_date; desc->dsc_length = type_lengths [dtype_sql_date]; break; case blr_sql_time: desc->dsc_dtype = dtype_sql_time; desc->dsc_length = type_lengths [dtype_sql_time]; break; case blr_double:#ifndef VMS case blr_d_float:#endif desc->dsc_dtype = dtype_double; desc->dsc_length = sizeof (double); break;#ifdef VMS case blr_d_float: desc->dsc_dtype = dtype_d_float; desc->dsc_length = sizeof (double); break;#endif default: if (dtype == blr_blob) { desc->dsc_dtype = dtype_blob; desc->dsc_length = sizeof (GDS__QUAD); break; } error (*csb, gds__datnotsup, 0); }return type_alignments [desc->dsc_dtype];}NOD PAR_gen_field ( TDBB tdbb, USHORT stream, USHORT id){/************************************** * * P A R _ g e n _ f i e l d * ************************************** * * Functional description * Generate a field block. * **************************************/NOD node;SET_TDBB (tdbb);node = (NOD) ALLOCDV (type_nod, e_fld_length);node->nod_type = nod_field;node->nod_arg [e_fld_id] = (NOD) (SLONG) id;node->nod_arg [e_fld_stream] = (NOD) (SLONG) stream;return node;}NOD PAR_make_field ( TDBB tdbb, CSB csb, USHORT context, TEXT *base_field){/************************************** * * P A R _ m a k e _ f i e l d * ************************************** * * Functional description * Make up a field node in the permanent pool. This is used * by MET_scan_relation to handle view fields. * **************************************/SSHORT id;USHORT stream;TEXT name [32];FLD field;REL temp_rel;NOD temp_node;SET_TDBB (tdbb);stream = csb->csb_rpt [context].csb_stream;/* CVC: This is just another case of a custom function that isn't preparedfor quoted identifiers and that causes views with fields names like "z x"to fail miserably. Since this function was truncating field names like "z x",MET_lookup_field() call below failed and hence the function returned NULLso only caller MET_scan_relation() did field->fld_source = 0;This means a field without entry in rdb$fields. This is the origin of themysterious message "cannot access column z x in view VF" when selecting fromsuch view that has field "z x". This closes Firebird Bug #227758. */strcpy (name, base_field);MET_exact_name (name);id = MET_lookup_field (tdbb, csb->csb_rpt [stream].csb_relation, name, 0);if (id < 0) return NULL;temp_rel = csb->csb_rpt [stream].csb_relation;/* If rel_fields is NULL this means that the relation is * in a temporary state (partially loaded). In this case * there is nothing we can do but post an error and exit. * Note: This will most likely happen if we have a large list * of deffered work which can not complete because of some * error, and while we are trying to commit, we find * that we have a dependency on something later in the list. * IF there were no error, then the dependency woyld have * been resolved, because we would have fully loaded the * relation, but if it can not be loaded, then we have this * problem. The only thing that can be done to remedy this * problem is to rollback. This will clear the dfw list and * allow the user to remedy the original error. Note: it would * be incorrect for us (the server) to perform the rollback * implicitly, because this is a task for the user to do, and * should never be decided by the server. This fixes bug 10052 */if (!temp_rel->rel_fields) { ERR_post(isc_depend_on_uncommitted_rel, 0); }temp_node = PAR_gen_field (tdbb, stream, id);if (field = (FLD) temp_rel->rel_fields->vec_object[id]) { if (field->fld_default_value && field->fld_not_null) temp_node->nod_arg [e_fld_default_value] = field->fld_default_value; }return temp_node;}NOD PAR_make_list ( TDBB tdbb, LLS stack){/************************************** * * P A R _ m a k e _ l i s t * ************************************** * * Functional description * Make a list node out of a stack. * **************************************/NOD node, *ptr;LLS temp;USHORT count;SET_TDBB (tdbb);/* Count the number of nodes */for (temp = stack, count = 0; temp; count++) temp = temp->lls_next;node = PAR_make_node (tdbb, count);node->nod_type = nod_list;ptr = node->nod_arg + count;while (stack) *--ptr = (NOD) LLS_POP (&stack);return node;}NOD PAR_make_node ( TDBB tdbb, int size){/************************************** * * P A R _ m a k e _ n o d e * ************************************** * * Functional description * Make a node element and pass it back. * **************************************/NOD node;SET_TDBB (tdbb);node = (NOD) ALLOCDV (type_nod, size);node->nod_count = size;return node;}CSB PAR_parse ( TDBB tdbb, UCHAR *blr, USHORT internal_flag){/************************************** * * P A R _ p a r s e * ************************************** * * Functional description * Parse blr, returning a compiler scratch block with the results. * **************************************/NOD node;CSB csb;SSHORT version;SET_TDBB (tdbb);csb = (CSB) ALLOCDV (type_csb, 5);csb->csb_count = 5;csb->csb_running = csb->csb_blr = blr;version = *csb->csb_running++;if (internal_flag) csb->csb_g_flags |= csb_internal;if (version != blr_version4 && version!= blr_version5) error (csb, gds__wroblrver, gds_arg_number, (SLONG) blr_version4, gds_arg_number, (SLONG) version, 0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -