int odxa_errhandler(void) { char buf[257]=""; char message[513]=" ::[ , 00000000]: "; long error_no = 0; char error_text[257]; SYSTIME time_now; i4 len; // EXEC SQL INQUIRE_SQL(:error_no = ERRORNO,:error_text = ERRORTEXT); IILQisInqSqlio((short *)0,1,30,4,&error_no,2); IILQisInqSqlio((short *)0,1,32,256,error_text,63); CVlx((u_i4)error_no, buf); STprintf(message, ERx(" ::[%-16s, %s]: "), szFuncName, buf); TMnow( &time_now ); TMstr( &time_now, buf ); STcat(message, buf); STcat(message, " MS DTC Ingres XA Interface: "); if (STequal(szFuncName,"xa_open")) /* dump out xa_open's xa_info string */ { len = (i4)STlength(message); STcat(message, errlog_xa_info); WriteDTCerrToEventLog(S_OK, message); message[len] = '\0'; /* chop back to the message header */ } STcat(message, error_text); WriteDTCerrToEventLog(S_OK, message); return 0; }
VOID history_time(char *timeStr) { SYSTIME atime ; struct TMhuman htime ; TMnow(&atime); TMbreak(&atime, &htime); STprintf(timeStr, ERx("%s-%s-%s"), htime.day, htime.month, htime.year); }
VOID copyright_year(char *year) { SYSTIME atime ; struct TMhuman htime ; TMnow(&atime); TMbreak(&atime, &htime); STprintf(year, ERx("%s"), htime.year); }
/* ** Name - SAwrite - write a record to the operating system audit trail ** ** Description: ** This routine writes an audit record to the operating system audit trail. ** It is preffereable though not compulsory for this routine to return ** asynchronously, a subsequent call to SAflush() will hand all ** outstanding audits to the operating system for auditing, if SAwrite() ** is synchronous then SAflush() will be a no-op routine. SAwrite() may ** buffer a number of audit records for performance before writing, if ** the caller wishes to guarantee writes a subsequent call to SAflush() ** must be used. SAwrite() should attempt, if possible, to write an ** additional field, other than those passed in SA_AUD_REC, to the ** operating system audit trail, that will uniquely identify the record ** as an Ingres audit record. The audit trail will be identified by it's ** descriptior passed back from SAopen(). ** ** Inputs: ** aud_trail_d a descriptor that identifies this audit trail ** aud_rec the audit record to be written ** ** Outputs: ** err_code pointer to a variable used to return OS errors. ** ** Returns: ** OK if operation succeeded ** SA_NOOPEN the audit trail decsribed by this descriptor has not ** been opened ** SA_NOWRITE this audit trail may not be written to ** SA_BADPARAM bad parameter values were passed to the routine ** SA_NOSUPP the operation is not supported by this implimentation of ** SA. ** FAIL the operation failed ** ** History: ** 7-jan-94 (stephenb) ** Initial creation using TRdisplay for testing. ** 28-feb-94 (stephenb) ** Updated to current SA spec. */ STATUS SAwrite(PTR *aud_trail_d, SA_AUD_REC *aud_rec, CL_ERR_DESC *err_code) { /* ** This is a "quick and dirty routine" which just re-formats ** the audit record and TRdisplay's it */ SYSTIME stime; struct TMhuman time; char *date; /* ** Check that the audit trail is open, this is just a dummy check ** that the stub routine SAopen() has been called. */ if (STcompare(((SA_DESC*)*aud_trail_d)->sa_desc, "OS")) return (SA_NOOPEN); /* ** Get a human readable date string */ TMnow(&stime); _VOID_ TMbreak(&stime, &time); _VOID_ STpolycat(7, time.wday, time.day, time.month, time.year, time.hour, time.mins, time.sec, &date); /* ** add null terminators to blank filled strings (this will fail ** if the string already uses all 32 charaters). */ _VOID_ SAtrim(aud_rec->sa_ruserid, GL_MAXNAME); _VOID_ SAtrim(aud_rec->sa_euserid, GL_MAXNAME); _VOID_ SAtrim(aud_rec->sa_dbname, GL_MAXNAME); _VOID_ SAtrim(aud_rec->sa_userpriv, GL_MAXNAME); _VOID_ SAtrim(aud_rec->sa_objpriv, GL_MAXNAME); _VOID_ SAtrim(aud_rec->sa_objowner, GL_MAXNAME); _VOID_ SAtrim(aud_rec->sa_objname, GL_MAXNAME); /* ** Send the lot to TRdisplay, not all fields are displayed, just ** enough to get the idea */ TRdisplay("%s | %s | %s | %s | %s | %s\n", &date, aud_rec->sa_accesstype, aud_rec->sa_eventtype, aud_rec->sa_objname, aud_rec->sa_ruserid, aud_rec->sa_dbname); return (OK); }
STATUS ERmsg_hdr( char *svr_id, SCALARP session, char *msg_header) { char host_name[65]; i4 length; SYSTIME stime; GChostname( host_name, sizeof( host_name ) ); STprintf( msg_header, "%-8.8s::[%-16.16s, %08.8x]: ", host_name, svr_id, session ); TMnow(&stime); TMstr(&stime,msg_header + STlength(msg_header)); length = STlength(msg_header); msg_header[length++] = ' '; msg_header[length] = EOS; return (OK); }
/* ** close_log */ STATUS close_log() { STATUS ret_val = OK ; SYSTIME atime ; char buffer [TEST_LINE] ; char timestr [TEST_LINE] ; append_line((char *)ERx("\n"),(i4)1); TMnow(&atime); TMstr(&atime,timestr); STprintf(buffer,ERx("Ending at: %s"),timestr); append_line(buffer,1); SIclose(logptr); return (ret_val); }
void rfapi_getDateTime( char *dtbuf ) { SYSTIME tm; /* system time in seconds */ struct TMhuman dthuman; /* human readable date and time structure */ /* get the system time */ TMnow( &tm ); /* break it up into human readable format */ TMbreak( &tm, &dthuman ); STprintf( dtbuf, RFAPI_DATE_FORMAT, dthuman.wday, dthuman.month, dthuman.day, dthuman.hour, dthuman.mins, dthuman.sec, dthuman.year ); }
VOID qee_d1_qid( QEE_DSH *v_dsh_p) { QEE_DDB_CB *qee_p = v_dsh_p->dsh_ddb_cb; DB_CURSOR_ID *csr_p; SYSTIME tm_now; char hi_ascii[QEK_015_LEN], lo_ascii[QEK_015_LEN], pid_ascii[QEK_015_LEN], temp[QEK_050_LEN + DB_CURSOR_MAXNAME]; PID pid; /* an i4 */ PCpid(& pid); /* get process (server) id */ CVla(pid, pid_ascii); /* convert to ascii */ TMnow(& tm_now); csr_p = & qee_p->qee_d4_given_qid; csr_p->db_cursor_id[0] = tm_now.TM_secs; csr_p->db_cursor_id[1] = tm_now.TM_msecs; CVla(tm_now.TM_secs, hi_ascii); CVla(tm_now.TM_msecs, lo_ascii); STpolycat((i4) 4, /* 4 constituent pieces */ "dd", lo_ascii, hi_ascii, pid_ascii, temp); MEmove(STlength(temp), temp, ' ', DB_CURSOR_MAXNAME, csr_p->db_cur_name); csr_p = & qee_p->qee_d5_local_qid; csr_p->db_cursor_id[0] = 0; csr_p->db_cursor_id[1] = 0; MEfill(DB_CURSOR_MAXNAME, ' ', (PTR) csr_p->db_cur_name); return; }
/*{ ** Name: psy_cproc - Create a database procedure definition in ** the system catalogs. ** ** Description: ** ** Inputs: ** ** Outputs: ** Exceptions: ** none ** ** Side Effects: ** Modifies system catalogs. ** ** History: ** 27-apr-88 (stec) ** Created. ** 23-aug-88 (stec) ** Added comments, initialize new fields in DB_PROCEDURE. ** 26-apr-89 (andre) ** For internal procedures, set db_mask[0] to DB_IPROC. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 12-jun-90 (andre) ** when trying to destroy a dbproc QEP, use "private" alias, which is ** always defined as opposed to the "public" alias which would not be ** defined if the dbproc is not grantable. ** 04-mar-92 (andre) ** set DB_ACTIVE_DBP in db_mask[0] to indicate that the dbproc is not ** abandoned. If the dbproc is grantable, set DB_DBPGRANT_OK in ** db_mask[0]. ** 18-may-92 (andre) ** call psy_dbp_status() to verify that the new dbproc is not abandoned ** and trust psy_dbp_status() to determine whether the dbproc is ** grantable or just active. ** 19-may-92 (andre) ** in pslsgram.yi, pss_dependencies_stream was opened to collect info ** about objects/privileges on which the new dbproc depends; ** this stream must be closed before leaving this function since the ** dependence information will be of no use once we return ** 01-jun-92 (andre) ** pass information about objects/privileges on which the new database ** procedure depends to QEF. ** 26-jun-92 (andre) ** enter information about the dbproc into IIPROCEDURE and the list of ** objects and privileges on which it depends into IIDBDEPENDS and ** IIPRIV respectively before calling psy_dbp_status() to determine ** whether it is active. This is necessary since otherwise it would be ** impossible to create mutually recursive database procedures (if P1 ** calls P2 and we are trying to create P2 calling P1, psy_dbp_status() ** will report that P1 is dormant and prevent us from creating P2) ** ** Since we won't know whether the dbproc is active and/or grantable ** until psy_dbp_status() is done, we will set only DB_DBP_INDEP_LIST ** bit in IIPROCEDURE.dbp_mask1 here, unless the independent ** object/privilege list is empty, in which case there is no reason to ** call psy_dbp_status(), so we will set DB_DBPGRANT_OK and ** DB_ACTIVE_DBP bits in IIPROCEDURE.dbp_mask1. ** ** If the independent object/privilege list is not empty and the ** procedure is not dormant, psy_dbp_status() will set appropriate bits ** (DB_DBPGRANT_OK and/or DB_ACTIVE_DBP) in IIPROCEDURE.dbp_mask1 once ** it has determined whether the dbproc is active or grantable ** 09-sep-92 (andre) ** psy_dbp_status() no longer accepts or returns an indicator of ** whether cache had to be flushed in psy_dbp_priv_check() ** 07-nov-92 (andre) ** we will no longer create private aliases for dbproc QPs ** 22-feb-93 (rblumer) ** initialize new RDF proc_param variables for both normal and ** set-input procedures; reverse order of MEcopy and I4assign in ** QP cleanup code so that qsf id gets set up correctly. ** 13-apr-93 (andre) ** if creating a system-generated procedure, independent ** object/privilege list will be empty - QEF will insert IIDBDEPENDS ** tuple recording dependence of the dbproc on a constraint (for ** constraint-enforcing dbprocs) or view (for CHECK OPTION-enforcing ** dbprocs.) Here we will set bits indicating that there will be ** independent object list and that the dbproc is active but not ** grantable (we don't want the user to grant privileges on ** system-generated dbprocs) ** 01-sep-93 (andre) ** in the course of parsing a dbproc definition, we will try to ** determine id of a base table on which the dbproc depends; here we ** will copy it into proctuple.dbPdbp_ubt_id to ensure that it gets ** inserted into IIPROCEDURE ** 22-oct-93 (rblumer) ** normal procedures will now have their parameters inserted into the ** catalogs (previously just set-input procedures did); changed ** initialization of db_parameterCount, rdr_proc_param_cnt and ** rdr_proc_params to work for both types of procedures. ** 30-apr-94 (andre) ** fix for bug 61087: ** proctuple.db_mask[0] was being set before proctuple was MEfill'd ** with NULLCHAR; moved the line initializing proctuple.db_mask[0] ** below call to MEfill() ** 16-jun-94 (andre) ** Bug #64395 ** it is dangerous to cast a (char *) into a (DB_CURSOR_ID *) and then ** dereference the resulting pointer because the chat ptr may not be ** pointing at memory not aligned on an appopriate boundary. Instead, ** we will allocate a DB_CURSOR_ID structure on the stack, initialize ** it and MEcopy() it into the char array ** 19-june-06 (dougi) ** Add DBP_DATA_CHANGE flag for BEFORE trigger validation. ** 28-march-2008 (dougi) ** Changes to support table procedures and named result row elements. ** 4-feb-2009 (dougi) ** Tidy up computation of table procedure result row length. ** 30-mar-2009 (toumi01) b121871 ** Rewrite and simplify the computation of table procedure input ** and output parameter count and width (fixes a logic error that ** caused the result width to be decremented by the width of the ** first result parameter when there were no input parameters). */ DB_STATUS psy_cproc( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; i4 textlen; QSF_RCB qsf_rb; DB_PROCEDURE proctuple; DB_STATUS status, stat; i4 err_code; PSY_TBL dbp_descr; i4 dbp_mask[2]; bool empty_indep_list, rowproc; /* If this is a recreate case, and this code gets called ** just return since there is no work to be done, not even ** recovery of resources. */ if (sess_cb->pss_dbp_flags & PSS_RECREATE) return(E_DB_OK); /* determine if the new dbproc depends on any object or privileges */ if ( sess_cb->pss_indep_objs.psq_objs || sess_cb->pss_indep_objs.psq_objprivs || sess_cb->pss_indep_objs.psq_colprivs ) { empty_indep_list = FALSE; } else { empty_indep_list = TRUE; } /* ** Initialize the header of the QSF control block ** NOTE: it is important that we init qsf_rb before calling ** psy_dbp_status() - if the dbproc cannot be created, code under ** exit: will expect the control block set up for deleting the query ** text QSF object and the query plan QSF object */ qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_PSF_ID; qsf_rb.qsf_sid = sess_cb->pss_sessid; STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id); /* Retrieve info about the procedure text object */ status = qsf_call(QSO_INFO, &qsf_rb); if (DB_FAILURE_MACRO(status)) { goto exit; } /* Get the text length. */ MEcopy((PTR) qsf_rb.qsf_root, sizeof(i4), (PTR) &textlen); /* Initialize the II_PROCEDURE tuple. */ MEfill(sizeof(proctuple), NULLCHAR, (PTR) &proctuple); (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME), (PTR)&proctuple.db_dbpname); /* Current user is the owner. */ STRUCT_ASSIGN_MACRO(sess_cb->pss_user, proctuple.db_owner); proctuple.db_txtlen = textlen; TMnow((SYSTIME *) &proctuple.db_txtid); /* ** if the independent object/privilege list is non-empty, we will set ** DB_DBP_INDEP_LIST bit and leave it to psy_dbp_status() to set the ** remaining bits, if appropriate; otherwise we will set DB_DBPGRANT_OK and ** DB_ACTIVE_DBP bits and avoid calling psy_dbp_status() ** ** if creating a system-generated dbproc, mark the dbproc ACTIVE and ** indicate that there is independent object list (there is not one at this ** point, but QEF will insert IIDBDEPENDS tuple recording dependence of the ** dbproc on a constraint (for constraint-enforcing dbprocs) or view (for ** CHECK OPTION-enforcingdbprocs.) */ /* If working on internal dbproc, set DB_IPROC in db_mask[0] */ if (sess_cb->pss_dbp_flags & PSS_IPROC) proctuple.db_mask[0] |= DB_IPROC; if (sess_cb->pss_dbp_flags & PSS_SYSTEM_GENERATED) proctuple.db_mask[0] |= DBP_SYSTEM_GENERATED | DB_ACTIVE_DBP | DB_DBP_INDEP_LIST; else if (empty_indep_list) proctuple.db_mask[0] |= DB_DBPGRANT_OK | DB_ACTIVE_DBP; else proctuple.db_mask[0] |= DB_DBP_INDEP_LIST; if (sess_cb->pss_dbp_flags & PSS_SET_INPUT_PARAM) proctuple.db_mask[0] |= DBP_SETINPUT; if (sess_cb->pss_dbp_flags & PSS_NOT_DROPPABLE) proctuple.db_mask[0] |= DBP_NOT_DROPPABLE; if (sess_cb->pss_dbp_flags & PSS_SUPPORTS_CONS) proctuple.db_mask[0] |= DBP_CONS; if (sess_cb->pss_dbp_flags & PSS_DATA_CHANGE) proctuple.db_mask[0] |= DBP_DATA_CHANGE; if (sess_cb->pss_dbp_flags & PSS_OUT_PARMS) proctuple.db_mask[0] |= DBP_OUT_PARMS; if (sess_cb->pss_dbp_flags & PSS_TX_STMT) proctuple.db_mask[0] |= DBP_TX_STMT; if (sess_cb->pss_dbp_flags & PSS_ROW_PROC) { rowproc = TRUE; proctuple.db_mask[0] |= DBP_ROW_PROC; } else rowproc = FALSE; proctuple.db_mask[1] = 0; /* ** if we were able to determine id of a base table on which this dbproc will ** depend, copy it into proctuple */ proctuple.db_dbp_ubt_id.db_tab_base = sess_cb->pss_dbp_ubt_id.db_tab_base; proctuple.db_dbp_ubt_id.db_tab_index = sess_cb->pss_dbp_ubt_id.db_tab_index; /* db_procid to be filled in by RDF or QEF */ proctuple.db_parameterCount = 0; proctuple.db_recordWidth = 0; proctuple.db_rescolCount = 0; proctuple.db_resrowWidth = 0; if (sess_cb->pss_procparmlist != (QEF_DATA *) NULL) { DB_PROCEDURE_PARAMETER *param_tuple; QEF_DATA *listptr; /* compute count and total width of input and result parameters */ for (listptr = sess_cb->pss_procparmlist; listptr != (QEF_DATA *) NULL; listptr = listptr->dt_next) { param_tuple = (DB_PROCEDURE_PARAMETER *)listptr->dt_data; if (param_tuple->dbpp_flags & DBPP_RESULT_COL) { proctuple.db_rescolCount++; proctuple.db_resrowWidth = param_tuple->dbpp_offset + param_tuple->dbpp_length; } else { proctuple.db_parameterCount++; proctuple.db_recordWidth = param_tuple->dbpp_offset + param_tuple->dbpp_length; } } if (proctuple.db_rescolCount > 0) proctuple.db_resrowWidth -= proctuple.db_recordWidth; } /* Initialize the RDF request block. */ pst_rdfcb_init(&rdf_cb, sess_cb); (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], sizeof(DB_DBP_NAME), (PTR)&rdf_rb->rdr_name.rdr_prcname); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, rdf_rb->rdr_owner); rdf_rb->rdr_types_mask = RDR_PROCEDURE; rdf_rb->rdr_update_op = RDR_APPEND; rdf_rb->rdr_qrytuple = (PTR) &proctuple; rdf_rb->rdr_l_querytext = textlen; rdf_rb->rdr_querytext = ((char *) qsf_rb.qsf_root) + sizeof(i4); /* ** pass information about objects/privileges on which the new database ** procedure depends to QEF */ sess_cb->pss_indep_objs.psq_grantee = &sess_cb->pss_user; rdf_rb->rdr_indep = (PTR) &sess_cb->pss_indep_objs; /* fill in the description of the procedure's parameters ** (which RDF/QEF will store into iiprocedure_parameter); */ rdf_rb->rdr_proc_param_cnt = proctuple.db_parameterCount + proctuple.db_rescolCount; rdf_rb->rdr_proc_params = sess_cb->pss_procparmlist; /* Create a new procedure in the system catalogs */ status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0137_DUPLICATE_PROCS) { /* Retry */ psy_cb->psy_error.err_code = E_PS0008_RETRY; } else { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } goto exit; } /* ** if the independent object/privilege list is non-empty, verify that the ** dbproc we are about to create is not abandoned; strictly speaking, as ** long as the independent object list is empty, we are guaranteed that the ** dbproc is not abandoned (user posesses required privileges), but we will ** take an extra step and try to determine whether it is grantable */ if (!empty_indep_list) { MEcopy((PTR) psy_cb->psy_tabname, sizeof(DB_DBP_NAME), (PTR) &dbp_descr.psy_tabnm); dbp_descr.psy_tabid.db_tab_base = proctuple.db_procid.db_tab_base; dbp_descr.psy_tabid.db_tab_index = proctuple.db_procid.db_tab_index; status = psy_dbp_status(&dbp_descr, sess_cb, (PSF_QUEUE *) NULL, (i4) PSQ_CREDBP, dbp_mask, &psy_cb->psy_error); if (DB_FAILURE_MACRO(status)) { goto exit; } } exit: /* ** close the memory stream which was used to allocate descriptors of ** objects/privileges on which the new dbproc depends */ stat = psf_mclose(sess_cb, sess_cb->pss_dependencies_stream, &psy_cb->psy_error); if (DB_FAILURE_MACRO(stat) && stat > status) status = stat; /* ** ensure that no one tries to use the stream that is no longer valid */ sess_cb->pss_dependencies_stream = (PSF_MSTREAM *) NULL; /* Get a lock on the query text from QSF */ qsf_rb.qsf_lk_state = QSO_EXLOCK; stat = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0A08_CANTLOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (stat > status) status = stat; } else { /* Now destroy the query text */ stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (stat > status) status = stat; } } /* Destroy the procedure QP in QSF if things went wrong. */ if (DB_FAILURE_MACRO(status)) { PSS_DBPALIAS dbpid; DB_CURSOR_ID dbp_curs_id; qsf_rb.qsf_feobj_id.qso_type = QSO_ALIAS_OBJ; qsf_rb.qsf_feobj_id.qso_lname = sizeof(dbpid); /* Identify the object first */ dbp_curs_id.db_cursor_id[0] = dbp_curs_id.db_cursor_id[1] = 0; (VOID) MEcopy((PTR)&psy_cb->psy_tabname[0], DB_TAB_MAXNAME, (PTR)dbp_curs_id.db_cur_name); MEcopy((PTR) &dbp_curs_id, sizeof(DB_CURSOR_ID), (PTR) dbpid); (VOID) MEcopy((PTR) &sess_cb->pss_user, DB_OWN_MAXNAME, (PTR) (dbpid + sizeof(DB_CURSOR_ID))); I4ASSIGN_MACRO(sess_cb->pss_udbid, *(i4 *) (dbpid + sizeof(DB_CURSOR_ID) + DB_OWN_MAXNAME)); (VOID)MEcopy((PTR) dbpid, sizeof(dbpid), (PTR) qsf_rb.qsf_feobj_id.qso_name); /* See if QP for the alias already exists. */ qsf_rb.qsf_lk_state = QSO_SHLOCK; stat = qsf_call(QSO_JUST_TRANS, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { if (qsf_rb.qsf_error.err_code != E_QS0019_UNKNOWN_OBJ) { (VOID) psf_error(E_PS037A_QSF_TRANS_ERR, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (stat > status) status = stat; goto exit1; } else { /* QP disappeared, which is alright. */ goto exit1; } } /* Now destroy the QP object in QSF */ stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0A09_CANTDESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (stat > status) status = stat; } } exit1: return (status); }
/*{ ** Name: RScommit - two-phase commit processing ** ** Description: ** Prepares to commit locally, commits remotely, commits locally. ** Logs each step of the commit so that a reasonable attempt can ** be made to recover if it does not complete. ** ** Inputs: ** target - target database, CDDS and connection number ** row - distribution queue row ** ** Outputs: ** none ** ** Returns: ** OK or Ingres error ** ** Side effects: ** A distributed transaction is committed using incomplete two-phase ** commit (a prepare is only done on the local database, so the target ** database is not aware it is part of a distributed transaction). */ STATUS RScommit( RS_TARGET *target, RS_TRANS_ROW *row) { i4 high = (i4)RSlocal_conn.db_no; SYSTIME now; char timestamp[21]; char timestr[27]; i4 start_entry_no; i4 prepare_entry_no; i4 remote_entry_no; i4 complete_entry_no; RS_TBLDESC *tbl = row->tbl_desc; RS_CONN *local_conn = &RSlocal_conn; RS_CONN *target_conn = &RSconns[target->conn_no]; IIAPI_GETEINFOPARM errParm; IIAPI_STATUS status; if (RStwo_phase) /* two-phase commit is on */ { start_entry_no = RS_2PC_BEGIN; prepare_entry_no = RS_PREP_COMMIT; remote_entry_no = RS_REMOTE_COMMIT; complete_entry_no = RS_2PC_END; } else /* two-phase commit is off */ { start_entry_no = RS_NPC_BEGIN; remote_entry_no = RS_NPC_REM_COMMIT; complete_entry_no = RS_NPC_END; } TMnow(&now); TMstr(&now, timestr); mktimestamp(timestr, timestamp); SIfprintf(RScommit_fp, log_format, start_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Start of commit"); SIflush(RScommit_fp); if (RStwo_phase) /* only prepare to commit if two-phase is on */ { /* ** Prepare to commit. The high value is %d, The low value is %d */ messageit(5, 1277, high, low); status = IIsw_prepareCommit(&local_conn->tranHandle, &errParm); if (status != IIAPI_ST_SUCCESS) { messageit(1, 1214); IIsw_rollback(&target_conn->tranHandle, &errParm); IIsw_rollback(&local_conn->tranHandle, &errParm); IIsw_releaseXID(&dtrans_id_handle); return (status); } SIfprintf(RScommit_fp, log_format, prepare_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Prepare to commit"); SIflush(RScommit_fp); } status = IIsw_commit(&target_conn->tranHandle, &errParm); if (status != IIAPI_ST_SUCCESS) { IIsw_rollback(&target_conn->tranHandle, &errParm); if (IIsw_rollback(&local_conn->tranHandle, &errParm) != IIAPI_ST_SUCCESS) { RSdo_recover = TRUE; messageit(1, 1215); messageit(1, 1216); } else { messageit(1, 1215); } IIsw_releaseXID(&dtrans_id_handle); SIfprintf(RScommit_fp, log_format, remote_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Local rollback"); SIfprintf(RScommit_fp, log_format, complete_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Commit complete"); SIflush(RScommit_fp); return (status); } SIfprintf(RScommit_fp, log_format, remote_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Remote commit"); SIflush(RScommit_fp); status = IIsw_commit(&local_conn->tranHandle, &errParm); if (status != IIAPI_ST_SUCCESS) { RSdo_recover = TRUE; IIsw_releaseXID(&dtrans_id_handle); return (status); } IIsw_releaseXID(&dtrans_id_handle); SIfprintf(RScommit_fp, log_format, complete_entry_no, high, low, (i4)target->db_no, tbl->table_owner, tbl->table_name, tbl->table_no, row->rep_key.trans_id, row->rep_key.seq_no, timestamp, "Commit complete"); SIflush(RScommit_fp); return (OK); }
static void gca_sm( i4 sid ) { GCA_LCB *lcb = &gca_lcb_tab[ sid ]; bool branch = FALSE; top: if ( JDBC_global.trace_level >= 5 && lsn_states[ lcb->state ].action != LSA_LABEL && lsn_states[ lcb->state ].action != LSA_GOTO ) TRdisplay( "%4d JDBC %s status 0x%x %s\n", sid, lsn_sa_names[ lsn_states[ lcb->state ].action ], lcb->statusp ? *lcb->statusp : OK, branch ? " (branch)" : "" ); branch = FALSE; switch( lsn_states[ lcb->state++ ].action ) { case LSA_INIT : /* Initialize, branch if listening */ branch = listening; lcb->sp = 0; lcb->flags = 0; if ( ! labels[ 1 ] ) { i4 i; for( i = 0; i < ARR_SIZE( lsn_states ); i++ ) if ( lsn_states[ i ].action == LSA_LABEL ) labels[ lsn_states[ i ].label ] = i + 1; } break; case LSA_GOTO : /* Branch unconditionally */ branch = TRUE; break; case LSA_GOSUB : /* Call subroutine */ lcb->ss[ lcb->sp++ ] = lcb->state; branch = TRUE; break; case LSA_RETURN : /* Return from subroutine */ lcb->state = lcb->ss[ --lcb->sp ]; break; case LSA_EXIT : /* Terminate thread */ lcb->state = 0; /* Initialize state */ /* ** Exit if there shutting down or there is an ** active listen. Otherwise, the current ** thread continues as the new listen thread. */ if ( lcb->flags & LCB_SHUTDOWN || listening ) return; break; case LSA_IF_RESUME : /* Branch if INCOMPLETE */ branch = (*lcb->statusp == E_GCFFFE_INCOMPLETE); break; case LSA_IF_TIMEOUT : /* Branch if TIMEOUT */ branch = (*lcb->statusp == E_GC0020_TIME_OUT); break; case LSA_IF_ERROR : /* Branch if status not OK */ branch = (*lcb->statusp != OK); break; case LSA_IF_SHUT : /* Branch if SHUTDOWN requested */ branch = (lcb->flags & LCB_SHUTDOWN) ? TRUE : FALSE; break; case LSA_SET_SHUT: /* Prepare to shutdown server */ GCshut(); lcb->stat = E_GC0040_CS_OK; lcb->statusp = &lcb->stat; break; case LSA_CLEAR_ERR : /* Set status to OK */ lcb->stat = OK; lcb->statusp = &lcb->stat; break; case LSA_LOG : /* Log an error */ if ( *lcb->statusp != OK && *lcb->statusp != FAIL && *lcb->statusp != E_GC0032_NO_PEER ) gcu_erlog( 0, JDBC_global.language, *lcb->statusp, NULL, 0, NULL ); break; case LSA_CHECK : /* Background checks */ jdbc_idle_check(); jdbc_pool_check(); break; case LSA_LISTEN: /* Post a listen */ { i4 timeout = -1; SYSTIME now; MEfill( sizeof(lcb->parms), 0, (PTR) &lcb->parms ); lcb->statusp = &lcb->parms.gca_ls_parms.gca_status; listening = TRUE; TMnow( &now ); if ( JDBC_global.client_idle_limit ) { i4 secs; if ( JDBC_global.client_check.TM_secs <= 0 ) secs = JDBC_global.client_idle_limit; else if ( TMcmp( &now, &JDBC_global.client_check ) < 0 ) secs = JDBC_global.client_check.TM_secs - now.TM_secs; else secs = JDBC_global.client_idle_limit / 2; if ( timeout <= 0 || secs < timeout ) timeout = secs; } if ( JDBC_global.pool_idle_limit ) { i4 secs; if ( JDBC_global.pool_check.TM_secs <= 0 ) secs = JDBC_global.pool_idle_limit; else if ( TMcmp( &now, &JDBC_global.pool_check ) < 0 ) secs = JDBC_global.pool_check.TM_secs - now.TM_secs; else secs = JDBC_global.pool_idle_limit / 2; if ( timeout <= 0 || secs < timeout ) timeout = secs; } /* ** If there is a timeout, leave some ** lee-way to ensure we actually pass ** the target check time. Also, convert ** seconds to milli-seconds. */ if ( timeout >= 0 ) timeout = (timeout + 10) * 1000; IIGCa_cb_call( &gca_cb, GCA_LISTEN, &lcb->parms, GCA_ASYNC_FLAG, (PTR)sid, timeout, &lcb->stat ); if ( lcb->stat != OK ) break; } return; case LSA_LS_RESUME : /* Resume a listen */ IIGCa_cb_call( &gca_cb, GCA_LISTEN, &lcb->parms, GCA_RESUME, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; case LSA_REPOST: /* Repost a listen */ { i4 id; listening = FALSE; for( id = 0; id < LCB_MAX; id++ ) if ( ! gca_lcb_tab[ id ].state ) { gca_sm( id ); break; } } break; case LSA_LS_DONE : /* Listen request has completed */ lcb->assoc_id = lcb->parms.gca_ls_parms.gca_assoc_id; break; case LSA_NEGOTIATE : /* Validate client */ lcb->protocol = min( lcb->parms.gca_ls_parms.gca_partner_protocol, JDBC_GCA_PROTO_LVL ); /* ** Check for shutdown/quiesce request. */ while( lcb->parms.gca_ls_parms.gca_l_aux_data > 0 ) { GCA_AUX_DATA aux_hdr; char *aux_data; i4 aux_len; MEcopy( lcb->parms.gca_ls_parms.gca_aux_data, sizeof( aux_hdr ), (PTR)&aux_hdr ); aux_data = (char *)lcb->parms.gca_ls_parms.gca_aux_data + sizeof( aux_hdr ); aux_len = aux_hdr.len_aux_data - sizeof( aux_hdr ); switch( aux_hdr.type_aux_data ) { case GCA_ID_QUIESCE : case GCA_ID_SHUTDOWN : lcb->flags |= LCB_SHUTDOWN; break; } lcb->parms.gca_ls_parms.gca_aux_data = (PTR)(aux_data + aux_len); lcb->parms.gca_ls_parms.gca_l_aux_data -= aux_hdr.len_aux_data; } break; case LSA_REJECT : /* Reject a client request */ lcb->stat = E_JD010B_NO_CLIENTS; lcb->statusp = &lcb->stat; break; case LSA_RQRESP : /* Respond to client request */ MEfill( sizeof(lcb->parms), 0, (PTR) &lcb->parms); lcb->parms.gca_rr_parms.gca_assoc_id = lcb->assoc_id; lcb->parms.gca_rr_parms.gca_request_status = *lcb->statusp; lcb->parms.gca_rr_parms.gca_local_protocol = lcb->protocol; lcb->statusp = &lcb->parms.gca_rr_parms.gca_status; IIGCa_cb_call( &gca_cb, GCA_RQRESP, &lcb->parms, GCA_ASYNC_FLAG, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; case LSA_DISASSOC : /* Disconnect association */ MEfill( sizeof(lcb->parms), 0, (PTR) &lcb->parms ); lcb->parms.gca_da_parms.gca_association_id = lcb->assoc_id; lcb->statusp = &lcb->parms.gca_da_parms.gca_status; IIGCa_cb_call( &gca_cb, GCA_DISASSOC, &lcb->parms, GCA_ASYNC_FLAG, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; case LSA_DA_RESUME : /* Resume disassociate */ IIGCa_cb_call( &gca_cb, GCA_DISASSOC, &lcb->parms, GCA_RESUME, (PTR)sid, -1, &lcb->stat ); if ( lcb->stat != OK ) break; return; } if ( branch ) lcb->state = labels[ lsn_states[ lcb->state - 1 ].label ]; goto top; }
static VOID IILQgtfGcaTraceFile( II_LBQ_CB *IIlbqcb, i4 action ) { IILQ_TRACE *msgtrc = &IIglbcb->iigl_msgtrc; FILE *trace_file = (FILE *)msgtrc->ii_tr_file; char *title = ERx("off"); SYSTIME now; char nowbuf[100]; i4 nowend; /* ** Check to see that we actually need to open ** or close the trace file. */ if ( (action == IITRC_ON && trace_file) || (action == IITRC_OFF && ! trace_file) || (action == IITRC_SWITCH && ! trace_file) ) return; if ( action == IITRC_SWITCH ) title = ERx("switched"); if ( action == IITRC_ON ) { LOCATION trace_loc; STATUS stat; /* ** If trace file name not provided, use default. */ if ( ! msgtrc->ii_tr_fname ) msgtrc->ii_tr_fname = STalloc( GCTRACEFILE ); LOfroms(FILENAME, msgtrc->ii_tr_fname, &trace_loc ); # ifdef hp9_mpe if ( msgtrc->ii_tr_flags & II_TR_APPEND ) stat = SIfopen(&trace_loc, ERx("a"), SI_TXT, 252, &trace_file); else stat = SIfopen(&trace_loc, ERx("w"), SI_TXT, 252, &trace_file); # else if ( msgtrc->ii_tr_flags & II_TR_APPEND ) stat = SIopen(&trace_loc, ERx("a"), &trace_file); else stat = SIopen(&trace_loc, ERx("w"), &trace_file); # endif if (stat != OK) { /* Simplest error path; don't want IIlocerr functionality */ IIUGerr(E_LQ0007_PRINTQRY, 0, 1, msgtrc->ii_tr_fname); /* ** We can't call IILQgstGcaSetTrace() because ** of possible conflicts with the tracing ** semaphore, so just turn off tracing here. */ msgtrc->ii_tr_flags &= ~II_TR_FILE; if ( ! (msgtrc->ii_tr_flags & II_TR_HDLR) ) IIcgct1_set_trace( IIlbqcb->ii_lq_gca, 0, NULL, NULL ); return; } msgtrc->ii_tr_file = (PTR)trace_file; title = ERx("on "); } /* Get time stamp */ TMnow(&now); TMstr(&now, nowbuf); nowend = STlength( nowbuf ); if ( nowbuf[ nowend - 1 ] == '\n' ) nowbuf[ nowend - 1 ] = EOS; SIfprintf( trace_file, ERx("---- printgca = %s session %d (%s) ---\n\n"), title, IIlbqcb->ii_lq_sid, nowbuf ); SIflush( trace_file ); if ( action != IITRC_OFF ) msgtrc->ii_tr_sid = IIlbqcb->ii_lq_sid; else { SIclose( trace_file ); msgtrc->ii_tr_file = NULL; msgtrc->ii_tr_sid = 0; msgtrc->ii_tr_flags |= II_TR_APPEND; /* Don't overwrite if reopened */ } return; } /* IILQgtfGcaTraceFile */
STATUS open_log(char *testPrefix,char *testSufix,char *username,char *errbuff) { SYSTIME atime ; char uname [20] ; char logFileName [MAX_LOC+1] ; char timestr [TEST_LINE] ; char buffer [MAX_LOC+1] ; char *dot = NULL ; char *cptr = NULL ; char year[5]; if (shellMode) STpolycat(3, testPrefix, ERx("."), testSufix, logFileName); else if (updateMode) STpolycat(2, testPrefix, ERx(".upd"), logFileName); else STpolycat(2, testPrefix, ERx(".log"), logFileName); if (outputDir) { if (outputDir_type == PATH) { STcopy(outputDir, buffer); LOfroms(PATH, buffer, &logloc); LOfstfile(logFileName, &logloc); LOtos(&logloc, &cptr); } else { LOtos(&outLoc,&cptr); } STcopy(cptr, logname); } else STcopy(logFileName, logname); if (LOfroms(FILENAME & PATH, logname, &logloc) != OK) { STprintf(errbuff,ERx("ERROR: could not get location for log file")); return(FAIL); } if (SIopen(&logloc,ERx("w"),&logptr) != OK) { STprintf(errbuff,ERx("ERROR: could not open log file")); return(FAIL); } if (!updateMode) { append_line(ERx("/*"),1); copyright_year(&year[0]); STprintf(buffer, ERx("Copyright (c) %s Ingres Corporation"), &year); append_line(buffer, 1); append_line(ERx(" "), 1); STprintf(buffer,ERx("\tTest Name: %s.%s"), testPrefix, testSufix); append_line(buffer,1); TMnow(&atime); TMstr(&atime,timestr); STprintf(buffer,ERx("\tTime: %s"),timestr); append_line(buffer,1); dot = uname; if (username == NULL || *username == '\0') IDname(&dot); else STcopy(username,uname); STprintf(buffer,ERx("\tUser Name: %s"),uname); append_line(buffer,1); STprintf(buffer, ERx("\tTerminal type: %s"), terminalType); append_line(buffer,1); append_line(ERx(" "),1); } return(OK); }
STATUS ERslookup( i4 msg_number, CL_ERR_DESC *clerror, i4 flags, char *sqlstate, char *msg_buf, i4 msg_buf_size, i4 language, i4 *msg_length, CL_ERR_DESC *err_code, i4 num_param, ER_ARGUMENT *param ) { i4 erindex; /* index of ERmulti table */ i4 status; i4 length = 0; ER_ARGUMENT *p; ER_ARGUMENT hidden[CLE_INFO_ITEMS]; /* to access info in clerror */ char tempbuf[ER_MAX_LEN+ER_MAX_NAME+2]; i4 templen; char *p_msg_buf; char *p_tempbuf; SYSTIME stime; char langbuf[ER_MAX_LANGSTR]; EX_CONTEXT context; ER_SEMFUNCS *sems; #define D_WIDTH 23 #define F_WIDTH 20 #define X_WIDTH 18 /* Validate the parameters. */ if (msg_buf == 0 || msg_buf_size == 0 || msg_length == 0) { return (ER_BADPARAM); } if (language != -1 && ERlangstr(language,langbuf) != OK) { return (ER_BADLANGUAGE); } if (!(flags & ER_NAMEONLY)) { EXdump(msg_number,0); } /* Insert timestamp if requested. */ if (flags & ER_TIMESTAMP) { if (msg_buf_size < 21) { return (ER_TOOSMALL); } TMnow(&stime); TMstr(&stime,msg_buf); length = (i4)STlength(msg_buf); msg_buf[length++] = ' '; } /* ** if (clerror && msg_number) ** look up msg_number, optional parameters in clerror->moreinfo ** else if (clerror) ** { ** if (clerror->intern) ** look up clerror.intern, optional params in clerror->moreinfo ** if (clerror->callid) ** look up system error message ** } */ if (clerror) { if (msg_number) /* Look up message after system error */ { /* ** Set up an ER_ARGUMENT that references system-dependent ** information in `clerror', and point `param' at it. */ i4 i; for (i = 0; i < CLE_INFO_ITEMS; ++i) { /* "...all of whose members begin at offset 0..." (K&R) */ hidden[i].er_value = (PTR)&clerror->moreinfo[i].data._i4; hidden[i].er_size = clerror->moreinfo[i].size; } param = &hidden[0]; num_param = CLE_INFO_ITEMS; } else /* retrieve system-dependent error messages */ { i4 len; ER_ARGUMENT argv[3]; if (clerror->intern) /* look up internal CL error */ { i4 i; for (i = 0; i < CLE_INFO_ITEMS; ++i) { argv[i].er_value = (PTR)&clerror->moreinfo[i].data._i4; argv[i].er_size = clerror->moreinfo[i].size; } /* ** Don't timestamp on recursive call, since it's been done ** already (if requested). */ if ((status = ERslookup((i4) clerror->intern, (CL_ERR_DESC*) NULL, flags & ~ER_TIMESTAMP | ER_TEXTONLY, NULL, &msg_buf[length], msg_buf_size-length, language, &len, err_code, CLE_INFO_ITEMS, argv)) != OK) { return (status); } length += len; if (clerror->callid) msg_buf[length++] = '\n'; } if (clerror->callid) /* look up system error message text */ { DESCRIPTOR msg_desc; msg_desc.desc_length = sizeof(tempbuf) - 1; msg_desc.desc_value = tempbuf; if ((status = cer_sysgetmsg(clerror, &len, &msg_desc, err_code)) != OK) { return(status); } argv[0].er_size = argv[1].er_size = argv[2].er_size = ER_PTR_ARGUMENT; argv[0].er_value = (PTR)&clerror->errnum; argv[1].er_value = (PTR)ERNAME((i4) clerror->callid); argv[2].er_value = (PTR)tempbuf; if ((status = ERslookup(ER_UNIXERROR, (CL_ERR_DESC*) NULL, flags & ~ER_TIMESTAMP | ER_TEXTONLY, NULL, &msg_buf[length], msg_buf_size - length, language, &len,err_code, 3, argv)) != OK) { return (status); } length += len; } msg_buf[*msg_length = length] = EOS; return (OK); } } /* ** Check if error message file is already opened or not yet. ** First see if the language is initialized. If not, initialize ** it and the message files. ** If it is already opened, cer_fndindex function returns the index of ** ERmulti table that internal language code is parameter 'language'. ** If not yet, it returns '-1'. */ if (cer_issem(&sems)) { if (((sems->sem_type & MU_SEM) ? (*sems->er_p_semaphore)(&sems->er_mu_sem) : (*sems->er_p_semaphore)(1, &sems->er_sem)) != OK) { sems = NULL; } } if ((erindex = cer_fndindex(language)) == -1) { if ((status = cer_nxtindex(language,&erindex)) != OK) { /* Error in initializing the language */ if (sems) { if (sems->sem_type & MU_SEM) _VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem); else _VOID_ (*sems->er_v_semaphore)(&sems->er_sem); } return (status); } } /* If the error message file is not opened, open the message file. */ if (!cer_isopen(erindex,ER_SLOWSIDE)) { if ((status = cer_sinit(language,msg_number,erindex,err_code)) != OK) { if (sems) { if (sems->sem_type & MU_SEM) _VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem); else _VOID_ (*sems->er_v_semaphore)(&sems->er_sem); } return (status); } } /* If not open then just return. */ if (!cer_isopen(erindex,ER_SLOWSIDE)) { if (sems) { if (sems->sem_type & MU_SEM) _VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem); else _VOID_ (*sems->er_v_semaphore)(&sems->er_sem); } /* ** As internal file id is '0', openning file will fail. ** In her,return status 'ER_BADOPEN' to show open fail. */ return (ER_BADOPEN); } /* ** Search message string from file and set to buffer. ** Error status on system call set to 'err_code'. */ status = cer_sstr(msg_number, sqlstate, tempbuf, msg_buf_size - length, erindex, err_code, flags & ER_TEXTONLY? ER_GET : ER_LOOKUP); if (sems) { if (sems->sem_type & MU_SEM) _VOID_ (*sems->er_v_semaphore)(&sems->er_mu_sem); else _VOID_ (*sems->er_v_semaphore)(&sems->er_sem); } if (status != OK) { return (status); } /* ** Format the text with parameters into the callers buffer. ** The message is truncated if it will not fit. */ /* Insert part of name from temporary buffer to buffer */ status = OK; templen = (i4)STlength(tempbuf); p_msg_buf = &msg_buf[length]; p_tempbuf = tempbuf; if (!(flags & ER_TEXTONLY)) { while(*p_tempbuf != '\t') { CMcpyinc(p_tempbuf,p_msg_buf); } CMcpyinc(p_tempbuf,p_msg_buf); } /* ============================================ */ /* Copy text to message substituting arguments. */ /* -------------------------------------------- */ /* (But first, declare an exception handler to */ /* catch bad params that may access violate.) */ /* ============================================ */ if (EXdeclare(er_exhandler, &context)) { u_i4 res_len; u_i4 bytes_left_in_buf; bytes_left_in_buf = (u_i4)(msg_buf_size - (p_msg_buf - msg_buf)); res_len = STlen( STncpy(p_msg_buf, ERx("*** ERslookup() ERROR: Missing or bad parameter for this message. ***"), bytes_left_in_buf )); p_msg_buf[ bytes_left_in_buf - 1 ] = EOS; p_msg_buf += res_len; *msg_length = (i4)(p_msg_buf - msg_buf); EXdelete(); return (OK); } for( ;p_tempbuf - tempbuf < templen; CMnext(p_tempbuf)) { long number; u_long unumber; double fnumber; i4 i; i4 pnum; if ( (*p_tempbuf != '%') || (flags & ER_NOPARAM) ) { if ((p_msg_buf - msg_buf) >= msg_buf_size) break; CMcpychar(p_tempbuf,p_msg_buf); CMnext(p_msg_buf); continue; } if (p_tempbuf - tempbuf + 2 >= templen) continue; CMnext(p_tempbuf); if (*p_tempbuf == '!') { if ((p_msg_buf - msg_buf) + 3 >= msg_buf_size) continue; CMcpychar(ERx("\r"),p_msg_buf); CMnext(p_msg_buf); CMcpychar(ERx("\n"),p_msg_buf); CMnext(p_msg_buf); CMcpychar(ERx("\t"),p_msg_buf); CMnext(p_msg_buf); continue; } /* ** Only works for up to 10 parameters, and makes character set ** assumptions - should be fixed. */ if ( *p_tempbuf < '0' || *p_tempbuf > '9' ) { /* treat any other character as a literal */ if ((p_msg_buf - msg_buf) >= msg_buf_size) break; if ( *p_tempbuf != '%' ) { CMcpychar("%",p_msg_buf); CMnext(p_msg_buf); } CMcpychar(p_tempbuf,p_msg_buf); CMnext(p_msg_buf); continue; } pnum = *p_tempbuf - '0'; if (pnum >= num_param) { EXdelete(); return(ER_BADPARAM); } p = ¶m[pnum]; CMnext(p_tempbuf); switch (*p_tempbuf) { case 'd': /* Convert an integer into the buffer with width D_WIDTH */ if (p->er_size == ER_PTR_ARGUMENT) /* this is ptr to i4 */ number = *(i4 *)p->er_value; else if (p->er_size == 0) /* this is a i4 */ number = (i4)(SCALARP)p->er_value; else if (p->er_size == 1) number = *(i1 *)p->er_value; else if (p->er_size == 2) number = *(i2 *)p->er_value; else if (p->er_size == 4) number = *(i4 *)p->er_value; else if (p->er_size == 8) number = *(i8 *)p->er_value; else continue; if (p_msg_buf - msg_buf + D_WIDTH >= msg_buf_size) continue; if (p->er_size == 8) { CVla8(number, p_msg_buf); } else { CVla((i4)number, p_msg_buf); } while (*p_msg_buf) CMnext(p_msg_buf); continue; case 'u': /* Convert an integer into the buffer with width D_WIDTH */ if (p->er_size == ER_PTR_ARGUMENT) /* this is ptr to u_i4 */ number = *(u_i4 *)p->er_value; else if (p->er_size == 0) /* this is a u_i4 */ number = (u_i4)(SCALARP)p->er_value; else if (p->er_size == 1) number = *(u_i1 *)p->er_value; else if (p->er_size == 2) number = *(u_i2 *)p->er_value; else if (p->er_size == 4) number = *(u_i4 *)p->er_value; else if (p->er_size == 8) number = *(u_i8 *)p->er_value; else continue; if (p_msg_buf - msg_buf + D_WIDTH >= msg_buf_size) continue; if (p->er_size == 8) { CVula8(number, p_msg_buf); } else { CVula((u_i4)number, p_msg_buf); } while (*p_msg_buf) CMnext(p_msg_buf); continue; case 'f': { i2 res_width; /* Convert a float into the buffer with width F_WIDTH */ if (p->er_size == ER_PTR_ARGUMENT) /* Pointer to a double */ fnumber = *(double *)p->er_value; else if (p->er_size == 4) fnumber = *(f4 *)p->er_value; else if (p->er_size == 8) fnumber = *(f8 *)p->er_value; else continue; if (p_msg_buf - msg_buf + F_WIDTH >= msg_buf_size) continue; /* Always convert to 'e' format. */ CVfa(fnumber, (i4) 20, (i4) 5, 'e', '.', p_msg_buf, &res_width); p_msg_buf += F_WIDTH; continue; } case 'c': /* Convert a character array into buffer. */ if (p->er_value == 0) p->er_value = (PTR)ERx("<missing>"); if ((p->er_size == 0) || (p->er_size == ER_PTR_ARGUMENT)) { for (i = 0; ((char *)p->er_value)[i]; i++) ; p->er_size = i; } if (p_msg_buf - msg_buf + p->er_size >= msg_buf_size) continue; if (p->er_size > msg_buf_size - (p_msg_buf - msg_buf)) p->er_size = (i4)(msg_buf_size - (p_msg_buf - msg_buf)); /* p->er_size=STtrmwhite(p_msg_buf);*/ MEcopy(p->er_value, p->er_size, p_msg_buf); p->er_size = (i4)STtrmnwhite(p_msg_buf, p->er_size); p_msg_buf += p->er_size; continue; case 'x': /* Convert an integer into the buffer with width D_WIDTH */ if (p->er_size == ER_PTR_ARGUMENT) unumber = *(u_i4 *)p->er_value; else if (p->er_size == 0) unumber = (u_i4)(SCALARP)p->er_value; else if (p->er_size == 1) unumber = *(u_i1 *)p->er_value; else if (p->er_size == 2) unumber = *(u_i2 *)p->er_value; else if (p->er_size == 4) unumber = *(u_i4 *)p->er_value; else if (p->er_size == 8) unumber = *(u_i8 *)p->er_value; if (p_msg_buf - msg_buf + X_WIDTH >= msg_buf_size) continue; for (i = 8; --i >= 0; ) { /* {@fix_me@} ** This is *NOT* machine independent. This relys on an ** ASCII-like character set, where the digits '0'-'9' are ** contiguous and sequential, and the characters 'A'-'F' ** are contiguous and sequential. Both ASCII and EBCDIC ** happen to be this way. */ if ((*(p_msg_buf + i) = (unumber & 0x0f) + '0') > '9') *(p_msg_buf + i) += 'A' - '9' - 1; unumber >>= 4; } p_msg_buf += 8; continue; default: continue; } } *msg_length = (i4)(p_msg_buf - msg_buf); *p_msg_buf = EOS; EXdelete(); return (OK); }
void main(int argc, char **argv) { int i; char buf[MAX_LOC]; FILE *fp; STATUS status; char *callstmt; i4 casef; char timestr[512]; SYSTIME timeval; char path[512]; char drive[2]; char current_path[512]; if (argc < 3) { SIfprintf(stdout,"Not enough parameters\n"); PCexit(FAIL); } /* ** */ if (!STbcompare(*++argv, STlength("Net"), "Net", STlength("Net"), casef )) callstmt = "@call %II_SYSTEM%\\ingres\\utility\\iisunet"; else if (!STbcompare(*argv, STlength("Dbms"), "Dbms", STlength("Dbms"), casef )) callstmt = "@call %II_SYSTEM%\\ingres\\utility\\iisudbms"; else if (!STbcompare(*argv, STlength("Star"), "Star", STlength("Star"), casef )) callstmt = "@call %II_SYSTEM%\\ingres\\utility\\iisustar"; else if (!STbcompare(*argv, STlength("Vision"), "Vision", STlength("Vision"), casef )) callstmt = "@call %II_SYSTEM%\\ingres\\utility\\iisuabf"; else if (!STbcompare(*argv, STlength("ESQL"), "ESQL", STlength("ESQL"), casef )) callstmt = "@call %II_SYSTEM%\\ingres\\utility\\iisutm"; else PCexit(FAIL); /* ** Set location and file name for the subsequent open. */ strcpy(path,*++argv); strcpy(current_path,*argv+2); strcat(path,"\\ingres\\bin\\ipsetup.bat"); LOfroms(PATH & FILENAME, path, &location); /* ** Open ipsetup.bat so we can append another line. */ if ((status = SIopen(&location, "a", &fp)) != OK) { printf("error opening file\n"); } /* ** Append another line that will call the setup bat files. */ TMnow(&timeval); TMstr(&timeval,×tr); drive[0] = path[0]; drive[1] = '\0'; /* ** Write a statement in the batch file that will set ** the current drive to the drive passed to us. */ SIfprintf(fp,"@%s:\n",drive); /* ** Write a statement in the batch file that will set ** the current path to the path passed to us. */ SIfprintf(fp,"@cd %s\n",current_path); /* ** Write a Remark as a primitive log. */ SIfprintf(fp,"@REM %s installed at %s\n",*argv,timestr); /* ** Now write the call statement that will call the appropiate ** iisu batch file. */ SIfprintf(fp,"%s\n",callstmt); }
DB_STATUS qel_c0_cre_lnk( QEF_RCB *v_qer_p ) { DB_STATUS status; QEF_CB *qef_cb = v_qer_p->qef_cb; QES_DDB_SES *dds_p = & v_qer_p->qef_cb->qef_c2_ddb_ses; QED_DDL_INFO *ddl_p = & v_qer_p->qef_r3_ddb_req.qer_d7_ddl_info; DD_0LDB_PLUS *plus_p = & ddl_p->qed_d6_tab_info_p-> dd_t9_ldb_p->dd_i2_ldb_plus; DD_CAPS *caps_p = & plus_p->dd_p3_ldb_caps; DD_LDB_DESC ldb, /* for replicating LDB desc */ *ldb_p = & ldb, *cdb_p = & dds_p->qes_d4_ddb_p-> dd_d3_cdb_info.dd_i1_ldb_desc, *ddl_ldb_p = & ddl_p->qed_d6_tab_info_p-> dd_t9_ldb_p->dd_i1_ldb_desc; QEC_D9_TABLEINFO tabinfo; /* used for table info of link */ QEC_D2_LDBIDS ldbids; /* used for internal LDB id info */ QEC_D5_LONG_LDBNAMES longnames; /* used for excessively long LDB ** name */ QEC_L16_TABLES tables; /* used for IITABLES-style info */ QEC_D6_OBJECTS objects; /* used for object info */ QEC_L6_INDEXES indexes; QEC_MIN_CAP_LVLS pre_mins, aft_mins; QEC_LINK link, /* used as global control block */ *link_p = & link; QEQ_1CAN_QRY del, ins, sel, upd, /* used for ordering canned query */ *upd_p = & upd; u_i4 len; SYSTIME now; bool log_ddl_56 = FALSE, log_err_59 = FALSE; i4 i4_1, i4_2; QEC_INDEX_ID ndx_ids[QEK_0MAX_NDX_COUNT + 1]; /* working space for index ids */ RQB_BIND rq_bind[QEC_CAT_COL_COUNT_MAX + 1]; QEC_D7_OBJECT_BASE obj_base, *base_p = & obj_base; i4 xact_mode; char *cbuf = v_qer_p->qef_cb->qef_trfmt; i4 cbufsize = v_qer_p->qef_cb->qef_trsize; if (ult_check_macro(& qef_cb->qef_trace, QEF_TRACE_DDB_LOG_DDL_56, & i4_1, & i4_2)) { log_ddl_56 = TRUE; } if (ult_check_macro(& qef_cb->qef_trace, QEF_TRACE_DDB_LOG_ERR_59, & i4_1, & i4_2)) { log_err_59 = TRUE; } sel.qeq_c2_rqf_bind_p = rq_bind; /* must set up */ del.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; ins.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; upd.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; /* 1. set up control block */ if (dds_p->qes_d7_ses_state == QES_4ST_REFRESH) /* REGISTER WITH REFRESH ? */ STRUCT_ASSIGN_MACRO(ddl_p->qed_d7_obj_id, tabinfo.d9_1_obj_id); /* yes */ else /* no */ { tabinfo.d9_1_obj_id.db_tab_base = 0; /* unknown */ tabinfo.d9_1_obj_id.db_tab_index = 0; /* always 0 for non-index */ } link_p->qec_1_ddl_info_p = ddl_p; link_p->qec_2_tableinfo_p = & tabinfo; link_p->qec_3_ldb_id = 0; link_p->qec_4_col_cnt = 0; MEfill(DB_DB_MAXNAME, ' ', link_p->qec_5_ldb_alias); link_p->qec_6_select_p = & sel; link_p->qec_7_ldbids_p = & ldbids; link_p->qec_8_longnames_p = & longnames; link_p->qec_9_tables_p = & tables; link_p->qec_10_haves = QEC_07_CREATE; if (caps_p->dd_c6_name_case == DD_2CASE_UPPER) link_p->qec_10_haves |= QEC_06_UPPER_LDB; if (caps_p->dd_c1_ldb_caps & DD_7CAP_USE_PHYSICAL_SOURCE) link_p->qec_10_haves |= QEC_10_USE_PHY_SRC; if (caps_p->dd_c2_ldb_caps & DD_201CAP_DIFF_ARCH) link_p->qec_10_haves |= QEC_11_LDB_DIFF_ARCH; /* make a copy of the LDB descriptor for non-$ingrs access if necessary */ if (ddl_ldb_p->dd_l1_ingres_b) { /* make a copy for non-$ingres access */ STRUCT_ASSIGN_MACRO(*ddl_ldb_p, ldb); ldb_p->dd_l1_ingres_b = FALSE; ldb_p->dd_l5_ldb_id = DD_0_IS_UNASSIGNED; } else { /* use provided LDB descriptor but determine if LDB has a long name */ qed_u0_trimtail( ddl_ldb_p->dd_l3_ldb_name, (u_i4) DD_256_MAXDBNAME, ldb_p->dd_l3_ldb_name); len = STlength(ldb_p->dd_l3_ldb_name); if (len > DB_DB_MAXNAME) link_p->qec_10_haves |= QEC_04_LONG_LDBNAME; ldb_p = ddl_ldb_p; } link_p->qec_11_ldb_obj_cnt = 0; link_p->qec_12_indexes_p = & indexes; link_p->qec_13_objects_p = & objects; link_p->qec_15_ndx_cnt = 0; link_p->qec_16_ndx_ids_p = ndx_ids; link_p->qec_19_ldb_p = ldb_p; link_p->qec_20_rqf_bind_p = rq_bind; link_p->qec_21_delete_p = & del; link_p->qec_22_insert_p = & ins; link_p->qec_23_update_p = & upd; status = qed_u8_gmt_now(v_qer_p, link_p->qec_24_cur_time); if (status) return(status); link_p->qec_24_cur_time[DD_25_DATE_SIZE] = EOS; link_p->qec_25_pre_mins_p = & pre_mins; link_p->qec_26_aft_mins_p = & aft_mins; link_p->qec_27_select_cnt = 0; link_p->qec_28_iistats_cnt = 0; TMnow(& now); link_p->qec_17_ts1 = now.TM_secs; link_p->qec_18_ts2 = now.TM_msecs; /* 2. inform TPF of update intention on CDB (note that only CREATE does ** LDB retrievals */ /* 2.1 2PC is required if DDL concurrency is off. */ if (dds_p->qes_d9_ctl_info & QES_01CTL_DDL_CONCURRENCY_ON) xact_mode = QEK_4TPF_1PC; else xact_mode = QEK_3TPF_UPDATE; status = qet_t5_register(v_qer_p, cdb_p, DB_SQL, xact_mode); if (status) return(status); if (log_ddl_56) { /* display beginning, CDB and LDB info */ STprintf(cbuf, "\n%s %p: %s REGISTRATION begins%s\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, IIQE_65_tracing, IIQE_62_3dots); qec_tprintf(v_qer_p, cbufsize, cbuf); STprintf(cbuf, "%s %p: ...the CDB:\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); qed_w1_prt_ldbdesc(v_qer_p, cdb_p); STprintf(cbuf, "%s %p: ...the LDB:\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb); qec_tprintf(v_qer_p, cbufsize, cbuf); qed_w1_prt_ldbdesc(v_qer_p, ldb_p); STprintf(cbuf, "\n"); qec_tprintf(v_qer_p, cbufsize, cbuf); } /* 3. update OBJECT_BASE in II_DD_DB_OBJECT_BASE */ upd_p->qeq_c1_can_id = UPD_716_DD_DDB_OBJECT_BASE; upd_p->qeq_c3_ptr_u.d7_object_base_p = base_p; upd_p->qeq_c4_ldb_p = cdb_p; status = qel_u1_update(v_qer_p, link_p); if (status) goto END_TRACING; /* 4. enter phase 1: set up necessary information */ status = qel_c1_cre_p1(v_qer_p, link_p); if (status) goto END_TRACING; /* 2. enter phase 2: promote information into STAR catalogs */ status = qel_c2_cre_p2(v_qer_p, link_p); if (status) v_qer_p->qef_cb->qef_abort = TRUE; END_TRACING: if (log_ddl_56) { /* display end tracing message */ STprintf(cbuf, "%s %p: %s REGISTRATION ends\n\n", IIQE_61_qefsess, (PTR) v_qer_p->qef_cb, IIQE_65_tracing); qec_tprintf(v_qer_p, cbufsize, cbuf); } return(status); }
DB_STATUS qeu_d6_cre_view( QEF_CB *qef_cb, QEUQ_CB *i_quq_p) { DB_STATUS status, sav_status = E_DB_OK; DB_ERROR sav_error; QEF_RCB qer, *qer_p = & qer; QES_DDB_SES *dds_p = & qef_cb->qef_c2_ddb_ses; QED_DDL_INFO *ddl_p = & qer_p->qef_r3_ddb_req.qer_d7_ddl_info; DD_LDB_DESC *cdb_p = & dds_p->qes_d4_ddb_p-> dd_d3_cdb_info.dd_i1_ldb_desc; QEC_L16_TABLES tables; /* used for IITABLES-style info */ QEC_D6_OBJECTS objects; /* used for object info */ QEC_LINK link, /* used as global control block */ *lnk_p = & link; QEQ_1CAN_QRY ins, sel, upd; /* used for ordering canned query */ RQB_BIND rq_bind[QEC_CAT_COL_COUNT_MAX + 1]; QEP_PTR_UNION ptr_u; DMU_CB *dmu_p; SYSTIME now; bool xact_b = FALSE; /* assume no begin transaction */ i4 xact_mode; ptr_u.qep_ptr_u.qep_1_ptr = i_quq_p->qeuq_dmf_cb; dmu_p = ptr_u.qep_ptr_u.qep_3_dmu_cb_p; /* 1. check input information */ if (i_quq_p->qeuq_type != QEUQCB_CB || i_quq_p->qeuq_length != sizeof(*i_quq_p)) { i_quq_p->error.err_code = E_QE0017_BAD_CB; return(E_DB_ERROR); } if ((i_quq_p->qeuq_cq == 0 || i_quq_p->qeuq_qry_tup == 0) || (i_quq_p->qeuq_ct == 0 || i_quq_p->qeuq_tre_tup == 0) || (i_quq_p->qeuq_db_id == 0) || (i_quq_p->qeuq_d_id == 0) || (i_quq_p->qeuq_dmf_cb == 0)) { i_quq_p->error.err_code = E_QE0018_BAD_PARAM_IN_CB; return(E_DB_ERROR); } /* 2. set up control information */ MEfill(sizeof(qer), '\0', (PTR) & qer); qer_p->qef_cb = qef_cb; qer_p->error.err_code = 0; qer_p->qef_r3_ddb_req.qer_d13_ctl_info = QEF_00DD_NIL_INFO; qef_cb->qef_rcb = qer_p; MEcopy(dmu_p->dmu_table_name.db_tab_name, sizeof(ddl_p->qed_d1_obj_name), ddl_p->qed_d1_obj_name); MEcopy(dmu_p->dmu_owner.db_own_name, sizeof(ddl_p->qed_d2_obj_owner), ddl_p->qed_d2_obj_owner); ddl_p->qed_d3_col_count = i_quq_p->qeuq_ano; ddl_p->qed_d4_ddb_cols_pp = NULL; ddl_p->qed_d5_qry_info_p = NULL; ddl_p->qed_d6_tab_info_p = NULL; ddl_p->qed_d7_obj_id.db_tab_base = 0; ddl_p->qed_d7_obj_id.db_tab_index = 0; ddl_p->qed_d9_reg_info_p = NULL; sel.qeq_c2_rqf_bind_p = rq_bind; /* must set up */ ins.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; upd.qeq_c2_rqf_bind_p = (RQB_BIND *) NULL; lnk_p->qec_1_ddl_info_p = ddl_p; lnk_p->qec_2_tableinfo_p = NULL; lnk_p->qec_3_ldb_id = 0; lnk_p->qec_4_col_cnt = 0; MEfill(DB_DB_MAXNAME, ' ', lnk_p->qec_5_ldb_alias); lnk_p->qec_6_select_p = & sel; lnk_p->qec_7_ldbids_p = NULL; lnk_p->qec_8_longnames_p = NULL; lnk_p->qec_9_tables_p = & tables; lnk_p->qec_10_haves = QEC_07_CREATE; lnk_p->qec_11_ldb_obj_cnt = 0; lnk_p->qec_12_indexes_p = NULL; lnk_p->qec_13_objects_p = & objects; lnk_p->qec_15_ndx_cnt = 0; lnk_p->qec_16_ndx_ids_p = NULL; lnk_p->qec_19_ldb_p = NULL; lnk_p->qec_20_rqf_bind_p = rq_bind; lnk_p->qec_21_delete_p = NULL; lnk_p->qec_22_insert_p = & ins; lnk_p->qec_23_update_p = & upd; status = qed_u8_gmt_now(qer_p, lnk_p->qec_24_cur_time); if (status) { STRUCT_ASSIGN_MACRO(qer_p->error, i_quq_p->error); return(status); } lnk_p->qec_24_cur_time[DD_25_DATE_SIZE] = EOS; lnk_p->qec_25_pre_mins_p = NULL; lnk_p->qec_26_aft_mins_p = NULL; TMnow(& now); lnk_p->qec_17_ts1 = now.TM_secs; lnk_p->qec_18_ts2 = now.TM_msecs; /* transaction semantics ** ** 1. pre-processing: ** ** 1.1 if no outstanding transaction, begin a transaction ** and set xact_b to TRUE; ** 1.2 if not in auto-commit mode, escalate transaction to MST; ** ** 2. post-processing: ** ** 2.1 if processing terminates normally, commit transaction ** only if xact_b is TRUE and not in auto-commit mode; ** 2.2 if processing terminates abnormally, abort transaction ** only if xact_b is TRUE; */ /* 2. begin a transaction if necessary */ if (qef_cb->qef_stat == QEF_NOTRAN) { status = qet_begin(qef_cb); if (status) return(status); xact_b = TRUE; } if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; /* escalate to MST */ /* 3. inform TPF of read intention on CDB */ status = qet_t5_register(qer_p, cdb_p, DB_SQL, QEK_2TPF_READ); if (status) { if (! xact_b) { STRUCT_ASSIGN_MACRO(qer_p->error, i_quq_p->error); return(status); /* ok to return */ } /* fall thru to terminate SST */ } if (status == E_DB_OK) { /* 4. set up new object base, query id */ status = qeu_10_get_obj_base(qer_p, lnk_p); if (status) { if (! xact_b) { STRUCT_ASSIGN_MACRO(qer_p->error, i_quq_p->error); return(status); /* ok to return */ } /* fall thru to terminate SST */ } else { objects.d6_4_qry_id.db_qry_high_time = now.TM_secs; objects.d6_4_qry_id.db_qry_low_time = now.TM_msecs; } } if (status == E_DB_OK) { /* 5. inform TPF of update intention on CDB */ /* 5.1 2PC is required if DDL concurrency is off. */ if (dds_p->qes_d9_ctl_info & QES_01CTL_DDL_CONCURRENCY_ON) xact_mode = QEK_4TPF_1PC; else xact_mode = QEK_3TPF_UPDATE; status = qet_t5_register(qer_p, cdb_p, DB_SQL, xact_mode); if (status) { if (! xact_b) { STRUCT_ASSIGN_MACRO(qer_p->error, i_quq_p->error); return(status); /* ok to return */ } /* fall thru to terminate SST */ } } if (status == E_DB_OK) { /* 6. update IIDD_DDB_OBJECT_BASE */ status = qeu_11_object_base(qer_p, lnk_p); if (status) qef_cb->qef_abort = TRUE; } if (status == E_DB_OK) { /* 7. update IIDD_DDB_OBJECTS */ status = qeu_12_objects(qer_p, lnk_p); if (status) qef_cb->qef_abort = TRUE; } if (status == E_DB_OK) { /* 8. update IIDD_IITABLES */ status = qeu_13_tables(qer_p, i_quq_p, lnk_p); if (status) qef_cb->qef_abort = TRUE; } if (status == E_DB_OK) { /* 9. update IIDD_COLUMNS */ status = qeu_14_columns(qer_p, i_quq_p, lnk_p); if (status) qef_cb->qef_abort = TRUE; } if (status == E_DB_OK) { /* 10. update IIDD_VIEWS */ status = qeu_15_views(qer_p, i_quq_p, lnk_p); if (status) qef_cb->qef_abort = TRUE; } if (status == E_DB_OK) { /* 11. update IIDD_DDB_TREE */ status = qeu_16_tree(qer_p, i_quq_p, lnk_p); if (status) qef_cb->qef_abort = TRUE; } if (status == E_DB_OK) { /* 12. update IIDD_DDB_DDB_DBDEPENDS */ status = qeu_17_dbdepends(qer_p, i_quq_p, lnk_p); if (status) qef_cb->qef_abort = TRUE; } /* 13. end transaction if necessary */ if (status) { /* error condition */ sav_status = status; STRUCT_ASSIGN_MACRO(qer_p->error, sav_error); if (xact_b || qef_cb->qef_abort) /* SST or abort */ status = qet_abort(qef_cb); } else { /* ok condition */ if (xact_b && qef_cb->qef_auto == QEF_ON) status = qet_commit(qef_cb); /* commit SST */ else { /* send message to commit CDB association to avoid deadlocks */ status = qed_u11_ddl_commit(qef_cb->qef_rcb); } } if (sav_status) { /* returned saved error */ STRUCT_ASSIGN_MACRO(sav_error, i_quq_p->error); return(sav_status); } else if (status) { /* return qef_cb error */ STRUCT_ASSIGN_MACRO(qef_cb->qef_rcb->error, i_quq_p->error); return(status); } return(E_DB_OK); }
DB_STATUS qee_d2_tmp( QEF_RCB *qef_rcb, QEE_DSH *dsh, ULM_RCB *ulm) { DB_STATUS status = E_DB_OK; QEF_QP_CB *qp_p = dsh->dsh_qp_ptr; QEQ_DDQ_CB *ddq_p = & qp_p->qp_ddq_cb; QEE_DDB_CB *qee_p = dsh->dsh_ddb_cb; DB_CURSOR_ID *csr_p; if (ddq_p->qeq_d3_elt_cnt > 0) { SYSTIME tm_now, tm_last; char hi_ascii[QEK_015_LEN], lo_ascii[QEK_015_LEN], /* pid_ascii[QEK_015_LEN], */ temp[QEK_050_LEN+DB_MAXNAME];/* must be > DB_MAXNAME */ DD_TAB_NAME *name_p; i4 *long_p; /* PID pid; ** an i4 ** */ i4 m, n; char *p, *q; u_i2 hi_len, /* lo_len, */ tmp_len; #define QEE_10SQL_NAME_LEN 10 /* allocate space for array of temporary-table names and ** generate their names */ /* 1. allocate array for DD_TAB_NAMEs */ ulm->ulm_psize = ddq_p->qeq_d3_elt_cnt * sizeof(DD_TAB_NAME); if (status = qec_malloc(ulm)) { qef_rcb->error.err_code = ulm->ulm_error.err_code; qed_u10_trap(); return(status); } qee_p->qee_d1_tmp_p = (DD_TAB_NAME *) ulm->ulm_pptr; /* ptr to array of DD_TAB_NAMEs */ /* 2. allocate array for i4 status */ ulm->ulm_psize = ddq_p->qeq_d3_elt_cnt * sizeof(i4); if (status = qec_malloc(ulm)) { qef_rcb->error.err_code = ulm->ulm_error.err_code; qed_u10_trap(); return(status); } qee_p->qee_d2_sts_p = (i4 *) ulm->ulm_pptr; /* ptr to array of i4s */ /* initialize both allocated arrays */ name_p = qee_p->qee_d1_tmp_p; long_p = qee_p->qee_d2_sts_p; tm_last.TM_secs = 0; tm_last.TM_msecs = 0; /* PCpid(& pid); ** get process (server) id ** CVla(pid, pid_ascii); ** convert to ascii ** */ for (n = 0; n < ddq_p->qeq_d3_elt_cnt; n++) { /* 3. generate temporary table name */ TMnow(& tm_now); if (tm_now.TM_secs == tm_last.TM_secs) { if (tm_now.TM_msecs <= tm_last.TM_msecs) tm_now.TM_msecs = tm_last.TM_msecs + 1; } CVla(tm_now.TM_secs, hi_ascii); CVla(tm_now.TM_msecs, lo_ascii); hi_len = STlength(hi_ascii); /* transpose the hi_ascii string to get lower digits */ p = hi_ascii; q = hi_ascii + hi_len - 1; /* backup past EOS */ for (m = 0; m < (i4) hi_len - 1; m++) /* do length - 1 characters */ { *p = *q; p++; q--; } STpolycat((i4) 3, /* 3 constituent pieces */ "z", lo_ascii, hi_ascii, temp); tmp_len = STlength(temp); /* use at most 10 characters */ if (tmp_len > QEE_10SQL_NAME_LEN) tmp_len = QEE_10SQL_NAME_LEN; MEmove(tmp_len, temp, ' ', sizeof(DD_TAB_NAME), (char *)name_p); STRUCT_ASSIGN_MACRO(tm_now, tm_last); /* save for comparison */ name_p++; /* pt to next slot */ /* 4. initialize status word for this table */ *long_p = QEE_00M_NIL; long_p++; /* pt to next status word */ } /* for */ } else { qee_p->qee_d1_tmp_p = (DD_TAB_NAME *) NULL; qee_p->qee_d2_sts_p = (i4 *) NULL; } /* 5. initialize */ qee_p->qee_d3_status = QEE_00Q_NIL; if (! (qp_p->qp_status & QEQP_RPT)) { /* initialize if not repeat query */ csr_p = & qee_p->qee_d4_given_qid; csr_p->db_cursor_id[0] = 0; csr_p->db_cursor_id[1] = 0; MEfill(DB_CURSOR_MAXNAME, ' ', (PTR) csr_p->db_cur_name); } csr_p = & qee_p->qee_d5_local_qid; csr_p->db_cursor_id[0] = 0; csr_p->db_cursor_id[1] = 0; MEfill(DB_CURSOR_MAXNAME, ' ', (PTR) csr_p->db_cur_name); return(status); }
DB_STATUS qeu_csecalarm( QEF_CB *qef_cb, QEUQ_CB *qeuq_cb) { DB_IIQRYTEXT *qtuple; /* Alarm text */ DB_SECALARM *atuple; /* New alarm tuple */ DB_SECALARM atuple_temp; /* Tuple to check for uniqueness */ DB_STATUS status, local_status; i4 error=0; bool transtarted = FALSE; bool tbl_opened = FALSE; i4 i; /* Querytext tuple counter */ QEF_DATA *next; /* and data pointer */ QEU_CB tranqeu; QEU_CB qeu; QEU_QUAL_PARAMS qparams; DB_QRY_ID qryid; /* Ids for query text */ QEF_DATA qef_data; bool loop=FALSE; QEF_RCB qef_rcb; i4 number; DMR_ATTR_ENTRY akey_array[3]; DMR_ATTR_ENTRY *akey_ptr_array[3]; DMT_CHAR_ENTRY char_spec; /* DMT_ALTER specification */ DMT_CB dmt_cb; DB_ERROR e_error; SXF_ACCESS access; SXF_EVENT evtype; DB_OWN_NAME objowner; do { MEfill(sizeof(objowner),' ',(PTR)&objowner); /* Validate CB and parameters */ if (qeuq_cb->qeuq_type != QEUQCB_CB || qeuq_cb->qeuq_length != sizeof(QEUQ_CB)) { status = E_DB_ERROR; error = E_QE0017_BAD_CB; break; } if ( qeuq_cb->qeuq_cq == 0 || qeuq_cb->qeuq_qry_tup == NULL || ( qeuq_cb->qeuq_uld_tup == NULL) || (qeuq_cb->qeuq_db_id == NULL) || (qeuq_cb->qeuq_d_id == 0)) { status = E_DB_ERROR; error = E_QE0018_BAD_PARAM_IN_CB; break; } qef_rcb.qef_cb = qef_cb; qef_rcb.qef_db_id = qeuq_cb->qeuq_db_id; qef_cb->qef_dbid = qeuq_cb->qeuq_db_id; /* ** Check to see if transaction is in progress, if so set a local ** transaction, otherwise we'll use the user's transaction. */ if (qef_cb->qef_stat == QEF_NOTRAN) { tranqeu.qeu_type = QEUCB_CB; tranqeu.qeu_length = sizeof(QEUCB_CB); tranqeu.qeu_db_id = qeuq_cb->qeuq_db_id; tranqeu.qeu_d_id = qeuq_cb->qeuq_d_id; tranqeu.qeu_flag = 0; tranqeu.qeu_mask = 0; status = qeu_btran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } transtarted = TRUE; } /* Escalate the transaction to MST */ if (qef_cb->qef_auto == QEF_OFF) qef_cb->qef_stat = QEF_MSTRAN; atuple = (DB_SECALARM *)qeuq_cb->qeuq_uld_tup->dt_data; /* For database alarms, make sure the database exists */ if(atuple->dba_objtype==DBOB_DATABASE && !(atuple->dba_flags&DBA_ALL_DBS)) { status=qeu_db_exists(qef_cb, qeuq_cb, (DB_DB_NAME *)&atuple->dba_objname, SXF_A_CONTROL, &objowner); if(status==E_DB_ERROR) { /* Error checking database name */ break; } else if (status==E_DB_WARN) { /* Database not found */ status=E_DB_ERROR; /* E_US2474_9332_ALARM_NO_DB */ (VOID)qef_error(9332, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple->dba_objname), (char *)&atuple->dba_objname), (PTR)&atuple->dba_objname); break; } } else if(atuple->dba_objtype==DBOB_TABLE) { /* ** Alter the table relstat to flag alarms exist. This validates that ** the table exists and ensures that we get an exclusive lock on it. */ char_spec.char_id = DMT_C_ALARM; /* create alarm code */ char_spec.char_value = DMT_C_ON; MEfill(sizeof(DMT_CB), 0, (PTR) &dmt_cb); dmt_cb.dmt_flags_mask = 0; dmt_cb.dmt_db_id = qeuq_cb->qeuq_db_id; dmt_cb.dmt_char_array.data_in_size = sizeof(DMT_CHAR_ENTRY); dmt_cb.dmt_char_array.data_address = (PTR)&char_spec; dmt_cb.length = sizeof(DMT_CB); dmt_cb.type = DMT_TABLE_CB; dmt_cb.dmt_id.db_tab_base = atuple->dba_objid.db_tab_base; dmt_cb.dmt_id.db_tab_index = atuple->dba_objid.db_tab_index; dmt_cb.dmt_tran_id = qef_cb->qef_dmt_id; status = dmf_call(DMT_ALTER, &dmt_cb); if (status != E_DB_OK) { error = dmt_cb.error.err_code; break; } } /* Get a unique query id */ TMnow((SYSTIME *)&qryid); atuple->dba_txtid.db_qry_high_time = qryid.db_qry_high_time; atuple->dba_txtid.db_qry_low_time = qryid.db_qry_low_time; /* Get a unique alarm id */ status = qea_reserveID(&atuple->dba_alarmid, qef_cb, &qef_rcb.error); if (status != E_DB_OK) { error = qef_rcb.error.err_code; break; } /* ** Generate an alarm name if needed, all blanks indicates no ** name specified. This is required for uniqueness check below. */ if(!STskipblank( (char*)&atuple->dba_alarmname, sizeof(atuple->dba_alarmname))) { status=qeu_gen_alarm_name( atuple->dba_objtype, (char*)&atuple->dba_objname, &qef_rcb, &atuple->dba_alarmid, (char*)&atuple->dba_alarmname, &error); if(status!=E_DB_OK) break; } /* Validate that the alarm name is unique */ qeu.qeu_type = QEUCB_CB; qeu.qeu_length = sizeof(QEUCB_CB); qeu.qeu_tab_id.db_tab_base = DM_B_IISECALARM_TAB_ID; qeu.qeu_tab_id.db_tab_index = DM_I_IISECALARM_TAB_ID; qeu.qeu_db_id = qeuq_cb->qeuq_db_id; qeu.qeu_lk_mode = DMT_IX; qeu.qeu_flag = DMT_U_DIRECT; qeu.qeu_access_mode = DMT_A_WRITE; qeu.qeu_mask = 0; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; atuple->dba_alarmno=0; /* Retrieve the same named alarm - if not there then ok */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_output = &qef_data; qef_data.dt_next = NULL; qef_data.dt_size = sizeof(DB_SECALARM); qef_data.dt_data = (PTR)&atuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 0; /* Not keyed */ qparams.qeu_qparms[0] = (PTR) atuple; /* What we're looking for */ qeu.qeu_qual = qeu_qalarm_by_name; qeu.qeu_qarg = &qparams; status = qeu_get(qef_cb, &qeu); if (status == E_DB_OK) /* Found the same alarm! */ { (VOID)qef_error(E_US2472_9330_ALARM_EXISTS, 0L, E_DB_ERROR, &error, &qeuq_cb->error, 1, qec_trimwhite(sizeof(atuple->dba_alarmname), (char *)&atuple->dba_alarmname), (PTR)&atuple->dba_alarmname); error = E_QE0025_USER_ERROR; break; } if (qeu.error.err_code != E_QE0015_NO_MORE_ROWS) { /* Some other error */ error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened=FALSE; /* ** Generate a unique alarm number. This is primarily for ** backwards compatibility with "anonymous" alarms which had ** to be dropped by number, not name. */ status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_input = &qef_data; qeu.qeu_output = &qef_data; qef_data.dt_next = 0; qef_data.dt_size = sizeof(DB_SECALARM); qef_data.dt_data = (PTR) &atuple_temp; qeu.qeu_getnext = QEU_REPO; qeu.qeu_klen = 3; qeu.qeu_key = akey_ptr_array; akey_ptr_array[0] = &akey_array[0]; akey_ptr_array[1] = &akey_array[1]; akey_ptr_array[2] = &akey_array[2]; akey_ptr_array[0]->attr_number = DM_1_IISECALARM_KEY; akey_ptr_array[0]->attr_operator = DMR_OP_EQ; akey_ptr_array[0]->attr_value = (char*) &atuple->dba_objtype; akey_ptr_array[1]->attr_number = DM_2_IISECALARM_KEY; akey_ptr_array[1]->attr_operator = DMR_OP_EQ; akey_ptr_array[1]->attr_value = (char*) &atuple->dba_objid.db_tab_base; akey_ptr_array[2]->attr_number = DM_3_IISECALARM_KEY; akey_ptr_array[2]->attr_operator = DMR_OP_EQ; akey_ptr_array[2]->attr_value = (char*) &atuple->dba_objid.db_tab_index; qeu.qeu_qual = 0; qeu.qeu_qarg = 0; /* ** Get all alarm tuples for this object ** and determine the next alarm number. */ status = E_DB_OK; number = 0; while (status == E_DB_OK) { status = qeu_get(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } qeu.qeu_getnext = QEU_NOREPO; qeu.qeu_klen = 0; if (atuple_temp.dba_alarmno > number) number = atuple_temp.dba_alarmno; } if (error != E_QE0015_NO_MORE_ROWS) break; /* ** We have to add 1 to derive the next alarm number. */ atuple->dba_alarmno=number+1; /* Save the alarm tuple */ status = E_DB_OK; /* Insert single alarm tuple */ qeu.qeu_count = 1; qeu.qeu_tup_length = sizeof(DB_SECALARM); qeu.qeu_input = qeuq_cb->qeuq_uld_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; /* Update all query text tuples with query id - validate list */ next = qeuq_cb->qeuq_qry_tup; for (i = 0; i < qeuq_cb->qeuq_cq; i++) { qtuple = (DB_IIQRYTEXT *)next->dt_data; next = next->dt_next; qtuple->dbq_txtid.db_qry_high_time = qryid.db_qry_high_time; qtuple->dbq_txtid.db_qry_low_time = qryid.db_qry_low_time; if (i < (qeuq_cb->qeuq_cq -1) && next == NULL) { error = E_QE0018_BAD_PARAM_IN_CB; status = E_DB_ERROR; break; } } /* for all query text tuples */ if (status != E_DB_OK) break; /* Insert all query text tuples */ qeu.qeu_tab_id.db_tab_base = DM_B_QRYTEXT_TAB_ID; qeu.qeu_tab_id.db_tab_index = 0L; status = qeu_open(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = TRUE; qeu.qeu_count = qeuq_cb->qeuq_cq; qeu.qeu_tup_length = sizeof(DB_IIQRYTEXT); qeu.qeu_input = qeuq_cb->qeuq_qry_tup; status = qeu_append(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } status = qeu_close(qef_cb, &qeu); if (status != E_DB_OK) { error = qeu.error.err_code; break; } tbl_opened = FALSE; if (transtarted) /* If we started a transaction */ { status = qeu_etran(qef_cb, &tranqeu); if (status != E_DB_OK) { error = tranqeu.error.err_code; break; } } } while(loop); /* call qef_error to handle error messages */ if(error) (VOID) qef_error(error, 0L, status, &error, &qeuq_cb->error, 0); /* Close off all the tables. */ local_status = E_DB_OK; if (tbl_opened) /* If system table opened, close it */ { local_status = qeu_close(qef_cb, &qeu); if (local_status != E_DB_OK) { (VOID) qef_error(qeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if (transtarted) /* If we started a transaction */ { local_status = qeu_atran(qef_cb, &tranqeu); if (local_status != E_DB_OK) { (VOID) qef_error(tranqeu.error.err_code, 0L, local_status, &error, &qeuq_cb->error, 0); if (local_status > status) status = local_status; } } if ( Qef_s_cb->qef_state & QEF_S_C2SECURE ) { if(atuple->dba_objtype==DBOB_DATABASE) { evtype=SXF_E_DATABASE; } else { evtype=SXF_E_TABLE; } /* ** Creating an alarm is a control operation on the base object ** (database/table) */ if(status==E_DB_OK) access=(SXF_A_CONTROL|SXF_A_SUCCESS); else access=(SXF_A_CONTROL|SXF_A_FAIL); if(qeu_secaudit(FALSE, qef_cb->qef_ses_id, (char *)&atuple->dba_objname, &objowner, sizeof(atuple->dba_objname), evtype, I_SX202D_ALARM_CREATE, access, &e_error)!=E_DB_OK) { error = e_error.err_code; status=E_DB_ERROR; } } /* ** Log QEF create error */ if(status!=E_DB_OK) { (VOID) qef_error(E_QE028B_CREATE_ALARM_ERR, 0L, local_status, &error, &qeuq_cb->error, 0); qeuq_cb->error.err_code= E_QE0025_USER_ERROR; } return (status); } /* qeu_csecalarm */
/*{ ** Name: psy_dpermit - Define a permit. ** ** INTERNAL PSF call format: status = psy_dpermit(&psy_cb, sess_cb); ** ** EXTERNAL call format: status = psy_call(PSY_DPERMIT, &psy_cb, sess_cb); ** ** Description: ** Given all of the parameters necessary to CREATE/DEFINE a permit on a ** table or view, this function will store the permission in the system ** catalogs. This will include storing the query tree in the tree table, ** storing the text of the query in the iiqrytext table (really done by ** QEF), storing a row in the protect table, and issuing an "alter table" ** operation to DMF to indicate that there are permissions on the given ** table. ** ** Inputs: ** psy_cb ** .psy_qrytext Id of query text as stored in QSF. ** .psy_cols[] Array of columns on which to grant ** permission ** .psy_numcols Number of columns listed above; 0 means ** give permission on all columns ** .psy_intree QSF id of query tree representing the ** where clause in the permit ** .psy_opctl Bit map of defined operations ** .psy_opmap Bit map of permitted operations ** .psy_user Name of user who will get permission ** .psy_terminal Terminal at which permission is given ** (blank if none specified) ** .psy_timbgn Time of day at which the permission ** begins (minutes since 00:00) ** .psy_timend Time of day at which the permission ends ** (minutes since 00:00) ** .psy_daybgn Day of week at which the permission ** begins (0 = Sunday) ** .psy_dayend Day of week at which the permission ends ** (0 = Sunday) ** .psy_grant ** PSY_CPERM CREATE/DEFINE PERMIT ** .psy_tblq head of table queue ** .psy_colq head of column queue ** .psy_usrq head of user queue ** .psy_qlen length of first iiqrytext ** .psy_flags useful info ** PSY_EXCLUDE_COLUMNS user specified a list of columns to ** which privilege should not apply ** sess_cb Pointer to session control block ** (Can be NULL) ** ** Outputs: ** psy_cb ** .psy_txtid Id of query text as stored in the ** iiqrytext system relation. ** .psy_error Filled in if error happens ** Returns: ** E_DB_OK Function completed normally. ** E_DB_WARN Function completed with warning(s); ** E_DB_ERROR Function failed; non-catastrophic error ** E_DB_FATAL Function failed; catastrophic error ** Exceptions: ** none ** ** Side Effects: ** Stores text of query in iiqrytext relation, query tree in tree ** relation, row in protect relation identifying the permit. Does ** an alter table DMF operation to indicate that there are permissions ** on the table. ** ** History: ** 02-oct-85 (jeff) ** written ** 03-sep-86 (seputis) ** changed some psy_cb. to psy_cb-> ** added .db_att_id reference ** changed rdr_cb. rdr_cb-> ** 02-dec-86 (daved) ** bug fixing. check for permit on tables owned by user and not ** view. ** 29-apr-87 (stec) ** Implemented changes for GRANT statement. ** 10-may-88 (stec) ** Make changes for db procs. ** 03-oct-88 (andre) ** Modified call to pst_rgent to pass 0 as a query mode since it is ** clearly not PSQ_DESTROY ** 06-feb-89 (ralph) ** Added support for 300 attributes: ** Use DB_COL_BITS in place of DB_MAX_COLS ** Loop over domset array using DB_COL_WORDS ** 06-mar-89 (ralph) ** GRANT Enhancements, Phase 1: ** Initialize new DB_PROTECTION fields, dbp_seq and dbp_gtype ** 03-apr-89 (ralph) ** GRANT Enhancements, Phase 2: ** Use DBGR_USER when initializing dbp_gtype ** 08-may-89 (ralph) ** Initialize reserved field to blanks (was \0) ** 04-jun-89 (ralph) ** Initialize dbp_fill1 to zero ** Fix unix portability problems ** 02-nov-89 (neil) ** Alerters: Allowed privileges for events. ** 1-mar-90 (andre) ** If processing a GRANT on tables, check if ** ALL-TO-ALL or RETRIEVE-TO-ALL has already been granted, and if so, ** mark psy_mask appropriately. ** If user tried to CREATE ALL/RETRIEVE-TO-ALL, and one already exists, ** skip to the exit. ** 12-mar-90 (andre) ** set rdr_2types_mask to 0. ** 22-may-90 (teg) ** init rdr_instr to RDF_NO_INSTR ** 08-aug-90 (ralph) ** Initialize new fields in iiprotect tuple ** 14-dec-90 (ralph) ** Disallow use of GRANT by non-DBA if xORANGE ** 11-jan-90 (ralph) ** Allow user "$ingres" to use GRANT if xORANGE. ** This was done for CREATEDB (UPGRADEFE). ** 20-feb-91 (andre) ** For CREATE/DEFINE PERMIT, grantee type was stored in ** psy_cb->psy_gtype. ** 24-jun-91 (andre) ** IIPROTECT tuples for table permits will contain exactly one ** privilege. IIQRYTEXT template built for table-wide privileges ** contains a placeholder for a privilege name which will be filled in ** with each of the table-wide privileges being granted, one at a time. ** PSY_CB.psy_opmap will be set to correspond with privilege name ** stored in the IIQRYTEXT permit. ** 16-jul-91 (andre) ** responsibility for splitting permit tuples will passed on to ** qeu_cprot(). If a permit specified only one privilege, we will ** substitute the appropriate privilege name here and will not ask ** qeu_cprot() to split tuples. ** 06-aug-91 (andre) ** before proceeding to CREATE a permit on a view owned by the current ** user, we will call psy_tbl_grant_check() to ensure that this user ** may create a permit on his view. If the object is not owned by the ** current user, we will not try to verify that the user may ** CREATE/DEFINE a permit since (until the relevant FE changes are ** made) we intend to continue allowing any user with CATUPD to ** CREATE/DEFINE permits on catalogs and the dba will be allowed to ** CREATE/DEFINE permits on extended catalogs ** 11-nov-91 (rblumer) ** merged from 6.4: 26-feb-91 (andre) ** PST_QTREE was changed to store the range table as an array of ** pointers to PST_RNGENTRY structure. ** 14-feb-92 (andre) ** we will no longer have to fill in privilege name for permits ** specifying one privilege - it will be handled in respective ** grammars. ** 15-jun-92 (barbara) ** For Sybil, change interface to pst_rgent(), Star returns from ** psy_dpermit before permits get stored. ** 07-jul-92 (andre) ** DB_PROTECTION tuple will contain an indicator of how the permit was ** created, i.e. whether it was created using SQL or QUEL and if the ** former, then whether it was created using GRANT statement. Having ** this information will facilitate merging similar and identical ** permit tuples. ** 14-jul-92 (andre) ** semantics of GRANT ALL [PRIVILEGES] is different from that of ** CREATE PERMIT ALL in that the former (as dictated by SQL92) means ** "grant all privileges which the current auth id posesses WGO" ** whereas the latter (as is presently interpreted) means "grant all ** privileges that can be defined on the object" which in case of ** tables and views means SELECT, INSERT, DELETE, UPDATE. ** psy_tbl_grant_check() (function responsible for determining whether ** a user may grant specified privilege on a specified table or view) ** will have to be notified whether we are processing GRANT ALL. Its ** behaviour will change as follows: ** - if processing GRANT ALL and psy_tbl_grant_check() determines ** that the user does not possess some (but not all) of the ** privileges passed to it by the caller it will not treat it as an ** error, but will instead inform the caller of privileges that the ** user does not posess, ** - if processing GRANT ALL and psy_tbl_grant_check() determines ** that the user does not possess any of the privileges passed to ** it by the caller it will treat it as an error ** - if processing a statement other than GRANT ALL and ** psy_tbl_grant_check() determines that the user does not possess ** some of the privileges passed to it by the caller it will treat ** it as an error ** 16-jul-92 (andre) ** if a permit being created depends on some privileges, build a ** structure describing these privileges and store its address in ** rdf_cb->rdr_indep. ** 18-jul-92 (andre) ** we will no longer be telling QEF to turn off DMT_ALL_PROT or ** DMT_RETRIEVE_PRO when a user creates ALL/RETRIEVE TO ALL permit. ** QEF will figure out on its own whether PUBLIC now has RETRIEVE or ** ALL on a table/view ** 20-jul-92 (andre) ** if user specified a list of columns to which privilege(s) should ** not apply, set dbp_domset correctly ** 03-aug-92 (barbara) ** Invalidate base table infoblk from RDF cache for CREATE PERMIT ** and CREATE SEC_ALARM. ** 16-sep-92 (andre) ** privilege maps are build using bitwise ops, so care should be ** exercised when accessing it using BT*() functions ** 17-jun-93 (andre) ** changed interface of psy_secaudit() to accept PSS_SESBLK ** 5-jul-93 (robf) ** changed interface of psy_secaudit() to accept security label ** 7-jan-94 (swm) ** Bug #58635 ** Added PTR cast for qsf_owner which has changed type to PTR. ** 06-mar-96 (nanpr01) ** Move the QSF request block initialization up. because if ** pst_rgnent returns a failure status code, subsequent QSF ** calls get bad control block error. */ DB_STATUS psy_dpermit( PSY_CB *psy_cb, PSS_SESBLK *sess_cb) { RDF_CB rdf_cb; register RDR_RB *rdf_rb = &rdf_cb.rdf_rb; QSF_RCB qsf_rb; DB_STATUS status; DB_STATUS stat; DB_PROTECTION ptuple; register DB_PROTECTION *protup = &ptuple; i4 *domset = ptuple.dbp_domset; register i4 i, j; i4 err_code; PSS_RNGTAB *rngvar; PSS_USRRANGE *rngtab; PST_PROCEDURE *pnode; PST_QTREE *qtree; DB_ERROR *err_blk = &psy_cb->psy_error; i4 textlen; i4 tree_lock = 0; i4 text_lock = 0; DB_TAB_ID tabids[PST_NUMVARS]; PSQ_INDEP_OBJECTS indep_objs; PSQ_OBJPRIV obj_priv; /* space for independent DELETE */ PSQ_COLPRIV col_privs[2]; /* ** space for independent INSERT and ** UPDATE */ PST_VRMAP varmap; PSY_TBL *psy_tbl; DB_TIME_ID timeid; DB_NAME *objname; /* ** For CREATE/DEFINE PERMIT execute code below. */ /* initialize the QSF control block */ qsf_rb.qsf_type = QSFRB_CB; qsf_rb.qsf_ascii_id = QSFRB_ASCII_ID; qsf_rb.qsf_length = sizeof(qsf_rb); qsf_rb.qsf_owner = (PTR)DB_PSF_ID; qsf_rb.qsf_sid = sess_cb->pss_sessid; rngtab = &sess_cb->pss_auxrng; /* table info is stored in the only entry in the table queue */ psy_tbl = (PSY_TBL *) psy_cb->psy_tblq.q_next; status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID, (DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL, &psy_tbl->psy_tabid, TRUE, &rngvar, (i4) 0, err_blk); if (DB_FAILURE_MACRO(status)) goto exit; /* In STAR, we do not actually store permits */ if (sess_cb->pss_distrib & DB_3_DDB_SESS) { qsf_rb.qsf_lk_state = QSO_EXLOCK; goto exit; } /* Fill in the RDF request block */ pst_rdfcb_init(&rdf_cb, sess_cb); /* The table which is receiving the permit */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, rdf_rb->rdr_tabid); /* Tell RDF we're doing a permit definition */ rdf_rb->rdr_update_op = RDR_APPEND; rdf_rb->rdr_types_mask = RDR_PROTECT; rdf_rb->rdr_qrytuple = (PTR) protup; /* initialize independent object structure */ indep_objs.psq_objs = (PSQ_OBJ *) NULL; indep_objs.psq_objprivs = (PSQ_OBJPRIV *) NULL; indep_objs.psq_colprivs = (PSQ_COLPRIV *) NULL; indep_objs.psq_grantee = &sess_cb->pss_user; rdf_rb->rdr_indep = (PTR) &indep_objs; /* ** populate the IIPROTECT tuple */ /* Zero out the template */ (VOID)MEfill(sizeof(ptuple), (u_char) 0, (PTR) protup); /* store grantee type */ protup->dbp_gtype = psy_cb->psy_gtype; /* Init reserved block */ (VOID)MEfill(sizeof(protup->dbp_reserve), (u_char) ' ', (PTR) protup->dbp_reserve); /* Init obj name */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabnm, protup->dbp_obname); /*@FIX_ME@ Where does this come from? */ protup->dbp_obstat = ' '; /* store the object type indicator */ if (psy_tbl->psy_mask & PSY_OBJ_IS_TABLE) { protup->dbp_obtype = DBOB_TABLE; } else if (psy_tbl->psy_mask & PSY_OBJ_IS_VIEW) { protup->dbp_obtype = DBOB_VIEW; } else { protup->dbp_obtype = DBOB_INDEX; } STRUCT_ASSIGN_MACRO(psy_tbl->psy_owner, protup->dbp_obown); STRUCT_ASSIGN_MACRO(sess_cb->pss_user, protup->dbp_grantor); TMnow((SYSTIME *)&timeid); protup->dbp_timestamp.db_tim_high_time = timeid.db_tim_high_time; protup->dbp_timestamp.db_tim_low_time = timeid.db_tim_low_time; /* The table on which we're giving permission */ STRUCT_ASSIGN_MACRO(psy_tbl->psy_tabid, protup->dbp_tabid); /* Beginning and ending times of day */ protup->dbp_pdbgn = psy_cb->psy_timbgn; protup->dbp_pdend = psy_cb->psy_timend; /* Beginning and ending days of week */ protup->dbp_pwbgn = psy_cb->psy_daybgn; protup->dbp_pwend = psy_cb->psy_dayend; if (psy_cb->psy_numcols != 0 && ~psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS) { /* user specified a list of columns to which privilege(s) will apply */ /* Bit map of permitted columns */ psy_fill_attmap(domset, ((i4) 0)); for (i = 0; i < psy_cb->psy_numcols; i++) { BTset((i4)psy_cb->psy_cols[i].db_att_id, (char *) domset); } } else { /* ** user specified table-wide privilege(s) or a list of columns L s.t. ** privilege(s) will apply to the entire table except for columns in L */ psy_fill_attmap(domset, ~((i4) 0)); if (psy_cb->psy_flags & PSY_EXCLUDE_COLUMNS) { /* ** exclude specified columns from the list of columns to which ** privilege(s) will apply */ for (i = 0; i < psy_cb->psy_numcols; i++) { BTclear((i4) psy_cb->psy_cols[i].db_att_id, (char *) domset); } } } if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW) { /* ** if view is owned by the current user, psy_tbl_grant_check() will ** determine if the permit can, indeed, be created; as long as we are ** preserving the kludge that allows users with CATUPD create permits on ** catalogs and DBAs to create permits on extended catalogs, we shall ** not call psy_tbl_grant_check() on view not owned by the current user, ** since it is likely to result in psy_tbl_grant_check() complaining ** about inadequate permissions */ if (!MEcmp((PTR) &rngvar->pss_ownname, (PTR) &sess_cb->pss_user, sizeof(sess_cb->pss_user))) { i4 tbl_wide_privs; PSY_COL_PRIVS col_specific_privs, *csp, indep_col_specific_privs; DB_TAB_ID indep_id; i4 indep_tbl_wide_privs; bool insuf_privs, quel_view; i4 val1, val2; /* ** build maps of table-wide and column-specific privileges for ** psy_tbl_grant_check() ** if a column list was specified with CREATE PERMIT and ** privileges specified in the statement include a set of ** privileges S s.t. for all P in S, P can only be specified as ** table-wide with GRANT statement (currently this includes ** SELECT, INSERT, DELETE), we will make ** psy_tbl_grant_check() think that privileges in S are ** table-wide. ** This will work correctly since if the view was defined over ** some objects owned by other user(s), for every P in S we ** would need table-wide privilege WGO on the underlying object. ** ** For the purposes of providing more descriptive output for ** trace point ps131, if column-list was specified, we will pass ** the map of attributes even if column-specific UPDATE was not ** specified */ if (psy_cb->psy_numcols != 0 && (psy_cb->psy_opmap & DB_REPLACE || ult_check_macro(&sess_cb->pss_trace, 3, &val1, &val2) ) ) { i4 *ip; csp = &col_specific_privs; /* ** column-specific UPDATE privilege will not be translated into ** a table-wide privilege since GRANT allows for specification ** of column-specific UPDATE privilege */ csp->psy_col_privs = psy_cb->psy_opmap & DB_REPLACE; tbl_wide_privs = psy_cb->psy_opmap & ~DB_REPLACE; /* ** if creating a permit on a set of columns and UPDATE is not ** one of the privileges named in the statement, store the ** attribute map in the first element of the attribute map list */ ip = (csp->psy_col_privs) ? csp->psy_attmap[PSY_UPDATE_ATTRMAP].map : csp->psy_attmap->map; /* copy the attribute map */ for (i = 0; i < DB_COL_WORDS; i++, ip++) { *ip = domset[i]; } } else { tbl_wide_privs = psy_cb->psy_opmap; csp = (PSY_COL_PRIVS *) NULL; } status = psy_tbl_grant_check(sess_cb, (i4) PSQ_PROT, &rngvar->pss_tabid, &tbl_wide_privs, csp, &indep_id, &indep_tbl_wide_privs, &indep_col_specific_privs, psy_cb->psy_flags, &insuf_privs, &quel_view, &psy_cb->psy_error); if (DB_FAILURE_MACRO(status)) { goto exit; } if (insuf_privs) { /* must audit failure to create a permit */ if ( Psf_srvblk->psf_capabilities & PSF_C_C2SECURE ) { DB_ERROR e_error; /* Must audit CREATE PERMIT failure. */ status = psy_secaudit(FALSE, sess_cb, (char *)&rngvar->pss_tabdesc->tbl_name, &rngvar->pss_tabdesc->tbl_owner, sizeof(DB_TAB_NAME), SXF_E_TABLE, I_SX2016_PROT_TAB_CREATE, SXF_A_FAIL | SXF_A_CREATE, &e_error); status = (status > E_DB_ERROR) ? status : E_DB_ERROR; } goto exit; } else if (quel_view) { goto exit; } /* ** If user is trying to grant one or more of ** INSERT/DELETE/UPDATE on his/her view whose underlying table ** or view is owned by another user, psy_tbl_grant_check() will ** return id of the underlying object along with map of ** privileges. We will convert maps of independent privileges ** into elements of independent privilege list and pass them ** along to QEF */ if ( indep_id.db_tab_base != (i4) 0 && ( indep_id.db_tab_base != rngvar->pss_tabid.db_tab_base || indep_id.db_tab_index != rngvar->pss_tabid.db_tab_index ) ) { if (indep_tbl_wide_privs & DB_DELETE) { /* ** the only expected independent table-wide privilege ** is DELETE */ obj_priv.psq_next = (PSQ_OBJPRIV *) NULL; obj_priv.psq_objtype = PSQ_OBJTYPE_IS_TABLE; obj_priv.psq_privmap = (i4) DB_DELETE; obj_priv.psq_objid.db_tab_base = indep_id.db_tab_base; obj_priv.psq_objid.db_tab_index = indep_id.db_tab_index; indep_objs.psq_objprivs = &obj_priv; } if (indep_col_specific_privs.psy_col_privs) { i4 i, j; PSQ_COLPRIV *csp; i4 *att_map, *p; i4 priv_map = 0; /* ** privilege map is built using bitwise operators, but ** here using BTnext() makes code much more palatable, ** so convert a privilege map */ if (indep_col_specific_privs.psy_col_privs & DB_APPEND) BTset(DB_APPP, (char *) &priv_map); if (indep_col_specific_privs.psy_col_privs & DB_REPLACE) BTset(DB_REPP, (char *) &priv_map); for (i = -1, csp = col_privs; (i = BTnext(i, (char *) &priv_map, BITS_IN(priv_map))) != -1; csp++ ) { csp->psq_next = indep_objs.psq_colprivs; indep_objs.psq_colprivs = csp; csp->psq_objtype = PSQ_OBJTYPE_IS_TABLE; csp->psq_tabid.db_tab_base = indep_id.db_tab_base; csp->psq_tabid.db_tab_index = indep_id.db_tab_index; switch (i) { case DB_APPP: /* INSERT privilege */ { csp->psq_privmap = (i4) DB_APPEND; att_map = indep_col_specific_privs. psy_attmap[PSY_INSERT_ATTRMAP].map; break; } case DB_REPP: { csp->psq_privmap = (i4) DB_REPLACE; att_map = indep_col_specific_privs. psy_attmap[PSY_UPDATE_ATTRMAP].map; break; } } for (p = csp->psq_attrmap, j = 0; j < DB_COL_WORDS; j++) { *p++ = *att_map++; } } } } } else { /* ** either this is a catalog and the user has CATUPD or ** this is an extended catalog and the user is the DBA; ** since we may be allowing a user to create a permit by ** circumventing the permit system, we only need to ascertain that ** this is an SQL view */ i4 issql = 0; status = psy_sqlview(rngvar, sess_cb, err_blk, &issql); if (status) { goto exit; } if (!issql) { /* can only have permits on SQL views */ psf_error(3598L, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(rngvar->pss_tabname), (char *) &rngvar->pss_tabname), &rngvar->pss_tabname); status = E_DB_ERROR; goto exit; } } } /* Name of user getting permission */ STRUCT_ASSIGN_MACRO(psy_cb->psy_user, protup->dbp_owner); /* Terminal at which permission given */ STRUCT_ASSIGN_MACRO(psy_cb->psy_terminal, protup->dbp_term); /* Give RDF pointer to query tree, if any */ if (!psy_cb->psy_istree) { rdf_rb->rdr_qry_root_node = (PTR) NULL; } else { PST_VRMAP varset; i4 j; STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id); qsf_rb.qsf_lk_state = QSO_EXLOCK; status = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); goto exit; } tree_lock = qsf_rb.qsf_lk_id; pnode = (PST_PROCEDURE *) qsf_rb.qsf_root; qtree = (PST_QTREE *) pnode->pst_stmts->pst_specific.pst_tree; rdf_rb->rdr_qry_root_node = (PTR) pnode; /* check for no views in the qualification. */ (VOID)psy_varset(qtree->pst_qtree, &varset); j = BTnext(-1, (char *) &varset, BITS_IN(varset)); for ( ; j >= 0; j = BTnext(j, (char *) &varset, BITS_IN(varset))) { status = pst_rgent(sess_cb, rngtab, -1, "", PST_SHWID, (DB_TAB_NAME *) NULL, (DB_TAB_OWN *) NULL, &qtree->pst_rangetab[j]->pst_rngvar, TRUE, &rngvar, (i4) 0, err_blk); if (status) goto exit; if (rngvar->pss_tabdesc->tbl_status_mask & DMT_VIEW) { psf_error(3597L, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(rngvar->pss_tabname), (char *) &rngvar->pss_tabname), &rngvar->pss_tabname); status = E_DB_ERROR; goto exit; } } } /* Give RDF a pointer to the query text to be stored in iiqrytext */ STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id); qsf_rb.qsf_lk_state = QSO_EXLOCK; status = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_error(E_PS0D19_QSF_INFO, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, err_blk, 0); goto exit; } text_lock = qsf_rb.qsf_lk_id; MEcopy((char *) qsf_rb.qsf_root, sizeof(i4), (char *) &textlen); rdf_rb->rdr_l_querytext = textlen; rdf_rb->rdr_querytext = ((char *) qsf_rb.qsf_root) + sizeof(i4); rdf_rb->rdr_status = (sess_cb->pss_lang == DB_SQL) ? DB_SQL : 0; /* determine if the permit specifies exactly one privilege */ if (BTcount((char *) &psy_cb->psy_opmap, BITS_IN(psy_cb->psy_opmap)) > 1) { /* ** if permit specified more than one privilege, notify QEF that it will ** have to split the permit into multiple IIPROTECT tuples */ rdf_rb->rdr_instr |= RDF_SPLIT_PERM; } else if (psy_cb->psy_opmap & DB_RETRIEVE) { /* ** if qeu_cprot() will not be splitting the permit into multiple tuples ** and RETRIEVE is the privilege mentioned in it, set the two bits ** associated with DB_RETRIEVE */ psy_cb->psy_opmap |= DB_TEST | DB_AGGREGATE; psy_cb->psy_opctl |= DB_TEST | DB_AGGREGATE; } /* Null out the DMU control block pointer, just in case */ rdf_rb->rdr_dmu_cb = (PTR) NULL; /* produce list of dependent tables */ rdf_rb->rdr_cnt_base_id = 0; if (psy_cb->psy_istree && qtree->pst_qtree) { j = 0; (VOID)psy_varset(qtree->pst_qtree, &varmap); for (i = -1; (i = BTnext(i, (char*) &varmap, PST_NUMVARS)) > -1;) { /* if this is the table that is getting the permit, ignore */ if (qtree->pst_rangetab[i]->pst_rngvar.db_tab_base != psy_tbl->psy_tabid.db_tab_base || qtree->pst_rangetab[i]->pst_rngvar.db_tab_index != psy_tbl->psy_tabid.db_tab_index ) { rdf_rb->rdr_cnt_base_id++; STRUCT_ASSIGN_MACRO(qtree->pst_rangetab[i]->pst_rngvar, tabids[j++]); } } rdf_rb->rdr_base_id = tabids; } protup->dbp_popctl = psy_cb->psy_opctl; protup->dbp_popset = psy_cb->psy_opmap; /* ** store an indication of whether this permit is being created using SQL or ** QUEL */ protup->dbp_flags = (sess_cb->pss_lang == DB_SQL) ? DBP_SQL_PERM : (i2) 0; protup->dbp_flags |= DBP_65_PLUS_PERM; /* Now let RDF do all the work of the permit definition */ status = rdf_call(RDF_UPDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { if (rdf_cb.rdf_error.err_code == E_RD0002_UNKNOWN_TBL) { (VOID) psf_error(E_PS0903_TAB_NOTFOUND, 0L, PSF_USERERR, &err_code, err_blk, 1, psf_trmwhite(sizeof(psy_tbl->psy_tabnm), (char *) &psy_tbl->psy_tabnm), &psy_tbl->psy_tabnm); } else { (VOID) psf_rdf_error(RDF_UPDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } goto exit; } /* ** Invalidate base object's infoblk from RDF cache. */ pst_rdfcb_init(&rdf_cb, sess_cb); STRUCT_ASSIGN_MACRO(psy_cb->psy_tables[0], rdf_rb->rdr_tabid); status = rdf_call(RDF_INVALIDATE, (PTR) &rdf_cb); if (DB_FAILURE_MACRO(status)) { (VOID) psf_rdf_error(RDF_INVALIDATE, &rdf_cb.rdf_error, &psy_cb->psy_error); } exit: qsf_rb.qsf_lk_state = QSO_EXLOCK; if (psy_cb->psy_istree) { /* Destroy query tree */ STRUCT_ASSIGN_MACRO(psy_cb->psy_intree, qsf_rb.qsf_obj_id); if ((qsf_rb.qsf_lk_id = tree_lock) == 0) { stat = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } tree_lock = qsf_rb.qsf_lk_id; } stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } tree_lock = 0; } /* Destroy query text */ STRUCT_ASSIGN_MACRO(psy_cb->psy_qrytext, qsf_rb.qsf_obj_id); if ((qsf_rb.qsf_lk_id = text_lock) == 0) { stat = qsf_call(QSO_LOCK, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D18_QSF_LOCK, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } text_lock = qsf_rb.qsf_lk_id; } stat = qsf_call(QSO_DESTROY, &qsf_rb); if (DB_FAILURE_MACRO(stat)) { (VOID) psf_error(E_PS0D1A_QSF_DESTROY, qsf_rb.qsf_error.err_code, PSF_INTERR, &err_code, &psy_cb->psy_error, 0); if (!status || stat == E_DB_FATAL) status = stat; } return (status); }
void IIodbc_timeOutThread() { QUEUE *q, *p, *pq; pENV penv; pDBC pdbc; RETCODE rc; SYSTIME expire_time; TM_STAMP stamp; char stampStr[TM_SIZE_STAMP]; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread() with timeout %d\n", IIodbc_cb.timeout); while(TRUE) { /* ** Search the pool every thirty seconds and check for expired ** connections. Force disconnect and free from the pool ** if the connection handle has passed the expiration time. ** Note that the CLI and driver connection handles are not ** freed. */ PCsleep(30000); TMget_stamp(&stamp); TMstamp_str(&stamp, stampStr); ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread woke up at %s\n", stampStr); TMnow(&expire_time); if (IIodbc_cb.pooling == DRIVER_POOL) { applyLock(SQL_HANDLE_IIODBC_CB, NULL); for (q = IIodbc_cb.pool_q.q_prev; q!= &IIodbc_cb.pool_q; q = p) { ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: driver pool count is %d\n", IIodbc_cb.pool_count); p = q->q_prev; pdbc = (pDBC)((pPOOL)q)->pdbc; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: found conn handle %p with time diff %d\n",pdbc, expire_time.TM_secs - pdbc->expire_time.TM_secs); if (expire_time.TM_secs - pdbc->expire_time.TM_secs > IIodbc_cb.timeout) { /* ** Note that the connection handle is not freed, only ** removed from the pool. */ ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: EXPIRED. pdbc time is %d vs %d\n", pdbc->expire_time.TM_secs, expire_time.TM_secs); rc = IIDisconnect(pdbc->hdr.driverHandle); QUremove(q); MEfree((PTR)q); IIodbc_cb.pool_count -= 1; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("new pool count is %d\n",IIodbc_cb.pool_count); applyLock(SQL_HANDLE_DBC, pdbc); pdbc->hdr.state = C2; releaseLock(SQL_HANDLE_DBC, pdbc); } } releaseLock(SQL_HANDLE_IIODBC_CB, NULL); } else { for (q = IIodbc_cb.env_q.q_prev; q!= &IIodbc_cb.env_q; q = q->q_prev) { penv = (pENV)q; TRdisplay("Found env handle %p\n",penv); applyLock(SQL_HANDLE_ENV, penv); for (pq = penv->pool_q.q_prev; pq != &penv->pool_q; pq = p) { ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("Env pool count is %d\n",penv->pool_count); p = q->q_prev; pdbc = (pDBC)((pPOOL)pq)->pdbc; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_TimeOutThread: Found conn handle %p with time diff %d\n",pdbc, expire_time.TM_secs - pdbc->expire_time.TM_secs); if (expire_time.TM_secs - pdbc->expire_time.TM_secs > 1) { ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: EXPIRED. pdbc time is %d vs %d\n", pdbc->expire_time.TM_secs, expire_time.TM_secs); rc = IIDisconnect(pdbc->hdr.driverHandle); QUremove(q); MEfree((PTR)q); penv->pool_count -= 1; ODBC_EXEC_TRACE(ODBC_EX_TRACE) ("IIodbc_timeOutThread: new pool count is %d\n", penv->pool_count); } } releaseLock(SQL_HANDLE_ENV, penv); } /* for (q = IIodbc_cb.env_q.q_prev; q!= &IIodbc_cb.env_q; q = q->q_prev) */ } /* if (IIodbc_cb.pooling == DRIVER_POOL) */ } /* while (TRUE) */ }