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,                                     &paramtype[stmt->nout],                                     0, OCI_ATTR_DATA_TYPE, sql->err);            sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM,                                     &paramsize[stmt->nout],                                     0, OCI_ATTR_DATA_SIZE, sql->err);            sql->status = OCIAttrGet(parms, OCI_DTYPE_PARAM,                                     &paramname[stmt->nout],                                     &paramnamelen[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 + -
显示快捷键?