apr_dbd_oracle.c
来自「linux网络服务器工具」· C语言 代码 · 共 1,920 行 · 第 1/5 页
C
1,920 行
static apr_status_t freeStatement(void *statement){ int rv = APR_SUCCESS; OCIStmt *stmt = ((apr_dbd_prepared_t*)statement)->stmt;#ifdef PREPARE2 OCIError *err; if (OCIHandleAlloc(dbd_oracle_env, (dvoid**)&err, OCI_HTYPE_ERROR, 0, NULL) != OCI_SUCCESS) { return APR_EGENERAL; } if (OCIStmtRelease(stmt, err, NULL, 0, OCI_DEFAULT) != OCI_SUCCESS) { rv = APR_EGENERAL; } if (OCIHandleFree(err, OCI_HTYPE_ERROR) != OCI_SUCCESS) { rv = APR_EGENERAL; }#else if (OCIHandleFree(stmt, OCI_HTYPE_STMT) != OCI_SUCCESS) { rv = APR_EGENERAL; }#endif return rv;}static int dbd_oracle_select(apr_pool_t *pool, apr_dbd_t *sql, apr_dbd_results_t **results, const char *query, int seek){ int ret = 0; apr_dbd_prepared_t *statement = NULL; ret = dbd_oracle_prepare(pool, sql, query, NULL, 0, 0, NULL, &statement); if (ret != 0) { return ret; } ret = dbd_oracle_pselect(pool, sql, results, statement, seek, NULL); if (ret != 0) { return ret; } return ret;}static int dbd_oracle_query(apr_dbd_t *sql, int *nrows, const char *query){ int ret = 0; apr_pool_t *pool; apr_dbd_prepared_t *statement = NULL; if (sql->trans && sql->trans->status == TRANS_ERROR) { return 1; } /* make our own pool so that APR allocations don't linger and so that * both Stmt and LOB handles are cleaned up (LOB handles may be * allocated when preparing APR_DBD_TYPE_CLOB/BLOBs) */ apr_pool_create(&pool, sql->pool); ret = dbd_oracle_prepare(pool, sql, query, NULL, 0, 0, NULL, &statement); if (ret == 0) { ret = dbd_oracle_pquery(pool, sql, nrows, statement, NULL); if (ret == 0) { sql->status = OCIAttrGet(statement->stmt, OCI_HTYPE_STMT, nrows, 0, OCI_ATTR_ROW_COUNT, sql->err); } } apr_pool_destroy(pool); return ret;}static const char *dbd_oracle_escape(apr_pool_t *pool, const char *arg, apr_dbd_t *sql){ return arg; /* OCI has no concept of string escape */}static int dbd_oracle_prepare(apr_pool_t *pool, apr_dbd_t *sql, const char *query, const char *label, int nargs, int nvals, apr_dbd_type_e *types, apr_dbd_prepared_t **statement){ int ret = 0; int i; apr_dbd_prepared_t *stmt ; if (*statement == NULL) { *statement = apr_pcalloc(pool, sizeof(apr_dbd_prepared_t)); } stmt = *statement; stmt->handle = sql; stmt->pool = pool; stmt->nargs = nargs; stmt->nvals = nvals; /* populate our own args, if any */ if (nargs > 0) { stmt->args = apr_pcalloc(pool, nargs*sizeof(bind_arg)); for (i = 0; i < nargs; i++) { stmt->args[i].type = types[i]; } } sql->status = OCIHandleAlloc(dbd_oracle_env, (dvoid**) &stmt->stmt, OCI_HTYPE_STMT, 0, NULL); if (sql->status != OCI_SUCCESS) { return 1; } sql->status = OCIStmtPrepare(stmt->stmt, sql->err, (text*) query, strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT); if (sql->status != OCI_SUCCESS) { OCIHandleFree(stmt->stmt, OCI_HTYPE_STMT); return 1; } apr_pool_cleanup_register(pool, stmt, freeStatement, apr_pool_cleanup_null); /* Perl gets statement type here */ sql->status = OCIAttrGet(stmt->stmt, OCI_HTYPE_STMT, &stmt->type, 0, OCI_ATTR_STMT_TYPE, sql->err); if (sql->status != OCI_SUCCESS) { return 1; }/* Perl sets PREFETCH_MEMORY here, but the docs say there's a working default */#if 0 sql->status = OCIAttrSet(stmt->stmt, OCI_HTYPE_STMT, &prefetch_size, sizeof(prefetch_size), OCI_ATTR_PREFETCH_MEMORY, sql->err); if (sql->status != OCI_SUCCESS) { return 1; }#endif if (stmt->type == OCI_STMT_SELECT) { ret = outputParams(sql, stmt); } return ret;}static void dbd_oracle_bind(apr_dbd_prepared_t *statement, const char **values){ OCIStmt *stmt = statement->stmt; apr_dbd_t *sql = statement->handle; int i, j; sb2 null_ind = -1; for (i = 0, j = 0; i < statement->nargs; i++, j++) { if (values[j] == NULL) { sql->status = OCIBindByPos(stmt, &statement->args[i].bind, sql->err, i + 1, NULL, 0, SQLT_STR, &null_ind, NULL, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT); } else { switch (statement->args[i].type) { case APR_DBD_TYPE_BLOB: { char *data = (char *)values[j]; int size = atoi((char*)values[++j]); /* skip table and column for now */ j += 2; sql->status = OCIBindByPos(stmt, &statement->args[i].bind, sql->err, i + 1, data, size, SQLT_LBI, &statement->args[i].ind, NULL, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT); } break; case APR_DBD_TYPE_CLOB: { char *data = (char *)values[j]; int size = atoi((char*)values[++j]); /* skip table and column for now */ j += 2; sql->status = OCIBindByPos(stmt, &statement->args[i].bind, sql->err, i + 1, data, size, SQLT_LNG, &statement->args[i].ind, NULL, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT); } break; default: sql->status = OCIBindByPos(stmt, &statement->args[i].bind, sql->err, i + 1, (dvoid*) values[j], strlen(values[j]) + 1, SQLT_STR, &statement->args[i].ind, NULL, (ub2) 0, (ub4) 0, (ub4 *) 0, OCI_DEFAULT); break; } } if (sql->status != OCI_SUCCESS) { return; } } return;}static int outputParams(apr_dbd_t *sql, apr_dbd_prepared_t *stmt){ OCIParam *parms; int i; ub2 paramtype[DBD_ORACLE_MAX_COLUMNS]; ub2 paramsize[DBD_ORACLE_MAX_COLUMNS]; const char *paramname[DBD_ORACLE_MAX_COLUMNS]; ub4 paramnamelen[DBD_ORACLE_MAX_COLUMNS]; int_errorcode; /* Perl uses 0 where we used 1 */ sql->status = OCIStmtExecute(sql->svc, stmt->stmt, sql->err, 0, 0, NULL, NULL, OCI_DESCRIBE_ONLY); switch (sql->status) { case OCI_SUCCESS: case OCI_SUCCESS_WITH_INFO: break; case OCI_ERROR:#ifdef DEBUG OCIErrorGet(sql->err, 1, NULL, &errorcode, sql->buf, sizeof(sql->buf), OCI_HTYPE_ERROR); printf("Describing prepared statement: %s\n", sql->buf);#endif default: return 1; } while (sql->status == OCI_SUCCESS) { sql->status = OCIParamGet(stmt->stmt, OCI_HTYPE_STMT, sql->err, (dvoid**)&parms, stmt->nout+1); switch (sql->status) { case OCI_SUCCESS: sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM, ¶mtype[stmt->nout], 0, OCI_ATTR_DATA_TYPE, sql->err); sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM, ¶msize[stmt->nout], 0, OCI_ATTR_DATA_SIZE, sql->err); sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM, ¶mname[stmt->nout], ¶mnamelen[stmt->nout], OCI_ATTR_NAME, sql->err); ++stmt->nout; } } switch (sql->status) { case OCI_SUCCESS: break; case OCI_ERROR: break; /* this is what we expect at end-of-loop */ default: return 1; } /* OK, the above works. We have the params; now OCIDefine them */ stmt->out = apr_palloc(stmt->pool, stmt->nout*sizeof(define_arg)); for (i=0; i<stmt->nout; ++i) { stmt->out[i].type = paramtype[i]; stmt->out[i].len = stmt->out[i].sz = paramsize[i]; stmt->out[i].name = apr_pstrmemdup(stmt->pool, paramname[i], paramnamelen[i]); switch (stmt->out[i].type) { default: switch (stmt->out[i].type) { case SQLT_NUM: /* 2: numeric, Perl worst case=130+38+3 */ stmt->out[i].sz = 171; break; case SQLT_CHR: /* 1: char */ case SQLT_AFC: /* 96: ANSI fixed char */ stmt->out[i].sz *= 4; /* ugh, wasteful UCS-4 handling */ break; case SQLT_DAT: /* 12: date, depends on NLS date format */ stmt->out[i].sz = 75; break; case SQLT_BIN: /* 23: raw binary, perhaps UTF-16? */ stmt->out[i].sz *= 2; break; case SQLT_RID: /* 11: rowid */ case SQLT_RDD: /* 104: rowid descriptor */ stmt->out[i].sz = 20; break; case SQLT_TIMESTAMP: /* 187: timestamp */ case SQLT_TIMESTAMP_TZ: /* 188: timestamp with time zone */ case SQLT_INTERVAL_YM: /* 189: interval year-to-month */ case SQLT_INTERVAL_DS: /* 190: interval day-to-second */ case SQLT_TIMESTAMP_LTZ: /* 232: timestamp with local time zone */ stmt->out[i].sz = 75; break; default:#ifdef DEBUG printf("Unsupported data type: %d\n", stmt->out[i].type);#endif break; } ++stmt->out[i].sz; stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz); sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, sql->err, i+1, stmt->out[i].buf.sval, stmt->out[i].sz, SQLT_STR, &stmt->out[i].ind, &stmt->out[i].len, 0, OCI_DEFAULT); break; case SQLT_LNG: /* 8: long */ stmt->out[i].sz = sql->long_size * 4 + 4; /* ugh, UCS-4 handling */ stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz); sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, sql->err, i+1, stmt->out[i].buf.raw, stmt->out[i].sz, SQLT_LVC, &stmt->out[i].ind, NULL, 0, OCI_DEFAULT); break; case SQLT_LBI: /* 24: long binary, perhaps UTF-16? */ stmt->out[i].sz = sql->long_size * 2 + 4; /* room for int prefix */ stmt->out[i].buf.raw = apr_palloc(stmt->pool, stmt->out[i].sz); sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, sql->err, i+1, stmt->out[i].buf.raw, stmt->out[i].sz, SQLT_LVB, &stmt->out[i].ind, NULL, 0, OCI_DEFAULT); break; case SQLT_BLOB: /* 113 */ case SQLT_CLOB: /* 112 *//*http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96584/oci05bnd.htm#434937*/ sql->status = OCIDescriptorAlloc(dbd_oracle_env, (dvoid**)&stmt->out[i].buf.lobval, OCI_DTYPE_LOB, 0, NULL); apr_pool_cleanup_register(stmt->pool, stmt->out[i].buf.lobval, dbd_free_lobdesc, apr_pool_cleanup_null); sql->status = OCIDefineByPos(stmt->stmt, &stmt->out[i].defn, sql->err, i+1, (dvoid*) &stmt->out[i].buf.lobval, -1, stmt->out[i].type, &stmt->out[i].ind, &stmt->out[i].len, 0, OCI_DEFAULT); break; } switch (sql->status) { case OCI_SUCCESS: break; default: return 1; } } return 0;}static int dbd_oracle_pquery(apr_pool_t *pool, apr_dbd_t *sql, int *nrows, apr_dbd_prepared_t *statement, const char **values){ OCISnapshot *oldsnapshot = NULL; OCISnapshot *newsnapshot = NULL; apr_dbd_transaction_t* trans = sql->trans; int exec_mode; int_errorcode; if (trans) { switch (trans->status) {
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?