123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- /*
- * 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 <[email protected]>
- *
- *
- * 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:
- * [email protected]
- *
- * 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 <stdio.h>
- #include <string.h>
- #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 <name> <op> :a and <name> <op> :b and ... <name> <op> :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 <col1>,<col2>,...,<colN>
- * 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 <table> */
- 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 <name>
- * 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 <table> */
- 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++ = ' ';
- }
- /* (<col1>, <col2>, ..., <colN>) */
- 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 <table> */
- 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 <table> */
- 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 <name1>=:a,<name2>=:b,...,<nameN>=: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;
- }
|