/* * It is assumed throughout this file that sqlbuf size is large enough. * Any paranoid checks should be performed outside. * * The code looks a bit ugly. This is for speed. * Please, don't add calls to sprintf(), etc. * * Copyright (C) 2005 RingCentral Inc. * Created by Dmitry Semyonov * * * This file is part of ser, a free SIP server. * * ser is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version * * For a license to use the ser software under conditions * other than those described here, or to purchase support for this * software, please contact iptel.org by e-mail at the following addresses: * info@iptel.org * * ser is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include #include #include "common.h" #include "prepare.h" #if SQL_STMT_BUFF_SZ < 1024 #warning It is not recommended to set SQL_STMT_BUFF_SZ to less than 1K #endif static char sqlbuf[SQL_STMT_BUFF_SZ]; static char *sqlbuf_pos = NULL; static const char sql_eq_char = '='; /* * ' is null ' or * ' is not null ' * depending on _op. */ void prepare_null(db_op_t *_op) { static const char sql_str_eq[] = " is null"; static const size_t sql_str_eq_len = sizeof(sql_str_eq) - 1; static const char sql_str_ne[] = " is not null"; static const size_t sql_str_ne_len = sizeof(sql_str_ne) - 1; if (_op == NULL || strcmp(*_op, OP_EQ) == 0) { memcpy(sqlbuf_pos, sql_str_eq, sql_str_eq_len); sqlbuf_pos += sql_str_eq_len; } else { memcpy(sqlbuf_pos, sql_str_ne, sql_str_ne_len); sqlbuf_pos += sql_str_ne_len; } } /* * where :a and :b and ... :n * or none. */ void prepare_where(db_key_t* _k, db_op_t* _op, db_val_t* _v, int _n) { static const char sql_str[] = "where "; static const size_t sql_str_len = sizeof(sql_str) - 1; char sql_bind_char = 'a'; /* XXX: assert(_n < 'z' - 'a' + 1) */ if (_n > 0) { size_t cur_len; memcpy(sqlbuf_pos, sql_str, sql_str_len); sqlbuf_pos += sql_str_len; cur_len = strlen(*_k); memcpy(sqlbuf_pos, *_k++, cur_len); sqlbuf_pos += cur_len; if (VAL_NULL(_v++)) { prepare_null(_op); } else { /* Default operation is '=' */ if (_op == NULL) { *sqlbuf_pos++ = sql_eq_char; } else { cur_len = strlen(*_op); memcpy(sqlbuf_pos, *_op, cur_len); sqlbuf_pos += cur_len; } *sqlbuf_pos++ = ':'; *sqlbuf_pos++ = sql_bind_char++; } if (_op != NULL) ++_op; while (--_n) { *sqlbuf_pos++ = ' '; *sqlbuf_pos++ = 'a'; *sqlbuf_pos++ = 'n'; *sqlbuf_pos++ = 'd'; *sqlbuf_pos++ = ' '; cur_len = strlen(*_k); memcpy(sqlbuf_pos, *_k++, cur_len); sqlbuf_pos += cur_len; if (VAL_NULL(_v++)) { prepare_null(_op); } else { /* Default operation is '=' */ if (_op == NULL) { *sqlbuf_pos++ = sql_eq_char; } else { cur_len = strlen(*_op); memcpy(sqlbuf_pos, *_op, cur_len); sqlbuf_pos += cur_len; } *sqlbuf_pos++ = ':'; *sqlbuf_pos++ = sql_bind_char++; } if (_op != NULL) ++_op; } *sqlbuf_pos++ = ' '; } } /* * ^select ,,..., * or * ^select * */ void prepare_select(db_key_t* _c, int _nc) { static const char sql_str[] = "select "; static const size_t sql_str_len = sizeof(sql_str) - 1; memcpy(sqlbuf, sql_str, sql_str_len); sqlbuf_pos = sqlbuf + sql_str_len; if (_nc <= 0) { *sqlbuf_pos++ = '*'; } else { size_t cur_len; cur_len = strlen(*_c); memcpy(sqlbuf_pos, *_c++, cur_len); sqlbuf_pos += cur_len; while (--_nc) { *sqlbuf_pos++ = ','; cur_len = strlen(*_c); memcpy(sqlbuf_pos, *_c++, cur_len); sqlbuf_pos += cur_len; } } *sqlbuf_pos++ = ' '; } /* from */ void prepare_from(const char* _t) { static const char sql_str[] = "from "; static const size_t sql_str_len = sizeof(sql_str) - 1; size_t cur_len; memcpy(sqlbuf_pos, sql_str, sql_str_len); sqlbuf_pos += sql_str_len; cur_len = strlen(_t); memcpy(sqlbuf_pos, _t, cur_len); sqlbuf_pos += cur_len; *sqlbuf_pos++ = ' '; } /* * order by * or none */ void prepare_order_by(db_key_t _o) { if (_o != NULL) { static const char sql_str[] = "order by "; static const size_t sql_str_len = sizeof(sql_str) - 1; size_t cur_len; memcpy(sqlbuf_pos, sql_str, sql_str_len); sqlbuf_pos += sql_str_len; cur_len = strlen(_o); memcpy(sqlbuf_pos, _o, cur_len); sqlbuf_pos += cur_len; *sqlbuf_pos++ = ' '; } } /* ^insert into
*/ void prepare_insert(const char* _t) { static const char sql_str[] = "insert into "; static const size_t sql_str_len = sizeof(sql_str) - 1; size_t cur_len; memcpy(sqlbuf, sql_str, sql_str_len); sqlbuf_pos = sqlbuf + sql_str_len; cur_len = strlen(_t); memcpy(sqlbuf_pos, _t, cur_len); sqlbuf_pos += cur_len; *sqlbuf_pos++ = ' '; } /* (, , ..., ) */ void prepare_insert_columns(db_key_t* _k, int _n) { size_t cur_len; *sqlbuf_pos++ = '('; cur_len = strlen(*_k); memcpy(sqlbuf_pos, *_k++, cur_len); sqlbuf_pos += cur_len; while (--_n) { *sqlbuf_pos++ = ','; cur_len = strlen(*_k); memcpy(sqlbuf_pos, *_k++, cur_len); sqlbuf_pos += cur_len; } *sqlbuf_pos++ = ')'; *sqlbuf_pos++ = ' '; } /* values (:a, :b, ..., :n) */ void prepare_insert_values(db_val_t* _v, int _n) { static const char sql_str[] = "values ("; static const size_t sql_str_len = sizeof(sql_str) - 1; char sql_bind_char = 'a'; memcpy(sqlbuf_pos, sql_str, sql_str_len); sqlbuf_pos += sql_str_len; if (VAL_NULL(_v++)) { *sqlbuf_pos++ = 'n'; *sqlbuf_pos++ = 'u'; *sqlbuf_pos++ = 'l'; *sqlbuf_pos++ = 'l'; } else { *sqlbuf_pos++ = ':'; *sqlbuf_pos++ = sql_bind_char++; } while (--_n) { *sqlbuf_pos++ = ','; if (VAL_NULL(_v++)) { *sqlbuf_pos++ = 'n'; *sqlbuf_pos++ = 'u'; *sqlbuf_pos++ = 'l'; *sqlbuf_pos++ = 'l'; } else { *sqlbuf_pos++ = ':'; *sqlbuf_pos++ = sql_bind_char++; } } *sqlbuf_pos++ = ')'; *sqlbuf_pos++ = ' '; } /* ^delete from
*/ void prepare_delete(const char* _t) { static const char sql_str[] = "delete from "; static const size_t sql_str_len = sizeof(sql_str) - 1; size_t cur_len; memcpy(sqlbuf, sql_str, sql_str_len); sqlbuf_pos = sqlbuf + sql_str_len; cur_len = strlen(_t); memcpy(sqlbuf_pos, _t, cur_len); sqlbuf_pos += cur_len; *sqlbuf_pos++ = ' '; } /* ^update
*/ void prepare_update(const char* _t) { static const char sql_str[] = "update "; static const size_t sql_str_len = sizeof(sql_str) - 1; size_t cur_len; memcpy(sqlbuf, sql_str, sql_str_len); sqlbuf_pos = sqlbuf + sql_str_len; cur_len = strlen(_t); memcpy(sqlbuf_pos, _t, cur_len); sqlbuf_pos += cur_len; *sqlbuf_pos++ = ' '; } /* set =:a,=:b,...,=:n */ void prepare_update_set(db_key_t* _k, db_val_t* _v, int _n) { size_t cur_len; char sql_bind_char = 'a'; *sqlbuf_pos++ = 's'; *sqlbuf_pos++ = 'e'; *sqlbuf_pos++ = 't'; *sqlbuf_pos++ = ' '; cur_len = strlen(*_k); memcpy(sqlbuf_pos, *_k++, cur_len); sqlbuf_pos += cur_len; *sqlbuf_pos++ = sql_eq_char; if (VAL_NULL(_v++)) { *sqlbuf_pos++ = 'n'; *sqlbuf_pos++ = 'u'; *sqlbuf_pos++ = 'l'; *sqlbuf_pos++ = 'l'; } else { *sqlbuf_pos++ = ':'; *sqlbuf_pos++ = sql_bind_char++; } while (--_n) { *sqlbuf_pos++ = ','; cur_len = strlen(*_k); memcpy(sqlbuf_pos, *_k++, cur_len); sqlbuf_pos += cur_len; *sqlbuf_pos++ = sql_eq_char; if (VAL_NULL(_v++)) { *sqlbuf_pos++ = 'n'; *sqlbuf_pos++ = 'u'; *sqlbuf_pos++ = 'l'; *sqlbuf_pos++ = 'l'; } else { *sqlbuf_pos++ = ':'; *sqlbuf_pos++ = sql_bind_char++; } } *sqlbuf_pos++ = ' '; } const char *prepared_sql(void) { /* OCI statements should be null terminated according to OCI docs. */ *sqlbuf_pos = '\0'; return sqlbuf; } /* without trailing null character */ size_t prepared_sql_len(void) { return sqlbuf_pos - sqlbuf; }