⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apr_dbd_pgsql.c

📁 Apache官方在今天放出产品系列2.2的最新版本2.2.11的源码包 最流行的HTTP服务器软件之一
💻 C
📖 第 1 页 / 共 3 页
字号:
/* Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements.  See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License.  You may obtain a copy of the License at * *     http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */#include "apu.h"#if APU_HAVE_PGSQL#include "apu_config.h"#include <ctype.h>#include <stdlib.h>#ifdef HAVE_LIBPQ_FE_H#include <libpq-fe.h>#elif defined(HAVE_POSTGRESQL_LIBPQ_FE_H)#include <postgresql/libpq-fe.h>#endif#include "apr_strings.h"#include "apr_time.h"#include "apr_buckets.h"#include "apr_dbd_internal.h"struct apr_dbd_transaction_t {    int mode;    int errnum;    apr_dbd_t *handle;};struct apr_dbd_t {    PGconn *conn;    apr_dbd_transaction_t *trans;};struct apr_dbd_results_t {    int random;    PGconn *handle;    PGresult *res;    size_t ntuples;    size_t sz;    size_t index;    apr_pool_t *pool;};struct apr_dbd_row_t {    int n;    apr_dbd_results_t *res;};struct apr_dbd_prepared_t {    const char *name;    int prepared;    int nargs;    int nvals;    apr_dbd_type_e *types;};#define dbd_pgsql_is_success(x) (((x) == PGRES_EMPTY_QUERY) \                                 || ((x) == PGRES_COMMAND_OK) \                                 || ((x) == PGRES_TUPLES_OK))static apr_status_t clear_result(void *data){    PQclear(data);    return APR_SUCCESS;}static int dbd_pgsql_select(apr_pool_t *pool, apr_dbd_t *sql,                            apr_dbd_results_t **results,                            const char *query, int seek){    PGresult *res;    int ret;    if ( sql->trans && sql->trans->errnum ) {        return sql->trans->errnum;    }    if (seek) { /* synchronous query */        if (TXN_IGNORE_ERRORS(sql->trans)) {            PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");            if (res) {                ret = PQresultStatus(res);                PQclear(res);                if (!dbd_pgsql_is_success(ret)) {                    sql->trans->errnum = ret;                    return PGRES_FATAL_ERROR;                }            } else {                return sql->trans->errnum = PGRES_FATAL_ERROR;            }        }        res = PQexec(sql->conn, query);        if (res) {            ret = PQresultStatus(res);            if (dbd_pgsql_is_success(ret)) {                ret = 0;            } else {                PQclear(res);            }        } else {            ret = PGRES_FATAL_ERROR;        }        if (ret != 0) {            if (TXN_IGNORE_ERRORS(sql->trans)) {                PGresult *res = PQexec(sql->conn,                                       "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");                if (res) {                    ret = PQresultStatus(res);                    PQclear(res);                    if (!dbd_pgsql_is_success(ret)) {                        sql->trans->errnum = ret;                        return PGRES_FATAL_ERROR;                    }                } else {                    return sql->trans->errnum = PGRES_FATAL_ERROR;                }            } else if (TXN_NOTICE_ERRORS(sql->trans)){                sql->trans->errnum = ret;            }            return ret;        } else {            if (TXN_IGNORE_ERRORS(sql->trans)) {                PGresult *res = PQexec(sql->conn,                                       "RELEASE SAVEPOINT APR_DBD_TXN_SP");                if (res) {                    ret = PQresultStatus(res);                    PQclear(res);                    if (!dbd_pgsql_is_success(ret)) {                        sql->trans->errnum = ret;                        return PGRES_FATAL_ERROR;                    }                } else {                    return sql->trans->errnum = PGRES_FATAL_ERROR;                }            }        }        if (!*results) {            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));        }        (*results)->res = res;        (*results)->ntuples = PQntuples(res);        (*results)->sz = PQnfields(res);        (*results)->random = seek;        (*results)->pool = pool;        apr_pool_cleanup_register(pool, res, clear_result,                                  apr_pool_cleanup_null);    }    else {        if (TXN_IGNORE_ERRORS(sql->trans)) {            PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");            if (res) {                ret = PQresultStatus(res);                PQclear(res);                if (!dbd_pgsql_is_success(ret)) {                    sql->trans->errnum = ret;                    return PGRES_FATAL_ERROR;                }            } else {                return sql->trans->errnum = PGRES_FATAL_ERROR;            }        }        if (PQsendQuery(sql->conn, query) == 0) {            if (TXN_IGNORE_ERRORS(sql->trans)) {                PGresult *res = PQexec(sql->conn,                                       "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");                if (res) {                    ret = PQresultStatus(res);                    PQclear(res);                    if (!dbd_pgsql_is_success(ret)) {                        sql->trans->errnum = ret;                        return PGRES_FATAL_ERROR;                    }                } else {                    return sql->trans->errnum = PGRES_FATAL_ERROR;                }            } else if (TXN_NOTICE_ERRORS(sql->trans)){                sql->trans->errnum = 1;            }            return 1;        } else {            if (TXN_IGNORE_ERRORS(sql->trans)) {                PGresult *res = PQexec(sql->conn,                                       "RELEASE SAVEPOINT APR_DBD_TXN_SP");                if (res) {                    ret = PQresultStatus(res);                    PQclear(res);                    if (!dbd_pgsql_is_success(ret)) {                        sql->trans->errnum = ret;                        return PGRES_FATAL_ERROR;                    }                } else {                    return sql->trans->errnum = PGRES_FATAL_ERROR;                }            }        }        if (*results == NULL) {            *results = apr_pcalloc(pool, sizeof(apr_dbd_results_t));        }        (*results)->random = seek;        (*results)->handle = sql->conn;        (*results)->pool = pool;    }    return 0;}static const char *dbd_pgsql_get_name(const apr_dbd_results_t *res, int n){    return (res->res ? PQfname(res->res, n) : NULL);}static int dbd_pgsql_get_row(apr_pool_t *pool, apr_dbd_results_t *res,                             apr_dbd_row_t **rowp, int rownum){    apr_dbd_row_t *row = *rowp;    int sequential = ((rownum >= 0) && res->random) ? 0 : 1;    if (row == NULL) {        row = apr_palloc(pool, sizeof(apr_dbd_row_t));        *rowp = row;        row->res = res;        if ( sequential ) {            row->n = 0;        }        else {            if (rownum > 0) {                row->n = --rownum;            }            else {                return -1; /* invalid row */            }        }    }    else {        if ( sequential ) {            ++row->n;        }        else {            if (rownum > 0) {                row->n = --rownum;            }            else {                return -1; /* invalid row */            }        }    }    if (res->random) {        if ((row->n >= 0) && (size_t)row->n >= res->ntuples) {            *rowp = NULL;            apr_pool_cleanup_run(pool, res->res, clear_result);            res->res = NULL;            return -1;        }    }    else {        if ((row->n >= 0) && (size_t)row->n >= res->ntuples) {            /* no data; we have to fetch some */            row->n -= res->ntuples;            if (res->res != NULL) {                PQclear(res->res);            }            res->res = PQgetResult(res->handle);            if (res->res) {                res->ntuples = PQntuples(res->res);                while (res->ntuples == 0) {                    /* if we got an empty result, clear it, wait a mo, try                     * again */                    PQclear(res->res);                    apr_sleep(100000);        /* 0.1 secs */                    res->res = PQgetResult(res->handle);                    if (res->res) {                        res->ntuples = PQntuples(res->res);                    }                    else {                        return -1;                    }                }                if (res->sz == 0) {                    res->sz = PQnfields(res->res);                }            }            else {                return -1;            }        }    }    return 0;}static const char *dbd_pgsql_get_entry(const apr_dbd_row_t *row, int n){    return PQgetvalue(row->res->res, row->n, n);}static apr_status_t dbd_pgsql_datum_get(const apr_dbd_row_t *row, int n,                                        apr_dbd_type_e type, void *data){    if (PQgetisnull(row->res->res, row->n, n)) {        return APR_ENOENT;    }    switch (type) {    case APR_DBD_TYPE_TINY:        *(char*)data = atoi(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_UTINY:        *(unsigned char*)data = atoi(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_SHORT:        *(short*)data = atoi(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_USHORT:        *(unsigned short*)data = atoi(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_INT:        *(int*)data = atoi(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_UINT:        *(unsigned int*)data = atoi(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_LONG:        *(long*)data = atol(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_ULONG:        *(unsigned long*)data = atol(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_LONGLONG:        *(apr_int64_t*)data = apr_atoi64(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_ULONGLONG:        *(apr_uint64_t*)data = apr_atoi64(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_FLOAT:        *(float*)data = (float)atof(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_DOUBLE:        *(double*)data = atof(PQgetvalue(row->res->res, row->n, n));        break;    case APR_DBD_TYPE_STRING:    case APR_DBD_TYPE_TEXT:    case APR_DBD_TYPE_TIME:    case APR_DBD_TYPE_DATE:    case APR_DBD_TYPE_DATETIME:    case APR_DBD_TYPE_TIMESTAMP:    case APR_DBD_TYPE_ZTIMESTAMP:        *(char**)data = PQgetvalue(row->res->res, row->n, n);        break;    case APR_DBD_TYPE_BLOB:    case APR_DBD_TYPE_CLOB:        {        apr_bucket *e;        apr_bucket_brigade *b = (apr_bucket_brigade*)data;        e = apr_bucket_pool_create(PQgetvalue(row->res->res, row->n, n),                                   PQgetlength(row->res->res, row->n, n),                                   row->res->pool, b->bucket_alloc);        APR_BRIGADE_INSERT_TAIL(b, e);        }        break;    case APR_DBD_TYPE_NULL:        *(void**)data = NULL;        break;    default:        return APR_EGENERAL;    }    return APR_SUCCESS;}static const char *dbd_pgsql_error(apr_dbd_t *sql, int n){    return PQerrorMessage(sql->conn);}static int dbd_pgsql_query(apr_dbd_t *sql, int *nrows, const char *query){    PGresult *res;    int ret;    if (sql->trans && sql->trans->errnum) {        return sql->trans->errnum;    }    if (TXN_IGNORE_ERRORS(sql->trans)) {        PGresult *res = PQexec(sql->conn, "SAVEPOINT APR_DBD_TXN_SP");        if (res) {            ret = PQresultStatus(res);            PQclear(res);            if (!dbd_pgsql_is_success(ret)) {                sql->trans->errnum = ret;                return PGRES_FATAL_ERROR;            }        } else {            return sql->trans->errnum = PGRES_FATAL_ERROR;        }    }    res = PQexec(sql->conn, query);    if (res) {        ret = PQresultStatus(res);        if (dbd_pgsql_is_success(ret)) {            /* ugh, making 0 return-success doesn't fit */            ret = 0;        }        *nrows = atoi(PQcmdTuples(res));        PQclear(res);    }    else {        ret = PGRES_FATAL_ERROR;    }        if (ret != 0){        if (TXN_IGNORE_ERRORS(sql->trans)) {            PGresult *res = PQexec(sql->conn,                                   "ROLLBACK TO SAVEPOINT APR_DBD_TXN_SP");            if (res) {                ret = PQresultStatus(res);                PQclear(res);                if (!dbd_pgsql_is_success(ret)) {                    sql->trans->errnum = ret;                    return PGRES_FATAL_ERROR;                }            } else {                sql->trans->errnum = ret;                return PGRES_FATAL_ERROR;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -