diff options
Diffstat (limited to 'ngx_postgres-1.0/src/ngx_postgres_variable.c')
-rw-r--r-- | ngx_postgres-1.0/src/ngx_postgres_variable.c | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/ngx_postgres-1.0/src/ngx_postgres_variable.c b/ngx_postgres-1.0/src/ngx_postgres_variable.c new file mode 100644 index 0000000..e7f4f38 --- /dev/null +++ b/ngx_postgres-1.0/src/ngx_postgres_variable.c @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2010, FRiCKLE Piotr Sikora <info@frickle.com> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef DDEBUG +#define DDEBUG 0 +#endif + +#include "ngx_postgres_ddebug.h" +#include "ngx_postgres_module.h" +#include "ngx_postgres_variable.h" + + +ngx_int_t +ngx_postgres_variable_columns(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_postgres_ctx_t *pgctx; + + dd("entering: \"$postgres_columns\""); + + pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); + + if ((pgctx == NULL) || (pgctx->var_cols == NGX_ERROR)) { + v->not_found = 1; + dd("returning NGX_OK (not_found)"); + return NGX_OK; + } + + v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN); + if (v->data == NULL) { + dd("returning NGX_ERROR"); + return NGX_ERROR; + } + + v->len = ngx_sprintf(v->data, "%i", pgctx->var_cols) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + dd("returning NGX_OK"); + return NGX_OK; +} + +ngx_int_t +ngx_postgres_variable_rows(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_postgres_ctx_t *pgctx; + + dd("entering: \"$postgres_rows\""); + + pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); + + if ((pgctx == NULL) || (pgctx->var_rows == NGX_ERROR)) { + v->not_found = 1; + dd("returning NGX_OK (not_found)"); + return NGX_OK; + } + + v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN); + if (v->data == NULL) { + dd("returning NGX_ERROR"); + return NGX_ERROR; + } + + v->len = ngx_sprintf(v->data, "%i", pgctx->var_rows) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + dd("returning NGX_OK"); + return NGX_OK; +} + +ngx_int_t +ngx_postgres_variable_affected(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_postgres_ctx_t *pgctx; + + dd("entering: \"$postgres_affected\""); + + pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); + + if ((pgctx == NULL) || (pgctx->var_affected == NGX_ERROR)) { + v->not_found = 1; + dd("returning NGX_OK (not_found)"); + return NGX_OK; + } + + v->data = ngx_pnalloc(r->pool, NGX_INT32_LEN); + if (v->data == NULL) { + dd("returning NGX_ERROR"); + return NGX_ERROR; + } + + v->len = ngx_sprintf(v->data, "%i", pgctx->var_affected) - v->data; + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + + dd("returning NGX_OK"); + return NGX_OK; +} + +ngx_int_t +ngx_postgres_variable_query(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_postgres_ctx_t *pgctx; + + dd("entering: \"$postgres_query\""); + + pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); + + if ((pgctx == NULL) || (pgctx->var_query.len == 0)) { + v->not_found = 1; + dd("returning NGX_OK (not_found)"); + return NGX_OK; + } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = pgctx->var_query.len; + v->data = pgctx->var_query.data; + + dd("returning NGX_OK"); + return NGX_OK; +} + +ngx_int_t +ngx_postgres_variable_get_custom(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_postgres_variable_t *pgvar = (ngx_postgres_variable_t *) data; + ngx_postgres_ctx_t *pgctx; + ngx_str_t *store; + + dd("entering: \"$%.*s\"", (int) pgvar->var->name.len, + pgvar->var->name.data); + + pgctx = ngx_http_get_module_ctx(r, ngx_postgres_module); + + if ((pgctx == NULL) || (pgctx->variables == NULL)) { + v->not_found = 1; + dd("returning NGX_OK (not_found)"); + return NGX_OK; + } + + store = pgctx->variables->elts; + + /* idx is always valid */ + if (store[pgvar->idx].len == 0) { + v->not_found = 1; + dd("returning NGX_OK (not_found)"); + return NGX_OK; + } + + v->valid = 1; + v->no_cacheable = 0; + v->not_found = 0; + v->len = store[pgvar->idx].len; + v->data = store[pgvar->idx].data; + + dd("returning NGX_OK"); + return NGX_OK; +} + +ngx_str_t +ngx_postgres_variable_set_custom(ngx_http_request_t *r, PGresult *res, + ngx_postgres_variable_t *pgvar) +{ + ngx_http_core_loc_conf_t *clcf; + ngx_postgres_value_t *pgv; + ngx_int_t col_count, row_count, col, len; + ngx_str_t value = ngx_null_string; + + dd("entering: \"$%.*s\"", (int) pgvar->var->name.len, + pgvar->var->name.data); + + col_count = PQnfields(res); + row_count = PQntuples(res); + + pgv = &pgvar->value; + + if (pgv->column != NGX_ERROR) { + /* get column by number */ + col = pgv->column; + } else { + /* get column by name */ + col = PQfnumber(res, (char const *) pgv->col_name); + if (col == NGX_ERROR) { + if (pgv->required) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "postgres: \"postgres_set\" for variable \"$%V\"" + " requires value from column \"%s\" that wasn't" + " found in the received result-set in location" + " \"%V\"", + &pgvar->var->name, pgv->col_name, &clcf->name); + } + + dd("returning empty value"); + return value; + } + } + + if ((pgv->row >= row_count) || (col >= col_count)) { + if (pgv->required) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "postgres: \"postgres_set\" for variable \"$%V\"" + " requires value out of range of the received" + " result-set (rows:%d cols:%d) in location \"%V\"", + &pgvar->var->name, row_count, col_count, &clcf->name); + } + + dd("returning empty value"); + return value; + } + + if (PQgetisnull(res, pgv->row, col)) { + if (pgv->required) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "postgres: \"postgres_set\" for variable \"$%V\"" + " requires non-NULL value in location \"%V\"", + &pgvar->var->name, &clcf->name); + } + + dd("returning empty value"); + return value; + } + + len = PQgetlength(res, pgv->row, col); + if (len == 0) { + if (pgv->required) { + clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); + + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "postgres: \"postgres_set\" for variable \"$%V\"" + " requires non-zero length value in location \"%V\"", + &pgvar->var->name, &clcf->name); + } + + dd("returning empty value"); + return value; + } + + value.data = ngx_pnalloc(r->pool, len); + if (value.data == NULL) { + dd("returning empty value"); + return value; + } + + ngx_memcpy(value.data, PQgetvalue(res, pgv->row, col), len); + value.len = len; + + dd("returning non-empty value"); + return value; +} |