/*{ ** Name: psy_qminit - Allocate and initialize the PSY_CB ** ** Description: ** This function allocates and initialzes the qrymod control ** block, PSY_CB. It is called by the grammar. ** ** Inputs: ** sess_cb Current session control block ** psq_cb ** .err_blk Filled in if an error happens ** mstream memory stream to use for allocating a ** PSY_CB ** ** Outputs: ** sess_cb ** .pss_object Points to allocated psy_cb ** Returns: ** E_DB_OK Success ** Other Return code from called functions ** Exceptions: ** none ** ** Side Effects: ** Allocates memory ** ** History: ** 22-jul-89 (ralph) ** Written. ** 08-aug-90 (ralph) ** Initialize new psy_cb fields. ** 14-jul-92 (andre) ** init PSY_CB.psy_flags ** 14-jul-92 (andre) ** added mstream to the function's interface which will enable it to no ** longer assume that PSY_CB must be allocated from any given stream. ** 20-jul-92 (andre) ** added initialization for psy_xcolq ** 20-jul-92 (andre) ** iprocessing DROP PROCEDURE (psq_cb->psq_mode == PSQ_DRODBP), memory ** stream has already been opened, so don't do it here ** 21-jul-92 (andre) ** removed initialization for psy_xcolq; ** ** replaced code initializing various fields to 0 with a call to MEfill ** to fill a newly allocated PSY_CB with 0's ** 06-dec-92 (andre) ** Added code to initialize psy_u_colq and psy_r_colq ** 10-jul-93 (andre) ** cast QUinit()'s arg to (QUEUE *) to agree with the prototype ** declaration ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 28-apr-94 (andre) ** (part of fix for bug 62890) ** if the statement was generated internally ** (psq_cb->psq_info->pst_execflags & PST_SYSTEM_GENERATED), set ** PSY_SYSTEM_GENEARTED in psy_cb->psy_flags. */ DB_STATUS psy_qminit( PSS_SESBLK *sess_cb, PSQ_CB *psq_cb, PSF_MSTREAM *mstream) { DB_STATUS status; PSY_CB *psy_cb; /* ** open the memory stream unless we are processing DROP PROCEDURE, in which ** case it has already been opened */ if (psq_cb->psq_mode != PSQ_DRODBP) { /* Allocate the PSY_CB statement */ status = psf_mopen(sess_cb, QSO_QP_OBJ, mstream, &psq_cb->psq_error); if (status != E_DB_OK) return (status); } status = psf_malloc(sess_cb, mstream, sizeof(PSY_CB), &sess_cb->pss_object, &psq_cb->psq_error); if (status != E_DB_OK) return (status); status = psf_mroot(sess_cb, mstream, sess_cb->pss_object, &psq_cb->psq_error); if (status != E_DB_OK) return (status); psy_cb = (PSY_CB *) sess_cb->pss_object; MEfill(sizeof(PSY_CB), (u_char) 0, (PTR) psy_cb); /* Fill in control block header */ psy_cb->psy_length = sizeof(PSY_CB); psy_cb->psy_type = PSYCB_CB; psy_cb->psy_owner = (PTR)DB_PSF_ID; psy_cb->psy_ascii_id = PSYCB_ASCII_ID; (VOID) QUinit((QUEUE *) &psy_cb->psy_usrq); /* No users */ (VOID) QUinit((QUEUE *) &psy_cb->psy_tblq); /* No tables */ (VOID) QUinit((QUEUE *) &psy_cb->psy_colq); /* No columns */ (VOID) QUinit((QUEUE *) &psy_cb->psy_u_colq); (VOID) QUinit((QUEUE *) &psy_cb->psy_r_colq); /* ** remember whether the statement was generated internally */ if ( psq_cb->psq_info && psq_cb->psq_info->pst_execflags & PST_SYSTEM_GENERATED) { psy_cb->psy_flags |= PSY_SYSTEM_GENERATED; } return(E_DB_OK); }
/*{ ** Name: psy_txtalloc - Allocate a new text block ** ** Description: ** This function allocates a new text block in a memory stream, ** fills it in, and returns a pointer to it. ** ** Inputs: ** mstream Pointer to memory stream ** newblock Place to put pointer to new block ** err_blk Filled in if error happens ** ** Outputs: ** newblock Filled in with pointer to new block ** err_blk Filled in if an error happened ** Returns: ** E_DB_OK Success ** E_DB_ERROR Failure ** Exceptions: ** none ** ** Side Effects: ** Allocates memory ** ** History: ** 15-jul-86 (jeff) ** written */ DB_STATUS psy_txtalloc( PSF_MSTREAM *mstream, PSY_QTEXT **newblock, DB_ERROR *err_blk) { DB_STATUS status; PSS_SESBLK *sess_cb; sess_cb = psf_sesscb(); /* Allocate the block */ status = psf_malloc(sess_cb, mstream, sizeof(PSY_QTEXT), (PTR *) newblock, err_blk); if (DB_FAILURE_MACRO(status)) return (status); /* Fill in the block */ (*newblock)->psy_qnext = (PSY_QTEXT *) NULL; (*newblock)->psy_qcount = 0; return (E_DB_OK); }
DB_STATUS pst_ruledup( PSS_SESBLK *sess_cb, PSF_MSTREAM *mstream, i4 filter, char *col_mask, PST_STATEMENT *stmt_tree, PST_STATEMENT **stmt_dup, DB_ERROR *err_blk) { PST_STATEMENT *curs; /* Current stmt to walk through list */ PST_STATEMENT *ifs; /* IF statement */ PST_STATEMENT *cps; /* CP statement */ PST_STATEMENT *prev_if; /* Previous IF and CP statements to */ PST_STATEMENT *prev_cp; /* patch dangling pointers */ PST_STATEMENT *cur_rule; /* PTR to CP node or IF-CP node pair */ PST_STATEMENT *result; /* Return value - start of list */ PSC_RULE_TYPE *rtype; /* Filter rule type */ DB_COLUMN_BITMAP tst_mask; /* test mask for update columns */ DB_STATUS status; PSS_DUPRB dup_rb; i4 err_code; *stmt_dup = result = NULL; if ((curs = stmt_tree) == NULL) /* Nothing doing */ return (E_DB_OK); prev_if = NULL; prev_cp = NULL; /* initialize fields in dup_rb */ dup_rb.pss_op_mask = 0; dup_rb.pss_num_joins = PST_NOJOIN; dup_rb.pss_tree_info = (i4 *) NULL; dup_rb.pss_mstream = mstream; dup_rb.pss_err_blk = err_blk; while (curs != NULL) { /* ** Filter out current rule if not applicable. Check statement type of ** caller and rule, and column mask. */ if (filter != 0) { if ((rtype = (PSC_RULE_TYPE *)curs->pst_opf) == NULL) { psf_error(E_PS0C06_BAD_STMT, 0L, PSF_INTERR, &err_code, err_blk, 1, sizeof("PSC_RULE_TYPE.pst_opf")-1, "PSC_RULE_TYPE.pst_opf"); return (E_DB_ERROR); } /* copy the bitmap of the rule to an overwriteable test mask, ** and test that against the bitmap of columns being updated */ MEcopy((PTR) &rtype->psr_columns, sizeof(DB_COLUMN_BITMAP), (PTR) &tst_mask); BTand((i4) DB_COL_BITS, (char *) col_mask, (char *) tst_mask.db_domset); /* Check statement type of caller and rule, ** and check result of column bitmap test. */ if ( ((rtype->psr_statement & filter) == 0) || (BTcount((char *) tst_mask.db_domset, DB_COL_BITS) == 0) ) { curs = curs->pst_next; /* Skip this one */ continue; } } ifs = cps = NULL; /* Current ones start out nulled */ /* If found IF, allocate node, patch pointers & continue with CP node */ if (curs->pst_type == PST_IF_TYPE) { status = psf_malloc(sess_cb, mstream, sizeof(*ifs), (PTR*)&ifs, err_blk); if (status != E_DB_OK) return (status); STRUCT_ASSIGN_MACRO(*curs, *ifs); if (filter != 0) /* Detach for safety when filtering */ ifs->pst_opf = NULL; /* Patch/copy IF condition pointer and confirm it exists*/ dup_rb.pss_tree = curs->pst_specific.pst_if.pst_condition; dup_rb.pss_dup = &ifs->pst_specific.pst_if.pst_condition; status = pst_treedup(sess_cb, &dup_rb); if (status != E_DB_OK) return (status); if (ifs->pst_specific.pst_if.pst_condition == NULL) { psf_error(E_PS0C06_BAD_STMT, 0L, PSF_INTERR, &err_code, err_blk, 1, sizeof("PST_IF.pst_condition") - 1, "PST_IF.pst_condition"); return (E_DB_ERROR); } /* True and False links done later */ curs = ifs->pst_link; /* Better be a CP statement node */ } /* If found an IF node */ if (curs->pst_type != PST_CP_TYPE) { psf_error(E_PS0C06_BAD_STMT, 0L, PSF_INTERR, &err_code, err_blk, 1, sizeof("PST_CP") - 1, "PST_CP"); return (E_DB_ERROR); } /* Allocate and initialize CP node */ status = psf_malloc(sess_cb, mstream, sizeof(*cps), (PTR *)&cps, err_blk); if (status != E_DB_OK) return (status); STRUCT_ASSIGN_MACRO(*curs, *cps); if (filter != 0) /* Detach for safety when filtering */ cps->pst_opf = NULL; /* If there are any arguments patch/copy arguments list pointer */ if (curs->pst_specific.pst_callproc.pst_arglist != NULL) { dup_rb.pss_tree = curs->pst_specific.pst_callproc.pst_arglist; dup_rb.pss_dup = &cps->pst_specific.pst_callproc.pst_arglist; status = pst_treedup(sess_cb, &dup_rb); if (status != E_DB_OK) return (status); } /* Adjust pointers of [IF node and] CP node */ if (ifs != NULL) { cur_rule = ifs; /* Rule pair is IF->CP */ ifs->pst_link = cps; ifs->pst_specific.pst_if.pst_true = cps; } else { cur_rule = cps; /* Rule is just CP */ } if (result == NULL) /* 1st rule - no patch needed */ { result = cur_rule; } else /* Patch dangling pointers of previous [IF node &] CP node */ { if (prev_if != NULL) { prev_if->pst_next = cur_rule; prev_if->pst_specific.pst_if.pst_false = cur_rule; } prev_cp->pst_next = cur_rule; prev_cp->pst_link = cur_rule; } /* Move on to next statement */ prev_if = ifs; prev_cp = cps; curs = curs->pst_next; } /* While there are more statements */ /* Clear dangling pointers of last [IF node and] CP node */ if (prev_if != NULL) { prev_if->pst_next = NULL; prev_if->pst_specific.pst_if.pst_false = NULL; } if (prev_cp != NULL) /* Could be null if all were filtered out */ { prev_cp->pst_next = NULL; prev_cp->pst_link = NULL; } *stmt_dup = result; return (E_DB_OK); } /* pst_ruledup */
/* ** Name: psq_store_text - store query text in a contiguous block of QSF memory ** ** Description: ** Copy contents of a query text chain (prepended, if necessary with RANGE ** statements) into a contiguous block of QSF memory. Caller may specify ** that the text be stored in DB_TEXT_STRING format by setting ** return_db_text_string to TRUE; otherwise the function will return a i4 ** followed by query text. ** ** Input: ** rngtab if non-NULL, range statements will be ** generated for all entries of the range table ** that are active (pss_used && pss_rgno >= 0); ** should be non-NULL only for QUEL queries ** header Pointer to chain header ** mstream Pointer to opened memory stream ** return_db_text_string if TRUE, function will store text in ** DB_TEXT_STRING format; otherwise it will store ** it a a i4 (length) followed by text ** ** Output: ** result query text in specified format ** err_blk Filled in if an error happens ** ** Side efects: ** allocates memory ** ** Returns: ** E_DB_{OK,ERROR} ** ** History: ** 09-jan-93 (andre) ** written ** 29-jul-2001 (toumi01) ** problem found doing i64_aix port: ** (u_char *)'\n' should be (uchar)'\n' ** (u_char *)'\0' should be (uchar)'\0' ** 26-Oct-2009 (coomi01) b122714 ** Move psq_store_text() declarator to pshparse.h and make it public here. ** 24-Jun-2010 (kschendel) b123775 ** Correct a call to trim-whitespace. */ DB_STATUS psq_store_text( PSS_SESBLK *sess_cb, PSS_USRRANGE *rngtab, PTR header, PSF_MSTREAM *mstream, PTR *result, bool return_db_text_string, DB_ERROR *err_blk) { DB_STATUS status; i4 i; PSQ_THEAD *hp = (PSQ_THEAD *) header; i4 size = hp->psq_tsize; PSQ_TEXT *tp; PSS_RNGTAB *rngvar; u_char *out; if (rngtab) { /* ** allocate enough space for range statements. each range statement ** looks like range of 'rngname' is 'tabname'\n. ** Thus, max space is 14+2*DB_MAX_NAME. */ for (i = 0, rngvar = rngtab->pss_rngtab; i < PST_NUMVARS; i++, rngvar++) { /* Only look at range vars that are being used */ if (rngvar->pss_used && rngvar->pss_rgno >= 0) { size += ( 14 /* "range of is \n" */ + psf_trmwhite(DB_TAB_MAXNAME, rngvar->pss_rgname) + psf_trmwhite(sizeof(DB_TAB_NAME), (char *) &rngvar->pss_tabname)); } } } if (return_db_text_string) { DB_TEXT_STRING *str; status = psf_malloc(sess_cb, mstream, size + sizeof(*str) - sizeof(u_char), result, err_blk); if (status != E_DB_OK) return (status); str = (DB_TEXT_STRING *) *result; /* ** store the total length of query text */ str->db_t_count = size; out = str->db_t_text; } else { /* Allocate a piece large enough for all the text + a i4 (count) */ status = psf_malloc(sess_cb, mstream, size + sizeof(i4), result, err_blk); if (status != E_DB_OK) return (status); out = (u_char *) *result; /* Copy the length into the buffer */ MEcopy((char *) &size, sizeof(size), (char *) out); out += sizeof(size); } /* Copy the pieces into the buffer; first put the range statements */ if (rngtab) { for (i = 0, rngvar = rngtab->pss_rngtab; i < PST_NUMVARS; i++, rngvar++) { /* Only look at range vars that are being used */ if (rngvar->pss_used && rngvar->pss_rgno >= 0) { i4 plen; STncpy( (char *)out, "range of ", 9); out += 9; /* add in range name */ plen = psf_trmwhite(DB_TAB_MAXNAME, rngvar->pss_rgname); STncpy( (char *)out, rngvar->pss_rgname, plen); out += plen; STncpy( (char *)out, " is ", 4); out += 4; plen = psf_trmwhite(DB_TAB_MAXNAME, rngvar->pss_tabname.db_tab_name); STncpy( (char *)out, (char *)&rngvar->pss_tabname, plen); out += plen; *out = (u_char)'\n'; out++; *out = (u_char)'\0'; } } } for (tp = hp->psq_first; tp != (PSQ_TEXT *) NULL; tp = tp->psq_next) { MEcopy((char *) tp->psq_tval, tp->psq_psize, (char *) out); out += tp->psq_psize; } return(E_DB_OK); }
/* ** Name psl_lm1_setlockstmnt() - perform semantic action for SETLOCKSTMNT ** production ** ** Description: ** perform semantic action for SETLOCKSTMNT production in QUEL and SQL ** grammars ** ** Input: ** sess_cb PSF session CB ** pss_distrib DB_3_DDB_SESS if distributed thread ** pss_ostream stream to be opened for memory allocation ** pss_stmt_flags PSS_SET_LOCKMODE_SESS if SET LOCKMODE SESSION ** psq_cb PSF request CB ** ** Output: ** sess_cb ** pss_ostream stream has been opened for memory allocation ** pss_object point to the root of a new QSF object ** (of type (DMC_CB *) or (QEF_RCB *)). ** psq_cb ** psq_mode set to PSQ_SLOCKMODE ** psq_error filled in if an error occurred ** ** Returns: ** E_DB_{OK, ERROR, SEVERE} ** ** Side effects: ** Opens a memory stream and allocates memory ** ** History: ** 07-mar-91 (andre) ** plagiarized from SETLOCKSTMNT production ** 17-apr-92 (barbara) ** Updated for Sybil. Distributed thread allocates QEF_RCB and ** calls QEF directly. ** 07-oct-93 (swm) ** Bug #56437 ** added PTR cast in assignment to dmc_cb->dmc_id. ** 09-oct-93 (swm) ** Bug #56437 ** Put pss_sessid into new dmc_session_id rather than dmc_id. ** 26-Feb-2001 (jenjo02) ** Set session_id in QEF_RCB; ** 11-Jun-2010 (kiria01) b123908 ** Initialise pointers after psf_mopen would have invalidated any ** prior content. */ DB_STATUS psl_lm1_setlockstmnt( PSS_SESBLK *sess_cb, PSQ_CB *psq_cb) { DB_STATUS status; i4 err_code; DMC_CB *dmc_cb; DB_ERROR err_blk; DB_STATUS tempstat; psq_cb->psq_mode = PSQ_SLOCKMODE; /* Verify the user has LOCKMODE permission */ status = psy_ckdbpr(psq_cb, (u_i4) DBPR_LOCKMODE); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(6247L, 0L, PSF_USERERR, &err_code, &psq_cb->psq_error, 0); /* ** Audit failed set lockmode */ if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE ) { (VOID)psy_secaudit( FALSE, sess_cb, "LOCKMODE", (DB_OWN_NAME *)0, 8, SXF_E_RESOURCE, I_SX2741_SET_LOCKMODE, SXF_A_FAIL|SXF_A_LIMIT, &err_blk); } return(status); } /* Create control block for DMC_ALTER or QEF_CALL for set lockmode */ status = psf_mopen(sess_cb, QSO_QP_OBJ, &sess_cb->pss_ostream, &psq_cb->psq_error); if (status != E_DB_OK) return (status); sess_cb->pss_stk_freelist = NULL; if (sess_cb->pss_distrib & DB_3_DDB_SESS) { /* Distributed thread calls QEF directly */ QEF_RCB *qef_rcb; status = psf_malloc(sess_cb, &sess_cb->pss_ostream, sizeof(QEF_RCB), &sess_cb->pss_object, &psq_cb->psq_error); if (status != E_DB_OK) return (status); status = psf_mroot(sess_cb, &sess_cb->pss_ostream, sess_cb->pss_object, &psq_cb->psq_error); if (status != E_DB_OK) return (status); /* Fill in the QEF control block */ qef_rcb = (QEF_RCB *) sess_cb->pss_object; qef_rcb->qef_length = sizeof(QEF_RCB); qef_rcb->qef_type = QEFRCB_CB; qef_rcb->qef_owner = (PTR)DB_PSF_ID; qef_rcb->qef_ascii_id = QEFRCB_ASCII_ID; qef_rcb->qef_modifier = QEF_MSTRAN; qef_rcb->qef_flag = 0; qef_rcb->qef_cb = (QEF_CB *) NULL; qef_rcb->qef_sess_id = sess_cb->pss_sessid; return (E_DB_OK); } status = psf_malloc(sess_cb, &sess_cb->pss_ostream, sizeof(DMC_CB), (PTR *) &dmc_cb, &psq_cb->psq_error); if (status != E_DB_OK) return (status); status = psf_mroot(sess_cb, &sess_cb->pss_ostream, (PTR) dmc_cb, &psq_cb->psq_error); if (status != E_DB_OK) return (status); sess_cb->pss_object = (PTR) dmc_cb; dmc_cb->type = DMC_CONTROL_CB; dmc_cb->length = sizeof (DMC_CB); dmc_cb->dmc_op_type = DMC_SESSION_OP; dmc_cb->dmc_session_id = (PTR)sess_cb->pss_sessid; dmc_cb->dmc_flags_mask = DMC_SETLOCKMODE; dmc_cb->dmc_db_id = sess_cb->pss_dbid; dmc_cb->dmc_db_access_mode = dmc_cb->dmc_lock_mode = 0; /* need to allocate characteristics array with MAX_LOCKMODE_CHARS entries */ status = psf_malloc(sess_cb, &sess_cb->pss_ostream, sizeof(DMC_CHAR_ENTRY) * MAX_LOCKMODE_CHARS, (PTR *) &dmc_cb->dmc_char_array.data_address, &psq_cb->psq_error); if (status != E_DB_OK) return (status); dmc_cb->dmc_char_array.data_in_size = 0; /* ** Audit allowed to issue lockmode */ if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE ) { (VOID)psy_secaudit( FALSE, sess_cb, "LOCKMODE", (DB_OWN_NAME *)0, 8, SXF_E_RESOURCE, I_SX2741_SET_LOCKMODE, SXF_A_SUCCESS|SXF_A_LIMIT, &err_blk); } return(E_DB_OK); }