2003-04-17 09:29:45 +08:00
|
|
|
/*
|
2003-06-15 02:16:47 +08:00
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| PHP Version 4 |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Copyright (c) 1997-2003 The PHP Group |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| This source file is subject to version 3.0 of the PHP license, |
|
|
|
|
| that is bundled with this package in the file LICENSE, and is |
|
|
|
|
| available through the world-wide-web at the following url: |
|
|
|
|
| http://www.php.net/license/3_0.txt. |
|
|
|
|
| If you did not receive a copy of the PHP license and are unable to |
|
|
|
|
| obtain it through the world-wide-web, please send a note to |
|
|
|
|
| license@php.net so we can mail you a copy immediately. |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
| Authors: Wez Furlong <wez@thebrainroom.com> |
|
|
|
|
| Tal Peer <tal@php.net> |
|
|
|
|
| Marcus Boerger <helly@php.net> |
|
|
|
|
+----------------------------------------------------------------------+
|
|
|
|
|
|
|
|
$Id$
|
2003-04-17 09:29:45 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
#define PHP_SQLITE_MODULE_VERSION "1.1-dev"
|
2003-04-18 03:13:21 +08:00
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
#include "php.h"
|
|
|
|
#include "php_ini.h"
|
|
|
|
#include "ext/standard/info.h"
|
2003-07-01 21:07:37 +08:00
|
|
|
#include "ext/session/php_session.h"
|
2003-04-17 09:29:45 +08:00
|
|
|
#include "php_sqlite.h"
|
|
|
|
|
2003-04-18 20:22:43 +08:00
|
|
|
#if HAVE_TIME_H
|
|
|
|
# include <time.h>
|
|
|
|
#endif
|
2003-06-27 22:30:26 +08:00
|
|
|
#if HAVE_UNISTD_H
|
2003-04-18 20:22:43 +08:00
|
|
|
#include <unistd.h>
|
2003-06-27 22:30:26 +08:00
|
|
|
#endif
|
2003-04-18 20:22:43 +08:00
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
#include <sqlite.h>
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
#ifdef HAVE_SPL
|
|
|
|
#include "ext/spl/php_spl.h"
|
|
|
|
#include "ext/spl/spl_functions.h"
|
|
|
|
#endif
|
|
|
|
|
2003-06-26 07:21:10 +08:00
|
|
|
#include "zend_default_classes.h"
|
2003-06-23 01:19:46 +08:00
|
|
|
|
2003-04-27 21:46:07 +08:00
|
|
|
#ifndef safe_emalloc
|
2003-06-20 04:57:11 +08:00
|
|
|
# define safe_emalloc(a,b,c) emalloc((a)*(b)+(c))
|
2003-04-27 21:46:07 +08:00
|
|
|
#endif
|
|
|
|
|
2003-06-19 03:48:02 +08:00
|
|
|
#ifndef ZEND_ENGINE_2
|
2003-06-05 06:40:00 +08:00
|
|
|
# define OnUpdateLong OnUpdateInt
|
|
|
|
#endif
|
|
|
|
|
2003-04-22 08:08:48 +08:00
|
|
|
ZEND_DECLARE_MODULE_GLOBALS(sqlite)
|
|
|
|
|
2003-07-01 21:07:37 +08:00
|
|
|
extern ps_module ps_mod_sqlite;
|
|
|
|
#define ps_sqlite_ptr &ps_mod_sqlite
|
|
|
|
|
2003-04-19 20:54:17 +08:00
|
|
|
extern int sqlite_encode_binary(const unsigned char *in, int n, unsigned char *out);
|
|
|
|
extern int sqlite_decode_binary(const unsigned char *in, unsigned char *out);
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
static unsigned char arg3_force_ref[] = {3, BYREF_NONE, BYREF_NONE, BYREF_FORCE };
|
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
static int le_sqlite_db, le_sqlite_result, le_sqlite_pdb;
|
|
|
|
|
2003-04-22 08:08:48 +08:00
|
|
|
static inline void php_sqlite_strtoupper(char *s)
|
|
|
|
{
|
2003-04-27 21:32:43 +08:00
|
|
|
while (*s!='\0') {
|
|
|
|
*s = toupper(*s);
|
|
|
|
s++;
|
|
|
|
}
|
2003-04-22 08:08:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void php_sqlite_strtolower(char *s)
|
|
|
|
{
|
2003-04-27 21:32:43 +08:00
|
|
|
while (*s!='\0') {
|
|
|
|
*s = tolower(*s);
|
|
|
|
s++;
|
|
|
|
}
|
2003-04-22 08:08:48 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* {{{ PHP_INI
|
|
|
|
*/
|
|
|
|
PHP_INI_BEGIN()
|
2003-06-05 06:40:00 +08:00
|
|
|
STD_PHP_INI_ENTRY_EX("sqlite.assoc_case", "0", PHP_INI_ALL, OnUpdateLong, assoc_case, zend_sqlite_globals, sqlite_globals, display_link_numbers)
|
2003-04-22 08:08:48 +08:00
|
|
|
PHP_INI_END()
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
#define DB_FROM_ZVAL(db, zv) ZEND_FETCH_RESOURCE2(db, struct php_sqlite_db *, zv, -1, "sqlite database", le_sqlite_db, le_sqlite_pdb)
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
#define DB_FROM_OBJECT(db, object) \
|
|
|
|
{ \
|
|
|
|
sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
|
|
|
|
db = obj->u.db; \
|
|
|
|
if (!db) { \
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "The database wasn't opened"); \
|
|
|
|
RETURN_NULL(); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define RES_FROM_OBJECT(res, object) \
|
|
|
|
{ \
|
|
|
|
sqlite_object *obj = (sqlite_object*) zend_object_store_get_object(object TSRMLS_CC); \
|
|
|
|
res = obj->u.res; \
|
|
|
|
if (!res) { \
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No result set available"); \
|
|
|
|
RETURN_NULL(); \
|
|
|
|
} \
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SQLITE_THROW(message) \
|
|
|
|
PG(suppress_errors) = 0; \
|
|
|
|
EG(exception) = sqlite_instanciate(sqlite_ce_exception, NULL TSRMLS_CC); \
|
|
|
|
{ \
|
|
|
|
zval *tmp; \
|
|
|
|
MAKE_STD_ZVAL(tmp); \
|
|
|
|
ZVAL_STRING(tmp, message, 1); \
|
|
|
|
zend_hash_update(Z_OBJPROP_P(EG(exception)), "message", sizeof("message"), (void **) message, sizeof(zval *), NULL); \
|
|
|
|
MAKE_STD_ZVAL(tmp); \
|
|
|
|
ZVAL_STRING(tmp, zend_get_executed_filename(TSRMLS_C), 1); \
|
|
|
|
zend_hash_update(Z_OBJPROP_P(EG(exception)), "file", sizeof("file"), (void **) &tmp, sizeof(zval *), NULL); \
|
|
|
|
MAKE_STD_ZVAL(tmp); \
|
|
|
|
ZVAL_LONG(tmp, zend_get_executed_lineno(TSRMLS_C)); \
|
|
|
|
zend_hash_update(Z_OBJPROP_P(EG(exception)), "line", sizeof("line"), (void **) &tmp, sizeof(zval *), NULL); \
|
|
|
|
}
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
struct php_sqlite_result {
|
2003-05-03 06:09:54 +08:00
|
|
|
struct php_sqlite_db *db;
|
2003-04-18 20:22:43 +08:00
|
|
|
sqlite_vm *vm;
|
|
|
|
int buffered;
|
2003-04-17 09:29:45 +08:00
|
|
|
int ncolumns;
|
2003-04-18 20:22:43 +08:00
|
|
|
int nrows;
|
2003-04-17 09:29:45 +08:00
|
|
|
int curr_row;
|
2003-04-18 20:22:43 +08:00
|
|
|
char **col_names;
|
|
|
|
int alloc_rows;
|
|
|
|
char **table;
|
2003-04-30 23:18:59 +08:00
|
|
|
int mode;
|
2003-04-17 09:29:45 +08:00
|
|
|
};
|
|
|
|
|
2003-04-18 04:08:00 +08:00
|
|
|
struct php_sqlite_db {
|
|
|
|
sqlite *db;
|
|
|
|
int last_err_code;
|
|
|
|
int is_persistent;
|
2003-04-19 00:30:16 +08:00
|
|
|
int rsrc_id;
|
2003-04-20 23:13:04 +08:00
|
|
|
|
|
|
|
HashTable callbacks;
|
2003-04-18 04:08:00 +08:00
|
|
|
};
|
|
|
|
|
2003-04-20 21:08:22 +08:00
|
|
|
struct php_sqlite_agg_functions {
|
2003-04-20 23:13:04 +08:00
|
|
|
struct php_sqlite_db *db;
|
|
|
|
int is_valid;
|
2003-04-20 21:08:22 +08:00
|
|
|
zval *step;
|
2003-04-20 23:13:04 +08:00
|
|
|
zval *fini;
|
2003-04-20 21:08:22 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
enum { PHPSQLITE_ASSOC = 1, PHPSQLITE_NUM = 2, PHPSQLITE_BOTH = PHPSQLITE_ASSOC|PHPSQLITE_NUM };
|
|
|
|
|
|
|
|
function_entry sqlite_functions[] = {
|
|
|
|
PHP_FE(sqlite_open, arg3_force_ref)
|
2003-04-19 00:30:16 +08:00
|
|
|
PHP_FE(sqlite_popen, arg3_force_ref)
|
2003-04-17 09:29:45 +08:00
|
|
|
PHP_FE(sqlite_close, NULL)
|
|
|
|
PHP_FE(sqlite_query, NULL)
|
2003-06-10 07:14:25 +08:00
|
|
|
PHP_FE(sqlite_array_query, NULL)
|
2003-06-26 00:59:24 +08:00
|
|
|
PHP_FE(sqlite_single_query, NULL)
|
2003-04-17 09:29:45 +08:00
|
|
|
PHP_FE(sqlite_fetch_array, NULL)
|
2003-06-27 03:26:26 +08:00
|
|
|
PHP_FE(sqlite_fetch_single, NULL)
|
|
|
|
PHP_FALIAS(sqlite_fetch_string, sqlite_fetch_single, NULL)
|
2003-06-07 03:00:16 +08:00
|
|
|
PHP_FE(sqlite_fetch_all, NULL)
|
2003-05-03 06:09:54 +08:00
|
|
|
PHP_FE(sqlite_current, NULL)
|
2003-05-03 20:51:13 +08:00
|
|
|
PHP_FE(sqlite_column, NULL)
|
2003-04-17 09:29:45 +08:00
|
|
|
PHP_FE(sqlite_libversion, NULL)
|
|
|
|
PHP_FE(sqlite_libencoding, NULL)
|
|
|
|
PHP_FE(sqlite_changes, NULL)
|
|
|
|
PHP_FE(sqlite_last_insert_rowid, NULL)
|
|
|
|
PHP_FE(sqlite_num_rows, NULL)
|
|
|
|
PHP_FE(sqlite_num_fields, NULL)
|
|
|
|
PHP_FE(sqlite_field_name, NULL)
|
|
|
|
PHP_FE(sqlite_seek, NULL)
|
2003-05-03 06:09:54 +08:00
|
|
|
PHP_FE(sqlite_rewind, NULL)
|
|
|
|
PHP_FE(sqlite_next, NULL)
|
|
|
|
PHP_FE(sqlite_has_more, NULL)
|
2003-04-17 10:20:26 +08:00
|
|
|
PHP_FE(sqlite_escape_string, NULL)
|
2003-04-18 00:57:46 +08:00
|
|
|
PHP_FE(sqlite_busy_timeout, NULL)
|
2003-04-18 04:08:00 +08:00
|
|
|
PHP_FE(sqlite_last_error, NULL)
|
|
|
|
PHP_FE(sqlite_error_string, NULL)
|
2003-04-18 20:22:43 +08:00
|
|
|
PHP_FE(sqlite_unbuffered_query, NULL)
|
2003-04-20 21:08:22 +08:00
|
|
|
PHP_FE(sqlite_create_aggregate, NULL)
|
2003-04-20 21:31:36 +08:00
|
|
|
PHP_FE(sqlite_create_function, NULL)
|
2003-06-27 05:07:07 +08:00
|
|
|
PHP_FE(sqlite_factory, arg3_force_ref)
|
2003-06-21 20:29:32 +08:00
|
|
|
PHP_FE(sqlite_udf_encode_binary, NULL)
|
|
|
|
PHP_FE(sqlite_udf_decode_binary, NULL)
|
2003-04-17 09:29:45 +08:00
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
#define PHP_ME_MAPPING(name, func_name, arg_types) \
|
|
|
|
ZEND_NAMED_FE(name, ZEND_FN(func_name), arg_types)
|
|
|
|
|
|
|
|
function_entry sqlite_funcs_db[] = {
|
|
|
|
PHP_ME_MAPPING(sqlite_db, sqlite_open, NULL)
|
2003-06-23 03:00:44 +08:00
|
|
|
/* PHP_ME_MAPPING(close, sqlite_close, NULL)*/
|
2003-06-23 01:19:46 +08:00
|
|
|
PHP_ME_MAPPING(query, sqlite_query, NULL)
|
|
|
|
PHP_ME_MAPPING(array_query, sqlite_array_query, NULL)
|
2003-06-26 00:59:24 +08:00
|
|
|
PHP_ME_MAPPING(single_query, sqlite_single_query, NULL)
|
2003-06-23 01:19:46 +08:00
|
|
|
PHP_ME_MAPPING(unbuffered_query, sqlite_unbuffered_query, NULL)
|
|
|
|
PHP_ME_MAPPING(last_insert_rowid, sqlite_last_insert_rowid, NULL)
|
|
|
|
PHP_ME_MAPPING(create_aggregate, sqlite_create_aggregate, NULL)
|
|
|
|
PHP_ME_MAPPING(create_function, sqlite_create_function, NULL)
|
|
|
|
PHP_ME_MAPPING(busy_timeout, sqlite_busy_timeout, NULL)
|
|
|
|
PHP_ME_MAPPING(last_error, sqlite_last_error, NULL)
|
|
|
|
/* PHP_ME_MAPPING(error_string, sqlite_error_string, NULL) static */
|
|
|
|
/* PHP_ME_MAPPING(escape_string, sqlite_escape_string, NULL) static */
|
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
function_entry sqlite_funcs_query[] = {
|
|
|
|
PHP_ME_MAPPING(fetch_array, sqlite_fetch_array, NULL)
|
2003-06-27 03:26:26 +08:00
|
|
|
PHP_ME_MAPPING(fetch_single, sqlite_fetch_single, NULL)
|
2003-06-23 01:19:46 +08:00
|
|
|
PHP_ME_MAPPING(fetch_all, sqlite_fetch_all, NULL)
|
|
|
|
PHP_ME_MAPPING(column, sqlite_column, NULL)
|
|
|
|
PHP_ME_MAPPING(changes, sqlite_changes, NULL)
|
|
|
|
PHP_ME_MAPPING(num_fields, sqlite_num_fields, NULL)
|
|
|
|
PHP_ME_MAPPING(field_name, sqlite_field_name, NULL)
|
|
|
|
/* spl_forward */
|
|
|
|
PHP_ME_MAPPING(current, sqlite_current, NULL)
|
|
|
|
PHP_ME_MAPPING(next, sqlite_next, NULL)
|
|
|
|
PHP_ME_MAPPING(has_more, sqlite_has_more, NULL)
|
|
|
|
/* spl_sequence */
|
|
|
|
PHP_ME_MAPPING(rewind, sqlite_rewind, NULL)
|
|
|
|
/* additional */
|
|
|
|
PHP_ME_MAPPING(num_rows, sqlite_num_rows, NULL)
|
|
|
|
PHP_ME_MAPPING(seek, sqlite_seek, NULL)
|
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
function_entry sqlite_funcs_ub_query[] = {
|
|
|
|
PHP_ME_MAPPING(fetch_array, sqlite_fetch_array, NULL)
|
2003-06-27 03:26:26 +08:00
|
|
|
PHP_ME_MAPPING(fetch_single, sqlite_fetch_single, NULL)
|
2003-06-23 01:19:46 +08:00
|
|
|
PHP_ME_MAPPING(fetch_all, sqlite_fetch_all, NULL)
|
|
|
|
PHP_ME_MAPPING(column, sqlite_column, NULL)
|
|
|
|
PHP_ME_MAPPING(changes, sqlite_changes, NULL)
|
|
|
|
PHP_ME_MAPPING(num_fields, sqlite_num_fields, NULL)
|
|
|
|
PHP_ME_MAPPING(field_name, sqlite_field_name, NULL)
|
|
|
|
/* spl_forward */
|
|
|
|
PHP_ME_MAPPING(current, sqlite_current, NULL)
|
|
|
|
PHP_ME_MAPPING(next, sqlite_next, NULL)
|
|
|
|
PHP_ME_MAPPING(has_more, sqlite_has_more, NULL)
|
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
|
|
|
|
|
|
|
function_entry sqlite_funcs_exception[] = {
|
|
|
|
{NULL, NULL, NULL}
|
|
|
|
};
|
2003-04-17 09:29:45 +08:00
|
|
|
|
|
|
|
zend_module_entry sqlite_module_entry = {
|
|
|
|
#if ZEND_MODULE_API_NO >= 20010901
|
|
|
|
STANDARD_MODULE_HEADER,
|
|
|
|
#endif
|
|
|
|
"sqlite",
|
|
|
|
sqlite_functions,
|
|
|
|
PHP_MINIT(sqlite),
|
|
|
|
NULL,
|
2003-06-23 01:19:46 +08:00
|
|
|
PHP_RINIT(sqlite),
|
2003-04-19 00:30:16 +08:00
|
|
|
PHP_RSHUTDOWN(sqlite),
|
2003-04-17 09:29:45 +08:00
|
|
|
PHP_MINFO(sqlite),
|
|
|
|
#if ZEND_MODULE_API_NO >= 20010901
|
2003-04-18 03:13:21 +08:00
|
|
|
PHP_SQLITE_MODULE_VERSION,
|
2003-04-17 09:29:45 +08:00
|
|
|
#endif
|
|
|
|
STANDARD_MODULE_PROPERTIES
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef COMPILE_DL_SQLITE
|
|
|
|
ZEND_GET_MODULE(sqlite)
|
|
|
|
#endif
|
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
static int php_sqlite_callback_invalidator(struct php_sqlite_agg_functions *funcs TSRMLS_DC)
|
|
|
|
{
|
|
|
|
if (!funcs->is_valid) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (funcs->step) {
|
|
|
|
zval_ptr_dtor(&funcs->step);
|
|
|
|
funcs->step = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (funcs->fini) {
|
|
|
|
zval_ptr_dtor(&funcs->fini);
|
|
|
|
funcs->fini = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
funcs->is_valid = 0;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void php_sqlite_callback_dtor(void *pDest)
|
|
|
|
{
|
|
|
|
struct php_sqlite_agg_functions *funcs = (struct php_sqlite_agg_functions*)pDest;
|
|
|
|
|
|
|
|
if (funcs->is_valid) {
|
|
|
|
TSRMLS_FETCH();
|
|
|
|
|
|
|
|
php_sqlite_callback_invalidator(funcs TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
static ZEND_RSRC_DTOR_FUNC(php_sqlite_db_dtor)
|
|
|
|
{
|
2003-04-19 00:30:16 +08:00
|
|
|
if (rsrc->ptr) {
|
|
|
|
struct php_sqlite_db *db = (struct php_sqlite_db*)rsrc->ptr;
|
|
|
|
sqlite_close(db->db);
|
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
zend_hash_destroy(&db->callbacks);
|
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
pefree(db, db->is_persistent);
|
2003-04-18 04:08:00 +08:00
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
rsrc->ptr = NULL;
|
|
|
|
}
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
static void real_result_dtor(struct php_sqlite_result *res TSRMLS_DC)
|
2003-04-17 09:29:45 +08:00
|
|
|
{
|
2003-04-18 20:22:43 +08:00
|
|
|
int i, j, base;
|
|
|
|
|
|
|
|
if (res->vm) {
|
|
|
|
sqlite_finalize(res->vm, NULL);
|
|
|
|
}
|
2003-04-27 21:25:10 +08:00
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
if (res->table) {
|
|
|
|
if (!res->buffered && res->nrows) {
|
2003-05-03 06:22:16 +08:00
|
|
|
res->nrows = 1; /* only one row is stored */
|
|
|
|
}
|
2003-05-03 06:17:01 +08:00
|
|
|
for (i = 0; i < res->nrows; i++) {
|
|
|
|
base = i * res->ncolumns;
|
|
|
|
for (j = 0; j < res->ncolumns; j++) {
|
|
|
|
if (res->table[base + j] != NULL) {
|
|
|
|
efree(res->table[base + j]);
|
|
|
|
}
|
2003-04-19 18:28:45 +08:00
|
|
|
}
|
2003-04-18 20:22:43 +08:00
|
|
|
}
|
|
|
|
efree(res->table);
|
|
|
|
}
|
|
|
|
if (res->col_names) {
|
|
|
|
for (j = 0; j < res->ncolumns; j++) {
|
|
|
|
efree(res->col_names[j]);
|
|
|
|
}
|
|
|
|
efree(res->col_names);
|
|
|
|
}
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
zend_list_delete(res->db->rsrc_id);
|
2003-04-17 09:29:45 +08:00
|
|
|
efree(res);
|
|
|
|
}
|
|
|
|
|
2003-04-18 20:22:43 +08:00
|
|
|
static ZEND_RSRC_DTOR_FUNC(php_sqlite_result_dtor)
|
|
|
|
{
|
|
|
|
struct php_sqlite_result *res = (struct php_sqlite_result *)rsrc->ptr;
|
2003-05-03 06:09:54 +08:00
|
|
|
real_result_dtor(res TSRMLS_CC);
|
2003-04-18 20:22:43 +08:00
|
|
|
}
|
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
static int php_sqlite_forget_persistent_id_numbers(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
|
|
|
{
|
|
|
|
struct php_sqlite_db *db;
|
|
|
|
|
|
|
|
if (Z_TYPE_P(rsrc) != le_sqlite_pdb) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
db = (struct php_sqlite_db*)rsrc->ptr;
|
|
|
|
|
|
|
|
db->rsrc_id = FAILURE;
|
|
|
|
|
|
|
|
/* don't leave pending commits hanging around */
|
|
|
|
sqlite_exec(db->db, "ROLLBACK", NULL, NULL, NULL);
|
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
/* prevent bad mojo if someone tries to use a previously registered function in the next request */
|
|
|
|
zend_hash_apply(&db->callbacks, (apply_func_t)php_sqlite_callback_invalidator TSRMLS_CC);
|
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
PHP_RSHUTDOWN_FUNCTION(sqlite)
|
|
|
|
{
|
|
|
|
zend_hash_apply(&EG(persistent_list), (apply_func_t)php_sqlite_forget_persistent_id_numbers TSRMLS_CC);
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2003-04-18 04:09:45 +08:00
|
|
|
/* {{{ PHP Function interface */
|
2003-04-20 21:31:36 +08:00
|
|
|
static void php_sqlite_generic_function_callback(sqlite_func *func, int argc, const char **argv)
|
2003-04-17 11:14:14 +08:00
|
|
|
{
|
|
|
|
zval *retval = NULL;
|
2003-04-27 21:25:10 +08:00
|
|
|
zval ***zargs = NULL;
|
2003-04-17 11:14:14 +08:00
|
|
|
zval funcname;
|
|
|
|
int i, res;
|
2003-04-17 11:38:20 +08:00
|
|
|
char *callable = NULL, *errbuf=NULL;
|
2003-04-19 03:43:38 +08:00
|
|
|
TSRMLS_FETCH();
|
2003-04-17 11:14:14 +08:00
|
|
|
|
|
|
|
/* sanity check the args */
|
|
|
|
if (argc == 0) {
|
|
|
|
sqlite_set_result_error(func, "not enough parameters", -1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
ZVAL_STRING(&funcname, (char*)argv[0], 0);
|
|
|
|
|
2003-04-17 11:38:20 +08:00
|
|
|
if (!zend_is_callable(&funcname, 0, &callable)) {
|
|
|
|
spprintf(&errbuf, 0, "function `%s' is not callable", callable);
|
|
|
|
sqlite_set_result_error(func, errbuf, -1);
|
|
|
|
efree(errbuf);
|
|
|
|
efree(callable);
|
2003-04-17 11:14:14 +08:00
|
|
|
return;
|
|
|
|
}
|
2003-04-17 11:38:20 +08:00
|
|
|
efree(callable);
|
2003-04-17 11:14:14 +08:00
|
|
|
|
|
|
|
if (argc > 1) {
|
2003-04-27 21:46:07 +08:00
|
|
|
zargs = (zval ***)safe_emalloc((argc - 1), sizeof(zval **), 0);
|
2003-04-17 11:14:14 +08:00
|
|
|
|
|
|
|
for (i = 0; i < argc-1; i++) {
|
|
|
|
zargs[i] = emalloc(sizeof(zval *));
|
|
|
|
MAKE_STD_ZVAL(*zargs[i]);
|
2003-04-18 00:36:59 +08:00
|
|
|
ZVAL_STRING(*zargs[i], (char*)argv[i+1], 1);
|
2003-04-17 11:14:14 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res = call_user_function_ex(EG(function_table),
|
|
|
|
NULL,
|
|
|
|
&funcname,
|
|
|
|
&retval,
|
|
|
|
argc-1,
|
|
|
|
zargs,
|
|
|
|
0, NULL TSRMLS_CC);
|
|
|
|
|
|
|
|
if (res == SUCCESS) {
|
|
|
|
if (retval == NULL) {
|
|
|
|
sqlite_set_result_string(func, NULL, 0);
|
|
|
|
} else {
|
|
|
|
switch (Z_TYPE_P(retval)) {
|
|
|
|
case IS_STRING:
|
|
|
|
sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_LONG:
|
|
|
|
case IS_BOOL:
|
|
|
|
sqlite_set_result_int(func, Z_LVAL_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_DOUBLE:
|
|
|
|
sqlite_set_result_double(func, Z_DVAL_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_NULL:
|
|
|
|
default:
|
|
|
|
sqlite_set_result_string(func, NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sqlite_set_result_error(func, "call_user_function_ex failed", -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval) {
|
|
|
|
zval_ptr_dtor(&retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zargs) {
|
|
|
|
for (i = 0; i < argc-1; i++) {
|
2003-04-18 00:36:59 +08:00
|
|
|
zval_ptr_dtor(zargs[i]);
|
2003-04-17 11:14:14 +08:00
|
|
|
efree(zargs[i]);
|
|
|
|
}
|
|
|
|
efree(zargs);
|
|
|
|
}
|
|
|
|
}
|
2003-04-18 04:09:45 +08:00
|
|
|
/* }}} */
|
2003-04-18 00:36:59 +08:00
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
/* {{{ callback for sqlite_create_function */
|
2003-04-20 21:31:36 +08:00
|
|
|
static void php_sqlite_function_callback(sqlite_func *func, int argc, const char **argv)
|
|
|
|
{
|
|
|
|
zval *retval = NULL;
|
2003-04-27 21:25:10 +08:00
|
|
|
zval ***zargs = NULL;
|
2003-04-20 21:31:36 +08:00
|
|
|
int i, res;
|
|
|
|
struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
|
|
|
|
TSRMLS_FETCH();
|
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
if (!funcs->is_valid) {
|
|
|
|
sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-20 21:31:36 +08:00
|
|
|
if (argc > 0) {
|
2003-04-27 21:46:07 +08:00
|
|
|
zargs = (zval ***)safe_emalloc(argc, sizeof(zval **), 0);
|
2003-04-20 21:31:36 +08:00
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
zargs[i] = emalloc(sizeof(zval *));
|
|
|
|
MAKE_STD_ZVAL(*zargs[i]);
|
2003-06-20 04:57:11 +08:00
|
|
|
|
|
|
|
if (argv[i] == NULL) {
|
|
|
|
ZVAL_NULL(*zargs[i]);
|
|
|
|
} else {
|
|
|
|
ZVAL_STRING(*zargs[i], (char*)argv[i], 1);
|
|
|
|
}
|
2003-04-20 21:31:36 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
res = call_user_function_ex(EG(function_table),
|
|
|
|
NULL,
|
|
|
|
funcs->step,
|
|
|
|
&retval,
|
|
|
|
argc,
|
|
|
|
zargs,
|
|
|
|
0, NULL TSRMLS_CC);
|
|
|
|
|
|
|
|
if (res == SUCCESS) {
|
|
|
|
if (retval == NULL) {
|
|
|
|
sqlite_set_result_string(func, NULL, 0);
|
|
|
|
} else {
|
|
|
|
switch (Z_TYPE_P(retval)) {
|
|
|
|
case IS_STRING:
|
2003-06-20 04:57:11 +08:00
|
|
|
/* TODO: for binary results, need to encode the string */
|
2003-04-20 21:31:36 +08:00
|
|
|
sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_LONG:
|
|
|
|
case IS_BOOL:
|
|
|
|
sqlite_set_result_int(func, Z_LVAL_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_DOUBLE:
|
|
|
|
sqlite_set_result_double(func, Z_DVAL_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_NULL:
|
|
|
|
default:
|
|
|
|
sqlite_set_result_string(func, NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sqlite_set_result_error(func, "call_user_function_ex failed", -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval) {
|
|
|
|
zval_ptr_dtor(&retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zargs) {
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
zval_ptr_dtor(zargs[i]);
|
|
|
|
efree(zargs[i]);
|
|
|
|
}
|
|
|
|
efree(zargs);
|
|
|
|
}
|
|
|
|
}
|
2003-04-20 23:13:04 +08:00
|
|
|
/* }}} */
|
2003-04-20 21:31:36 +08:00
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
/* {{{ callback for sqlite_create_aggregate: step function */
|
2003-04-20 21:08:22 +08:00
|
|
|
static void php_sqlite_agg_step_function_callback(sqlite_func *func, int argc, const char **argv)
|
|
|
|
{
|
|
|
|
zval *retval = NULL;
|
|
|
|
zval ***zargs;
|
|
|
|
zval **context_p;
|
|
|
|
int i, res, zargc;
|
|
|
|
struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
|
|
|
|
TSRMLS_FETCH();
|
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
if (!funcs->is_valid) {
|
|
|
|
sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-20 21:08:22 +08:00
|
|
|
/* sanity check the args */
|
|
|
|
if (argc < 1) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
zargc = argc + 1;
|
2003-04-27 21:46:07 +08:00
|
|
|
zargs = (zval ***)safe_emalloc(zargc, sizeof(zval **), 0);
|
2003-04-20 21:08:22 +08:00
|
|
|
|
|
|
|
/* first arg is always the context zval */
|
|
|
|
context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
|
2003-04-20 23:13:04 +08:00
|
|
|
|
2003-04-20 21:08:22 +08:00
|
|
|
if (*context_p == NULL) {
|
|
|
|
MAKE_STD_ZVAL(*context_p);
|
2003-04-20 23:13:04 +08:00
|
|
|
(*context_p)->is_ref = 1;
|
|
|
|
Z_TYPE_PP(context_p) = IS_NULL;
|
2003-04-20 21:08:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
zargs[0] = context_p;
|
|
|
|
|
|
|
|
/* copy the other args */
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
zargs[i+1] = emalloc(sizeof(zval *));
|
|
|
|
MAKE_STD_ZVAL(*zargs[i+1]);
|
2003-06-20 04:57:11 +08:00
|
|
|
if (argv[i] == NULL) {
|
|
|
|
ZVAL_NULL(*zargs[i+1]);
|
|
|
|
} else {
|
|
|
|
ZVAL_STRING(*zargs[i+1], (char*)argv[i], 1);
|
|
|
|
}
|
2003-04-20 21:08:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
res = call_user_function_ex(EG(function_table),
|
|
|
|
NULL,
|
|
|
|
funcs->step,
|
|
|
|
&retval,
|
|
|
|
zargc,
|
|
|
|
zargs,
|
|
|
|
0, NULL TSRMLS_CC);
|
|
|
|
|
|
|
|
if (res != SUCCESS) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "call_user_function_ex failed");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval) {
|
|
|
|
zval_ptr_dtor(&retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (zargs) {
|
|
|
|
for (i = 1; i < zargc; i++) {
|
|
|
|
zval_ptr_dtor(zargs[i]);
|
|
|
|
efree(zargs[i]);
|
|
|
|
}
|
|
|
|
efree(zargs);
|
|
|
|
}
|
|
|
|
}
|
2003-04-20 23:13:04 +08:00
|
|
|
/* }}} */
|
2003-04-20 21:08:22 +08:00
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
/* {{{ callback for sqlite_create_aggregate: finalize function */
|
2003-04-20 21:08:22 +08:00
|
|
|
static void php_sqlite_agg_fini_function_callback(sqlite_func *func)
|
|
|
|
{
|
|
|
|
zval *retval = NULL;
|
2003-04-20 23:13:04 +08:00
|
|
|
int res;
|
2003-04-20 21:08:22 +08:00
|
|
|
struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
|
|
|
|
zval **context_p;
|
|
|
|
TSRMLS_FETCH();
|
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
if (!funcs->is_valid) {
|
|
|
|
sqlite_set_result_error(func, "this function has not been correctly defined for this request", -1);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-20 21:08:22 +08:00
|
|
|
context_p = (zval **)sqlite_aggregate_context(func, sizeof(*context_p));
|
|
|
|
|
|
|
|
res = call_user_function_ex(EG(function_table),
|
|
|
|
NULL,
|
2003-04-20 23:13:04 +08:00
|
|
|
funcs->fini,
|
2003-04-20 21:08:22 +08:00
|
|
|
&retval,
|
|
|
|
1,
|
|
|
|
&context_p,
|
|
|
|
0, NULL TSRMLS_CC);
|
|
|
|
|
|
|
|
if (res == SUCCESS) {
|
|
|
|
if (retval == NULL) {
|
|
|
|
sqlite_set_result_string(func, NULL, 0);
|
|
|
|
} else {
|
|
|
|
switch (Z_TYPE_P(retval)) {
|
|
|
|
case IS_STRING:
|
|
|
|
/* TODO: for binary results, need to encode the string */
|
|
|
|
sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_LONG:
|
|
|
|
case IS_BOOL:
|
|
|
|
sqlite_set_result_int(func, Z_LVAL_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_DOUBLE:
|
|
|
|
sqlite_set_result_double(func, Z_DVAL_P(retval));
|
|
|
|
break;
|
|
|
|
case IS_NULL:
|
|
|
|
default:
|
|
|
|
sqlite_set_result_string(func, NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
sqlite_set_result_error(func, "call_user_function_ex failed", -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retval) {
|
|
|
|
zval_ptr_dtor(&retval);
|
|
|
|
}
|
|
|
|
|
|
|
|
zval_ptr_dtor(context_p);
|
|
|
|
}
|
2003-04-20 23:13:04 +08:00
|
|
|
/* }}} */
|
2003-04-20 21:08:22 +08:00
|
|
|
|
2003-04-18 04:09:45 +08:00
|
|
|
/* {{{ Authorization Callback */
|
2003-06-05 06:40:00 +08:00
|
|
|
static int php_sqlite_authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
|
|
|
|
const char *arg5, const char *arg6)
|
2003-04-18 02:54:40 +08:00
|
|
|
{
|
|
|
|
switch (access_type) {
|
|
|
|
case SQLITE_COPY:
|
|
|
|
{
|
|
|
|
TSRMLS_FETCH();
|
|
|
|
if (PG(safe_mode) && (!php_checkuid(arg4, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
|
|
|
return SQLITE_DENY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (php_check_open_basedir(arg4 TSRMLS_CC)) {
|
|
|
|
return SQLITE_DENY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SQLITE_OK;
|
2003-06-07 06:44:57 +08:00
|
|
|
#ifdef SQLITE_ATTACH
|
|
|
|
case SQLITE_ATTACH:
|
|
|
|
{
|
|
|
|
TSRMLS_FETCH();
|
|
|
|
if (PG(safe_mode) && (!php_checkuid(arg3, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
|
|
|
return SQLITE_DENY;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (php_check_open_basedir(arg3 TSRMLS_CC)) {
|
|
|
|
return SQLITE_DENY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return SQLITE_OK;
|
|
|
|
#endif
|
2003-04-18 02:54:40 +08:00
|
|
|
|
|
|
|
default:
|
|
|
|
/* access allowed */
|
|
|
|
return SQLITE_OK;
|
|
|
|
}
|
|
|
|
}
|
2003-04-18 04:09:45 +08:00
|
|
|
/* }}} */
|
2003-04-18 00:36:59 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
/* {{{ OO init/structure stuff */
|
|
|
|
#define REGISTER_SQLITE_CLASS(name, parent) \
|
|
|
|
{ \
|
|
|
|
zend_class_entry ce; \
|
|
|
|
INIT_CLASS_ENTRY(ce, "sqlite_" # name, sqlite_funcs_ ## name); \
|
|
|
|
ce.create_object = sqlite_object_new_ ## name; \
|
|
|
|
sqlite_ce_ ## name = zend_register_internal_class_ex(&ce, parent, NULL TSRMLS_CC); \
|
|
|
|
memcpy(&sqlite_object_handlers_ ## name, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); \
|
|
|
|
}
|
|
|
|
|
|
|
|
zend_class_entry *sqlite_ce_db, *sqlite_ce_exception;
|
|
|
|
zend_class_entry *sqlite_ce_query, *sqlite_ce_ub_query;
|
|
|
|
|
|
|
|
static zend_object_handlers sqlite_object_handlers_db;
|
|
|
|
static zend_object_handlers sqlite_object_handlers_query;
|
|
|
|
static zend_object_handlers sqlite_object_handlers_ub_query;
|
|
|
|
static zend_object_handlers sqlite_object_handlers_exception;
|
|
|
|
|
|
|
|
typedef enum {
|
|
|
|
is_db,
|
|
|
|
is_result
|
|
|
|
} sqlite_obj_type;
|
|
|
|
|
|
|
|
typedef struct _sqlite_object {
|
|
|
|
zend_object std;
|
|
|
|
sqlite_obj_type type;
|
|
|
|
union {
|
|
|
|
struct php_sqlite_db *db;
|
|
|
|
struct php_sqlite_result *res;
|
|
|
|
void *ptr;
|
|
|
|
} u;
|
|
|
|
} sqlite_object;
|
|
|
|
|
|
|
|
static void sqlite_object_clone(void *object, void **object_clone TSRMLS_DC)
|
|
|
|
{
|
|
|
|
/* TODO */
|
|
|
|
}
|
|
|
|
|
|
|
|
static int sqlite_free_persistent(list_entry *le, void *ptr TSRMLS_DC)
|
|
|
|
{
|
|
|
|
return le->ptr == ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sqlite_object_dtor(void *object, zend_object_handle handle TSRMLS_DC)
|
|
|
|
{
|
|
|
|
sqlite_object *intern = (sqlite_object *)object;
|
|
|
|
|
|
|
|
zend_hash_destroy(intern->std.properties);
|
|
|
|
FREE_HASHTABLE(intern->std.properties);
|
|
|
|
|
|
|
|
if (intern->u.ptr) {
|
|
|
|
if (intern->type == is_db) {
|
|
|
|
if (intern->u.db->rsrc_id) {
|
|
|
|
zend_list_delete(intern->u.db->rsrc_id);
|
|
|
|
zend_hash_apply_with_argument(&EG(persistent_list), (apply_func_arg_t) sqlite_free_persistent, &intern->u.ptr TSRMLS_CC);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
real_result_dtor(intern->u.res TSRMLS_CC);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
efree(object);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void sqlite_object_new(zend_class_entry *class_type, zend_object_handlers *handlers, zend_object_value *retval TSRMLS_DC)
|
|
|
|
{
|
|
|
|
sqlite_object *intern;
|
|
|
|
zval *tmp;
|
|
|
|
|
|
|
|
intern = emalloc(sizeof(sqlite_object));
|
|
|
|
memset(intern, 0, sizeof(sqlite_object));
|
|
|
|
intern->std.ce = class_type;
|
|
|
|
|
|
|
|
ALLOC_HASHTABLE(intern->std.properties);
|
|
|
|
zend_hash_init(intern->std.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
|
|
|
|
zend_hash_copy(intern->std.properties, &class_type->default_properties, (copy_ctor_func_t) zval_add_ref, (void *) &tmp, sizeof(zval *));
|
|
|
|
|
|
|
|
retval->handle = zend_objects_store_put(intern, sqlite_object_dtor, sqlite_object_clone TSRMLS_CC);
|
|
|
|
retval->handlers = handlers;
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_object_value sqlite_object_new_db(zend_class_entry *class_type TSRMLS_DC)
|
|
|
|
{
|
|
|
|
zend_object_value retval;
|
|
|
|
|
|
|
|
sqlite_object_new(class_type, &sqlite_object_handlers_db, &retval TSRMLS_CC);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_object_value sqlite_object_new_query(zend_class_entry *class_type TSRMLS_DC)
|
|
|
|
{
|
|
|
|
zend_object_value retval;
|
|
|
|
|
|
|
|
sqlite_object_new(class_type, &sqlite_object_handlers_query, &retval TSRMLS_CC);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_object_value sqlite_object_new_ub_query(zend_class_entry *class_type TSRMLS_DC)
|
|
|
|
{
|
|
|
|
zend_object_value retval;
|
|
|
|
|
|
|
|
sqlite_object_new(class_type, &sqlite_object_handlers_ub_query, &retval TSRMLS_CC);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_object_value sqlite_object_new_exception(zend_class_entry *class_type TSRMLS_DC)
|
|
|
|
{
|
|
|
|
zend_object_value retval;
|
|
|
|
|
|
|
|
sqlite_object_new(class_type, &sqlite_object_handlers_exception, &retval TSRMLS_CC);
|
|
|
|
return retval;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define SQLITE_REGISTER_OBJECT(_type, _object, _ptr) \
|
|
|
|
{ \
|
|
|
|
sqlite_object *obj; \
|
|
|
|
obj = (sqlite_object*)zend_object_store_get_object(_object TSRMLS_CC); \
|
|
|
|
obj->type = is_ ## _type; \
|
|
|
|
obj->u._type = _ptr; \
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_class_entry *sqlite_get_ce_query(zval *object TSRMLS_DC)
|
|
|
|
{
|
|
|
|
return sqlite_ce_query;
|
|
|
|
}
|
|
|
|
|
|
|
|
static zend_class_entry *sqlite_get_ce_ub_query(zval *object TSRMLS_DC)
|
|
|
|
{
|
|
|
|
return sqlite_ce_ub_query;
|
|
|
|
}
|
|
|
|
|
|
|
|
static zval * sqlite_instanciate(zend_class_entry *pce, zval *object TSRMLS_DC)
|
|
|
|
{
|
|
|
|
if (!object) {
|
|
|
|
ALLOC_ZVAL(object);
|
|
|
|
}
|
|
|
|
Z_TYPE_P(object) = IS_OBJECT;
|
|
|
|
object_init_ex(object, pce);
|
|
|
|
object->refcount = 1;
|
|
|
|
object->is_ref = 1;
|
|
|
|
return object;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-23 07:24:44 +08:00
|
|
|
static int init_sqlite_globals(zend_sqlite_globals *g)
|
|
|
|
{
|
|
|
|
g->assoc_case = 0;
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
PHP_MINIT_FUNCTION(sqlite)
|
|
|
|
{
|
2003-06-23 01:19:46 +08:00
|
|
|
REGISTER_SQLITE_CLASS(db, NULL);
|
|
|
|
REGISTER_SQLITE_CLASS(query, NULL);
|
|
|
|
REGISTER_SQLITE_CLASS(ub_query, NULL);
|
|
|
|
REGISTER_SQLITE_CLASS(exception, zend_exception_get_default());
|
|
|
|
sqlite_object_handlers_query.get_class_entry = sqlite_get_ce_query;
|
|
|
|
sqlite_object_handlers_ub_query.get_class_entry = sqlite_get_ce_ub_query;
|
|
|
|
|
2003-04-23 07:24:44 +08:00
|
|
|
ZEND_INIT_MODULE_GLOBALS(sqlite, init_sqlite_globals, NULL);
|
2003-06-23 01:19:46 +08:00
|
|
|
|
2003-04-22 08:08:48 +08:00
|
|
|
REGISTER_INI_ENTRIES();
|
2003-04-23 07:24:44 +08:00
|
|
|
|
2003-07-01 21:07:37 +08:00
|
|
|
php_session_register_module(ps_sqlite_ptr);
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
le_sqlite_db = zend_register_list_destructors_ex(php_sqlite_db_dtor, NULL, "sqlite database", module_number);
|
2003-04-19 00:30:16 +08:00
|
|
|
le_sqlite_pdb = zend_register_list_destructors_ex(NULL, php_sqlite_db_dtor, "sqlite database (persistent)", module_number);
|
2003-04-17 09:29:45 +08:00
|
|
|
le_sqlite_result = zend_register_list_destructors_ex(php_sqlite_result_dtor, NULL, "sqlite result", module_number);
|
|
|
|
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_BOTH", PHPSQLITE_BOTH, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_NUM", PHPSQLITE_NUM, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_ASSOC", PHPSQLITE_ASSOC, CONST_CS|CONST_PERSISTENT);
|
2003-04-18 04:17:54 +08:00
|
|
|
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_OK", SQLITE_OK, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_ERROR", SQLITE_ERROR, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_INTERNAL", SQLITE_INTERNAL, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_PERM", SQLITE_PERM, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_ABORT", SQLITE_ABORT, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_BUSY", SQLITE_BUSY, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_LOCKED", SQLITE_LOCKED, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_NOMEM", SQLITE_NOMEM, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_READONLY", SQLITE_READONLY, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_INTERRUPT", SQLITE_INTERRUPT, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_IOERR", SQLITE_IOERR, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_CORRUPT", SQLITE_CORRUPT, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_NOTFOUND", SQLITE_NOTFOUND, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_FULL", SQLITE_FULL, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_CANTOPEN", SQLITE_CANTOPEN, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_PROTOCOL", SQLITE_PROTOCOL, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_EMPTY", SQLITE_EMPTY, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_SCHEMA", SQLITE_SCHEMA, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_TOOBIG", SQLITE_TOOBIG, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_CONSTRAINT", SQLITE_CONSTRAINT, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_MISMATCH", SQLITE_MISMATCH, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_MISUSE", SQLITE_MISUSE, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_NOLFS", SQLITE_NOLFS, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_AUTH", SQLITE_AUTH, CONST_CS|CONST_PERSISTENT);
|
2003-06-20 04:57:11 +08:00
|
|
|
#ifdef SQLITE_FORMAT
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_FORMAT", SQLITE_FORMAT, CONST_CS|CONST_PERSISTENT);
|
|
|
|
#endif
|
2003-04-18 04:17:54 +08:00
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_ROW", SQLITE_ROW, CONST_CS|CONST_PERSISTENT);
|
|
|
|
REGISTER_LONG_CONSTANT("SQLITE_DONE", SQLITE_DONE, CONST_CS|CONST_PERSISTENT);
|
2003-04-17 09:29:45 +08:00
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
PHP_RINIT_FUNCTION(sqlite)
|
|
|
|
{
|
|
|
|
#ifdef HAVE_SPL
|
|
|
|
if (!sqlite_ce_query->num_interfaces) {
|
|
|
|
spl_register_implement(sqlite_ce_query, spl_ce_forward TSRMLS_CC);
|
|
|
|
spl_register_implement(sqlite_ce_query, spl_ce_sequence TSRMLS_CC);
|
|
|
|
}
|
|
|
|
if (!sqlite_ce_ub_query->num_interfaces) {
|
|
|
|
spl_register_implement(sqlite_ce_ub_query, spl_ce_forward TSRMLS_CC);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return SUCCESS;
|
|
|
|
}
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
PHP_MINFO_FUNCTION(sqlite)
|
|
|
|
{
|
|
|
|
php_info_print_table_start();
|
|
|
|
php_info_print_table_header(2, "SQLite support", "enabled");
|
2003-04-18 03:13:21 +08:00
|
|
|
php_info_print_table_row(2, "PECL Module version", PHP_SQLITE_MODULE_VERSION " $Id$");
|
2003-04-17 09:29:45 +08:00
|
|
|
php_info_print_table_row(2, "SQLite Library", sqlite_libversion());
|
|
|
|
php_info_print_table_row(2, "SQLite Encoding", sqlite_libencoding());
|
|
|
|
php_info_print_table_end();
|
2003-04-22 08:08:48 +08:00
|
|
|
|
|
|
|
DISPLAY_INI_ENTRIES();
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
static struct php_sqlite_db *php_sqlite_open(char *filename, int mode, char *persistent_id, zval *return_value, zval *errmsg, zval *object TSRMLS_DC)
|
2003-04-17 09:29:45 +08:00
|
|
|
{
|
|
|
|
char *errtext = NULL;
|
2003-04-18 04:08:00 +08:00
|
|
|
sqlite *sdb = NULL;
|
2003-04-19 00:30:16 +08:00
|
|
|
struct php_sqlite_db *db = NULL;
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-04-18 04:08:00 +08:00
|
|
|
sdb = sqlite_open(filename, mode, &errtext);
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-04-18 04:08:00 +08:00
|
|
|
if (sdb == NULL) {
|
2003-04-19 03:43:38 +08:00
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
|
|
|
|
|
|
|
|
if (errmsg) {
|
|
|
|
ZVAL_STRING(errmsg, errtext, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
sqlite_freemem(errtext);
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
/* if object is not an object then we're called from the factory() function */
|
|
|
|
if (object && Z_TYPE_P(object) != IS_OBJECT) {
|
|
|
|
RETVAL_NULL();
|
|
|
|
} else {
|
|
|
|
RETVAL_FALSE;
|
|
|
|
}
|
2003-04-19 00:30:16 +08:00
|
|
|
return NULL;
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
db = (struct php_sqlite_db *)pemalloc(sizeof(struct php_sqlite_db), persistent_id ? 1 : 0);
|
|
|
|
db->is_persistent = persistent_id ? 1 : 0;
|
2003-04-18 04:17:54 +08:00
|
|
|
db->last_err_code = SQLITE_OK;
|
2003-04-18 04:08:00 +08:00
|
|
|
db->db = sdb;
|
2003-04-20 23:13:04 +08:00
|
|
|
|
|
|
|
zend_hash_init(&db->callbacks, 0, NULL, php_sqlite_callback_dtor, db->is_persistent);
|
2003-04-18 04:08:00 +08:00
|
|
|
|
2003-04-17 11:14:14 +08:00
|
|
|
/* register the PHP functions */
|
2003-04-20 21:31:36 +08:00
|
|
|
sqlite_create_function(sdb, "php", -1, php_sqlite_generic_function_callback, 0);
|
2003-04-18 00:57:46 +08:00
|
|
|
|
2003-06-20 04:57:11 +08:00
|
|
|
/* set default busy handler; keep retrying up until 1 minute has passed,
|
2003-04-18 00:57:46 +08:00
|
|
|
* then fail with a busy status code */
|
2003-06-20 04:57:11 +08:00
|
|
|
sqlite_busy_timeout(sdb, 60000);
|
2003-04-18 02:54:40 +08:00
|
|
|
|
2003-06-07 19:38:03 +08:00
|
|
|
/* authorizer hook so we can enforce safe mode
|
|
|
|
* Note: the declaration of php_sqlite_authorizer is correct for 2.8.2 of libsqlite,
|
|
|
|
* and IS backwards binary compatible with earlier versions */
|
2003-04-18 04:08:00 +08:00
|
|
|
sqlite_set_authorizer(sdb, php_sqlite_authorizer, NULL);
|
2003-04-17 11:14:14 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
db->rsrc_id = ZEND_REGISTER_RESOURCE(object ? NULL : return_value, db, persistent_id ? le_sqlite_pdb : le_sqlite_db);
|
|
|
|
if (object) {
|
|
|
|
/* if object is not an object then we're called from the factory() function */
|
|
|
|
if (Z_TYPE_P(object) != IS_OBJECT) {
|
|
|
|
sqlite_instanciate(sqlite_ce_db, object TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* and now register the object */
|
|
|
|
SQLITE_REGISTER_OBJECT(db, object, db)
|
|
|
|
}
|
2003-04-19 00:30:16 +08:00
|
|
|
|
|
|
|
if (persistent_id) {
|
|
|
|
list_entry le;
|
|
|
|
|
|
|
|
Z_TYPE(le) = le_sqlite_pdb;
|
|
|
|
le.ptr = db;
|
|
|
|
|
|
|
|
if (FAILURE == zend_hash_update(&EG(persistent_list), persistent_id,
|
|
|
|
strlen(persistent_id)+1,
|
|
|
|
(void *)&le, sizeof(le), NULL)) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to register persistent resource");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return db;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* {{{ proto resource sqlite_popen(string filename [, int mode, string &errmessage])
|
|
|
|
Opens a persistent handle to an SQLite database. Will create the database if it does not exist */
|
|
|
|
PHP_FUNCTION(sqlite_popen)
|
|
|
|
{
|
|
|
|
int mode = 0666;
|
|
|
|
char *filename, *fullpath, *hashkey;
|
|
|
|
long filename_len, hashkeylen;
|
|
|
|
zval *errmsg = NULL;
|
|
|
|
struct php_sqlite_db *db = NULL;
|
|
|
|
list_entry *le;
|
|
|
|
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
|
|
|
|
&filename, &filename_len, &mode, &errmsg)) {
|
|
|
|
return;
|
|
|
|
}
|
2003-06-27 03:07:17 +08:00
|
|
|
if (errmsg) {
|
|
|
|
zval_dtor(errmsg);
|
|
|
|
}
|
2003-04-19 00:30:16 +08:00
|
|
|
|
2003-06-10 04:36:55 +08:00
|
|
|
if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
|
|
|
|
/* resolve the fully-qualified path name to use as the hash key */
|
|
|
|
fullpath = expand_filepath(filename, NULL TSRMLS_CC);
|
2003-04-19 00:30:16 +08:00
|
|
|
|
2003-06-10 04:36:55 +08:00
|
|
|
if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-04-19 00:30:16 +08:00
|
|
|
|
2003-06-10 04:36:55 +08:00
|
|
|
if (php_check_open_basedir(fullpath TSRMLS_CC)) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
fullpath = estrndup(filename, filename_len);
|
2003-04-19 00:30:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
hashkeylen = spprintf(&hashkey, 0, "sqlite_pdb_%s:%d", fullpath, mode);
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
/* do we have an existing persistent connection ? */
|
|
|
|
if (SUCCESS == zend_hash_find(&EG(persistent_list), hashkey, hashkeylen+1, (void*)&le)) {
|
|
|
|
if (Z_TYPE_P(le) == le_sqlite_pdb) {
|
|
|
|
db = (struct php_sqlite_db*)le->ptr;
|
|
|
|
|
|
|
|
if (db->rsrc_id == FAILURE) {
|
|
|
|
/* give it a valid resource id for this request */
|
|
|
|
db->rsrc_id = ZEND_REGISTER_RESOURCE(return_value, db, le_sqlite_pdb);
|
|
|
|
} else {
|
|
|
|
/* already accessed this request; map it */
|
|
|
|
ZVAL_RESOURCE(return_value, db->rsrc_id);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* all set */
|
|
|
|
efree(fullpath);
|
|
|
|
efree(hashkey);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-06-15 02:16:47 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Some other type of persistent resource is using this hash key!?");
|
2003-04-19 00:30:16 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* now we need to open the database */
|
2003-06-23 01:19:46 +08:00
|
|
|
php_sqlite_open(fullpath, mode, hashkey, return_value, errmsg, NULL TSRMLS_CC);
|
2003-04-19 00:30:16 +08:00
|
|
|
|
|
|
|
efree(fullpath);
|
|
|
|
efree(hashkey);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto resource sqlite_open(string filename [, int mode, string &errmessage])
|
|
|
|
Opens an SQLite database. Will create the database if it does not exist */
|
|
|
|
PHP_FUNCTION(sqlite_open)
|
|
|
|
{
|
|
|
|
int mode = 0666;
|
|
|
|
char *filename;
|
|
|
|
long filename_len;
|
|
|
|
zval *errmsg = NULL;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-19 00:30:16 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
php_set_error_handling(object ? EH_THROW : EH_NORMAL, zend_exception_get_default() TSRMLS_CC);
|
2003-04-19 00:30:16 +08:00
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
|
|
|
|
&filename, &filename_len, &mode, &errmsg)) {
|
2003-06-23 01:19:46 +08:00
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
2003-04-19 00:30:16 +08:00
|
|
|
return;
|
|
|
|
}
|
2003-06-27 03:07:17 +08:00
|
|
|
if (errmsg) {
|
|
|
|
zval_dtor(errmsg);
|
|
|
|
}
|
2003-04-19 00:30:16 +08:00
|
|
|
|
2003-06-10 04:36:55 +08:00
|
|
|
if (strncmp(filename, ":memory:", sizeof(":memory:") - 1)) {
|
|
|
|
if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
2003-06-23 01:19:46 +08:00
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
|
|
|
if (object) {
|
|
|
|
RETURN_NULL();
|
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-06-10 04:36:55 +08:00
|
|
|
}
|
2003-06-23 01:19:46 +08:00
|
|
|
|
2003-06-10 04:36:55 +08:00
|
|
|
if (php_check_open_basedir(filename TSRMLS_CC)) {
|
2003-06-23 01:19:46 +08:00
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
|
|
|
if (object) {
|
|
|
|
RETURN_NULL();
|
|
|
|
} else {
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-06-10 04:36:55 +08:00
|
|
|
}
|
2003-04-19 00:30:16 +08:00
|
|
|
}
|
2003-06-23 01:19:46 +08:00
|
|
|
|
|
|
|
php_sqlite_open(filename, mode, NULL, return_value, errmsg, object TSRMLS_CC);
|
|
|
|
|
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto object factory(string filename [, int mode, string &errmessage])
|
|
|
|
Opens a SQLite database and create an object for it. Will create the database if it does not exist */
|
|
|
|
PHP_FUNCTION(sqlite_factory)
|
|
|
|
{
|
|
|
|
int mode = 0666;
|
|
|
|
char *filename;
|
|
|
|
long filename_len;
|
|
|
|
zval *errmsg = NULL;
|
|
|
|
|
|
|
|
php_set_error_handling(EH_THROW, sqlite_ce_exception TSRMLS_CC);
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
|
|
|
|
&filename, &filename_len, &mode, &errmsg)) {
|
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
2003-06-27 03:07:17 +08:00
|
|
|
if (errmsg) {
|
|
|
|
zval_dtor(errmsg);
|
|
|
|
}
|
2003-06-23 01:19:46 +08:00
|
|
|
|
|
|
|
if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) {
|
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (php_check_open_basedir(filename TSRMLS_CC)) {
|
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
|
|
|
|
php_sqlite_open(filename, mode, NULL, return_value, errmsg, return_value TSRMLS_CC);
|
|
|
|
|
|
|
|
php_set_error_handling(EH_NORMAL, NULL TSRMLS_CC);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-18 00:57:46 +08:00
|
|
|
/* {{{ proto void sqlite_busy_timeout(resource db, int ms)
|
|
|
|
Set busy timeout duration. If ms <= 0, all busy handlers are disabled */
|
|
|
|
PHP_FUNCTION(sqlite_busy_timeout)
|
|
|
|
{
|
|
|
|
zval *zdb;
|
2003-04-18 04:08:00 +08:00
|
|
|
struct php_sqlite_db *db;
|
2003-04-18 00:57:46 +08:00
|
|
|
long ms;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-18 00:57:46 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &ms)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zdb, &ms)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-18 00:57:46 +08:00
|
|
|
}
|
|
|
|
|
2003-04-18 04:08:00 +08:00
|
|
|
sqlite_busy_timeout(db->db, ms);
|
2003-04-18 00:57:46 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
/* {{{ proto void sqlite_close(resource db)
|
|
|
|
Closes an open sqlite database */
|
|
|
|
PHP_FUNCTION(sqlite_close)
|
|
|
|
{
|
|
|
|
zval *zdb;
|
2003-04-18 04:08:00 +08:00
|
|
|
struct php_sqlite_db *db;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Ignored, you must destruct the object instead");
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-06-05 05:11:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
zend_list_delete(Z_RESVAL_P(zdb));
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-27 21:32:43 +08:00
|
|
|
/* {{{ php_sqlite_fetch */
|
2003-04-27 21:25:10 +08:00
|
|
|
int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC)
|
|
|
|
{
|
|
|
|
const char **rowdata, **colnames;
|
|
|
|
int ret, i, base;
|
2003-05-01 21:20:22 +08:00
|
|
|
char *errtext = NULL, *colname;
|
2003-04-27 21:25:10 +08:00
|
|
|
|
|
|
|
next_row:
|
|
|
|
ret = sqlite_step(rres->vm, &rres->ncolumns, &rowdata, &colnames);
|
|
|
|
if (!rres->nrows) {
|
|
|
|
/* first row - lets copy the column names */
|
|
|
|
rres->col_names = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
|
|
|
|
for (i = 0; i < rres->ncolumns; i++) {
|
2003-05-01 21:20:22 +08:00
|
|
|
colname = strchr(colnames[i], '.');
|
|
|
|
if (!colname++) {
|
|
|
|
colname = (char*)colnames[i];
|
|
|
|
}
|
|
|
|
if (SQLITE_G(assoc_case) == 1) {
|
|
|
|
php_sqlite_strtoupper(colname);
|
|
|
|
} else if (SQLITE_G(assoc_case) == 2) {
|
|
|
|
php_sqlite_strtolower(colname);
|
|
|
|
}
|
|
|
|
rres->col_names[i] = estrdup(colname);
|
2003-04-27 21:25:10 +08:00
|
|
|
}
|
|
|
|
if (!rres->buffered) {
|
|
|
|
/* non buffered mode - also fetch memory for on single row */
|
|
|
|
rres->table = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (ret) {
|
|
|
|
case SQLITE_ROW:
|
|
|
|
if (rres->buffered) {
|
|
|
|
/* add the row to our collection */
|
|
|
|
if (rres->nrows + 1 >= rres->alloc_rows) {
|
|
|
|
rres->alloc_rows = rres->alloc_rows ? rres->alloc_rows * 2 : 16;
|
|
|
|
rres->table = erealloc(rres->table, rres->alloc_rows * rres->ncolumns * sizeof(char *));
|
|
|
|
}
|
|
|
|
base = rres->nrows * rres->ncolumns;
|
|
|
|
for (i = 0; i < rres->ncolumns; i++) {
|
|
|
|
if (rowdata[i]) {
|
|
|
|
rres->table[base + i] = estrdup(rowdata[i]);
|
|
|
|
} else {
|
|
|
|
rres->table[base + i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
rres->nrows++;
|
|
|
|
goto next_row;
|
|
|
|
} else {
|
|
|
|
/* non buffered: only fetch one row but first free data if not first row */
|
|
|
|
if (rres->nrows++) {
|
|
|
|
for (i = 0; i < rres->ncolumns; i++) {
|
|
|
|
if (rres->table[i]) {
|
|
|
|
efree(rres->table[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (i = 0; i < rres->ncolumns; i++) {
|
|
|
|
if (rowdata[i]) {
|
|
|
|
rres->table[i] = estrdup(rowdata[i]);
|
|
|
|
} else {
|
|
|
|
rres->table[i] = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret = SQLITE_OK;
|
|
|
|
break;
|
|
|
|
|
2003-04-27 22:01:09 +08:00
|
|
|
case SQLITE_BUSY:
|
|
|
|
case SQLITE_ERROR:
|
|
|
|
case SQLITE_MISUSE:
|
2003-04-27 21:25:10 +08:00
|
|
|
case SQLITE_DONE:
|
2003-04-27 22:01:09 +08:00
|
|
|
default:
|
2003-04-27 21:25:10 +08:00
|
|
|
if (rres->vm) {
|
|
|
|
ret = sqlite_finalize(rres->vm, &errtext);
|
|
|
|
}
|
|
|
|
rres->vm = NULL;
|
|
|
|
if (ret != SQLITE_OK) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
|
|
|
|
sqlite_freemem(errtext);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2003-05-03 06:09:54 +08:00
|
|
|
rres->db->last_err_code = ret;
|
|
|
|
|
2003-04-27 21:25:10 +08:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* {{{ sqlite_query */
|
2003-06-23 01:19:46 +08:00
|
|
|
void sqlite_query(zval *object, struct php_sqlite_db *db, char *sql, long sql_len, int mode, int buffered, zval *return_value, struct php_sqlite_result *rres TSRMLS_DC)
|
2003-04-18 20:22:43 +08:00
|
|
|
{
|
2003-06-10 07:14:25 +08:00
|
|
|
struct php_sqlite_result res;
|
2003-04-20 23:13:04 +08:00
|
|
|
int ret;
|
2003-04-18 20:22:43 +08:00
|
|
|
char *errtext = NULL;
|
|
|
|
const char *tail;
|
|
|
|
|
|
|
|
memset(&res, 0, sizeof(res));
|
2003-05-03 06:09:54 +08:00
|
|
|
res.buffered = buffered;
|
2003-04-30 23:18:59 +08:00
|
|
|
res.mode = mode;
|
2003-04-18 20:22:43 +08:00
|
|
|
|
|
|
|
ret = sqlite_compile(db->db, sql, &tail, &res.vm, &errtext);
|
|
|
|
db->last_err_code = ret;
|
|
|
|
|
|
|
|
if (ret != SQLITE_OK) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
|
|
|
|
sqlite_freemem(errtext);
|
2003-06-24 03:37:48 +08:00
|
|
|
if (return_value) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
2003-04-18 20:22:43 +08:00
|
|
|
}
|
|
|
|
|
2003-06-10 07:14:25 +08:00
|
|
|
if (!rres) {
|
|
|
|
rres = (struct php_sqlite_result*)emalloc(sizeof(*rres));
|
|
|
|
}
|
2003-04-18 20:22:43 +08:00
|
|
|
memcpy(rres, &res, sizeof(*rres));
|
2003-05-03 06:09:54 +08:00
|
|
|
rres->db = db;
|
|
|
|
zend_list_addref(db->rsrc_id);
|
|
|
|
|
2003-04-18 20:22:43 +08:00
|
|
|
|
2003-04-27 21:25:10 +08:00
|
|
|
/* now the result set is ready for stepping: get first row */
|
2003-05-03 06:09:54 +08:00
|
|
|
if (php_sqlite_fetch(rres TSRMLS_CC) != SQLITE_OK) {
|
|
|
|
real_result_dtor(rres TSRMLS_CC);
|
2003-06-24 03:37:48 +08:00
|
|
|
if (return_value) {
|
|
|
|
RETURN_FALSE;
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
2003-04-27 21:25:10 +08:00
|
|
|
}
|
|
|
|
|
2003-04-18 20:22:43 +08:00
|
|
|
rres->curr_row = 0;
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
sqlite_object *obj;
|
|
|
|
if (buffered) {
|
|
|
|
sqlite_instanciate(sqlite_ce_query, return_value TSRMLS_CC);
|
|
|
|
} else {
|
|
|
|
sqlite_instanciate(sqlite_ce_ub_query, return_value TSRMLS_CC);
|
|
|
|
}
|
|
|
|
obj = (sqlite_object *) zend_object_store_get_object(return_value TSRMLS_CC);
|
|
|
|
obj->type = is_result;
|
|
|
|
obj->u.res = rres;
|
|
|
|
} else if (return_value) {
|
|
|
|
ZEND_REGISTER_RESOURCE(object ? NULL : return_value, rres, le_sqlite_result);
|
2003-06-10 07:14:25 +08:00
|
|
|
}
|
2003-04-18 20:22:43 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type ])
|
|
|
|
Execute a query that does not prefetch and buffer all data */
|
|
|
|
PHP_FUNCTION(sqlite_unbuffered_query)
|
2003-04-17 09:29:45 +08:00
|
|
|
{
|
|
|
|
zval *zdb;
|
2003-04-18 04:08:00 +08:00
|
|
|
struct php_sqlite_db *db;
|
2003-04-17 09:29:45 +08:00
|
|
|
char *sql;
|
|
|
|
long sql_len;
|
2003-04-30 23:18:59 +08:00
|
|
|
int mode = PHPSQLITE_BOTH;
|
2003-05-03 06:09:54 +08:00
|
|
|
char *errtext = NULL;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &sql, &sql_len, &mode)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
2003-04-30 23:18:59 +08:00
|
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode) &&
|
|
|
|
FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode)) {
|
2003-06-23 01:19:46 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-19 00:30:16 +08:00
|
|
|
/* avoid doing work if we can */
|
|
|
|
if (!return_value_used) {
|
|
|
|
db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
|
|
|
|
|
|
|
|
if (db->last_err_code != SQLITE_OK) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
|
|
|
|
sqlite_freemem(errtext);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2003-06-23 01:19:46 +08:00
|
|
|
|
|
|
|
sqlite_query(object, db, sql, sql_len, mode, 0, return_value, NULL TSRMLS_CC);
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* {{{ proto resource sqlite_query(string query, resource db [ , int result_type ])
|
|
|
|
Executes a query against a given database and returns a result handle */
|
|
|
|
PHP_FUNCTION(sqlite_query)
|
|
|
|
{
|
|
|
|
zval *zdb;
|
|
|
|
struct php_sqlite_db *db;
|
|
|
|
char *sql;
|
|
|
|
long sql_len;
|
|
|
|
int mode = PHPSQLITE_BOTH;
|
|
|
|
char *errtext = NULL;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &sql, &sql_len, &mode)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &sql, &sql_len, &zdb, &mode) &&
|
|
|
|
FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &sql, &sql_len, &mode)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* avoid doing work if we can */
|
|
|
|
if (!return_value_used) {
|
|
|
|
db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
|
2003-04-18 20:22:43 +08:00
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
if (db->last_err_code != SQLITE_OK) {
|
2003-06-07 19:38:03 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
|
|
|
|
sqlite_freemem(errtext);
|
|
|
|
}
|
2003-05-03 06:09:54 +08:00
|
|
|
return;
|
2003-04-18 20:22:43 +08:00
|
|
|
}
|
2003-06-23 01:19:46 +08:00
|
|
|
|
|
|
|
sqlite_query(object, db, sql, sql_len, mode, 1, return_value, NULL TSRMLS_CC);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* {{{ php_sqlite_fetch_array */
|
|
|
|
static void php_sqlite_fetch_array(struct php_sqlite_result *res, int mode, zend_bool decode_binary, int move_next, zval *return_value TSRMLS_DC)
|
2003-04-17 09:29:45 +08:00
|
|
|
{
|
2003-06-23 01:19:46 +08:00
|
|
|
int j, n = res->ncolumns, buffered = res->buffered;
|
2003-04-18 20:22:43 +08:00
|
|
|
const char **rowdata, **colnames;
|
2003-06-23 01:19:46 +08:00
|
|
|
|
2003-04-27 21:25:10 +08:00
|
|
|
/* check range of the row */
|
|
|
|
if (res->curr_row >= res->nrows) {
|
|
|
|
/* no more */
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
colnames = (const char**)res->col_names;
|
2003-04-18 20:22:43 +08:00
|
|
|
if (res->buffered) {
|
|
|
|
rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
|
|
|
|
} else {
|
2003-04-27 21:25:10 +08:00
|
|
|
rowdata = (const char**)res->table;
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-18 20:22:43 +08:00
|
|
|
/* now populate the result */
|
2003-04-17 09:29:45 +08:00
|
|
|
array_init(return_value);
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
for (j = 0; j < n; j++) {
|
2003-06-07 03:00:16 +08:00
|
|
|
zval *decoded;
|
|
|
|
MAKE_STD_ZVAL(decoded);
|
2003-04-19 20:54:17 +08:00
|
|
|
|
2003-06-10 07:14:25 +08:00
|
|
|
if (rowdata[j] == NULL) {
|
|
|
|
ZVAL_NULL(decoded);
|
|
|
|
} else if (decode_binary && rowdata[j][0] == '\x01') {
|
2003-06-15 02:16:47 +08:00
|
|
|
Z_STRVAL_P(decoded) = emalloc(strlen(rowdata[j]));
|
|
|
|
Z_STRLEN_P(decoded) = sqlite_decode_binary(rowdata[j]+1, Z_STRVAL_P(decoded));
|
|
|
|
Z_STRVAL_P(decoded)[Z_STRLEN_P(decoded)] = '\0';
|
2003-06-07 03:00:16 +08:00
|
|
|
Z_TYPE_P(decoded) = IS_STRING;
|
2003-06-10 07:14:25 +08:00
|
|
|
if (!buffered) {
|
|
|
|
efree((char*)rowdata[j]);
|
|
|
|
rowdata[j] = NULL;
|
|
|
|
}
|
2003-04-19 20:54:17 +08:00
|
|
|
} else {
|
2003-06-10 07:14:25 +08:00
|
|
|
ZVAL_STRING(decoded, (char*)rowdata[j], buffered);
|
|
|
|
if (!buffered) {
|
|
|
|
rowdata[j] = NULL;
|
2003-04-19 20:54:17 +08:00
|
|
|
}
|
|
|
|
}
|
2003-06-07 03:00:16 +08:00
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
if (mode & PHPSQLITE_NUM) {
|
2003-06-07 03:00:16 +08:00
|
|
|
if (mode & PHPSQLITE_ASSOC) {
|
2003-06-15 02:16:47 +08:00
|
|
|
add_index_zval(return_value, j, decoded);
|
2003-06-07 03:00:16 +08:00
|
|
|
ZVAL_ADDREF(decoded);
|
|
|
|
add_assoc_zval(return_value, (char*)colnames[j], decoded);
|
2003-06-15 02:16:47 +08:00
|
|
|
} else {
|
|
|
|
add_next_index_zval(return_value, decoded);
|
2003-04-18 01:09:59 +08:00
|
|
|
}
|
2003-06-07 03:00:16 +08:00
|
|
|
} else {
|
|
|
|
add_assoc_zval(return_value, (char*)colnames[j], decoded);
|
2003-04-19 20:54:17 +08:00
|
|
|
}
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
if (move_next) {
|
2003-05-03 20:51:13 +08:00
|
|
|
if (!res->buffered) {
|
|
|
|
/* non buffered: fetch next row */
|
|
|
|
php_sqlite_fetch(res TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* advance the row pointer */
|
|
|
|
res->curr_row++;
|
2003-04-27 21:25:10 +08:00
|
|
|
}
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
2003-05-03 20:51:13 +08:00
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ php_sqlite_fetch_column */
|
|
|
|
static void php_sqlite_fetch_column(struct php_sqlite_result *res, zval *which, zend_bool decode_binary, zval *return_value TSRMLS_DC)
|
|
|
|
{
|
|
|
|
int j;
|
|
|
|
const char **rowdata, **colnames;
|
|
|
|
|
|
|
|
/* check range of the row */
|
|
|
|
if (res->curr_row >= res->nrows) {
|
|
|
|
/* no more */
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
colnames = (const char**)res->col_names;
|
|
|
|
|
|
|
|
if (Z_TYPE_P(which) == IS_LONG) {
|
|
|
|
j = Z_LVAL_P(which);
|
|
|
|
} else {
|
|
|
|
convert_to_string_ex(&which);
|
|
|
|
for (j = 0; j < res->ncolumns; j++) {
|
|
|
|
if (!strcasecmp((char*)colnames[j], Z_STRVAL_P(which))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (j < 0 || j >= res->ncolumns) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "No such column %d", j);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2003-06-10 07:14:25 +08:00
|
|
|
if (res->buffered) {
|
|
|
|
rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
|
2003-05-03 20:51:13 +08:00
|
|
|
} else {
|
2003-06-10 07:14:25 +08:00
|
|
|
rowdata = (const char**)res->table;
|
2003-05-03 20:51:13 +08:00
|
|
|
}
|
2003-06-10 07:14:25 +08:00
|
|
|
|
|
|
|
if (rowdata[j] == NULL) {
|
2003-05-03 20:51:13 +08:00
|
|
|
RETURN_NULL();
|
2003-06-23 01:19:46 +08:00
|
|
|
} else if (decode_binary && rowdata[j] != NULL && rowdata[j][0] == '\x01') {
|
2003-06-10 07:14:25 +08:00
|
|
|
int l = strlen(rowdata[j]);
|
|
|
|
char *decoded = emalloc(l);
|
|
|
|
l = sqlite_decode_binary(rowdata[j]+1, decoded);
|
|
|
|
decoded[l] = '\0';
|
|
|
|
RETVAL_STRINGL(decoded, l, 0);
|
|
|
|
if (!res->buffered) {
|
|
|
|
efree((char*)rowdata[j]);
|
|
|
|
rowdata[j] = NULL;
|
2003-06-23 01:19:46 +08:00
|
|
|
}
|
2003-05-03 20:51:13 +08:00
|
|
|
} else {
|
2003-06-10 07:14:25 +08:00
|
|
|
RETVAL_STRING((char*)rowdata[j], res->buffered);
|
|
|
|
if (!res->buffered) {
|
|
|
|
rowdata[j] = NULL;
|
2003-06-23 01:19:46 +08:00
|
|
|
}
|
2003-05-03 20:51:13 +08:00
|
|
|
}
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-06-07 03:00:16 +08:00
|
|
|
/* {{{ proto array sqlite_fetch_all(resource result [, int result_type, bool decode_binary])
|
|
|
|
Fetches all rows from a result set as an array */
|
|
|
|
PHP_FUNCTION(sqlite_fetch_all)
|
|
|
|
{
|
|
|
|
zval *zres, *ent;
|
|
|
|
int mode = PHPSQLITE_BOTH;
|
|
|
|
zend_bool decode_binary = 1;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-06-07 03:00:16 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
if (!ZEND_NUM_ARGS()) {
|
|
|
|
mode = res->mode;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
|
|
|
if (ZEND_NUM_ARGS() < 2) {
|
|
|
|
mode = res->mode;
|
|
|
|
}
|
2003-06-07 03:00:16 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (res->curr_row >= res->nrows && res->nrows) {
|
|
|
|
if (!res->buffered) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "One or more rowsets were already returned");
|
|
|
|
} else {
|
|
|
|
res->curr_row = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
array_init(return_value);
|
|
|
|
|
|
|
|
while (res->curr_row < res->nrows) {
|
|
|
|
MAKE_STD_ZVAL(ent);
|
|
|
|
php_sqlite_fetch_array(res, mode, decode_binary, 1, ent TSRMLS_CC);
|
|
|
|
add_next_index_zval(return_value, ent);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* {{{ proto array sqlite_fetch_array(resource result [, int result_type, bool decode_binary])
|
|
|
|
Fetches the next row from a result set as an array */
|
|
|
|
PHP_FUNCTION(sqlite_fetch_array)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
int mode = PHPSQLITE_BOTH;
|
|
|
|
zend_bool decode_binary = 1;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-05-03 06:09:54 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
if (!ZEND_NUM_ARGS()) {
|
|
|
|
mode = res->mode;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
|
|
|
if (ZEND_NUM_ARGS() < 2) {
|
|
|
|
mode = res->mode;
|
|
|
|
}
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
php_sqlite_fetch_array(res, mode, decode_binary, 1, return_value TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-06-10 07:14:25 +08:00
|
|
|
/* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type, bool decode_binary ])
|
|
|
|
Executes a query against a given database and returns an array */
|
|
|
|
PHP_FUNCTION(sqlite_array_query)
|
|
|
|
{
|
|
|
|
zval *zdb, *ent;
|
|
|
|
struct php_sqlite_db *db;
|
|
|
|
struct php_sqlite_result *rres;
|
|
|
|
char *sql;
|
|
|
|
long sql_len;
|
|
|
|
int mode = PHPSQLITE_BOTH;
|
|
|
|
char *errtext = NULL;
|
|
|
|
zend_bool decode_binary = 1;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-06-10 07:14:25 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &sql, &sql_len, &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "sr|lb", &sql, &sql_len, &zdb, &mode, &decode_binary) &&
|
|
|
|
FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lb", &zdb, &sql, &sql_len, &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-06-10 07:14:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
/* avoid doing work if we can */
|
|
|
|
if (!return_value_used) {
|
|
|
|
db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
|
|
|
|
|
|
|
|
if (db->last_err_code != SQLITE_OK) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
|
|
|
|
sqlite_freemem(errtext);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
2003-06-23 01:19:46 +08:00
|
|
|
|
2003-06-10 07:14:25 +08:00
|
|
|
rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
|
2003-06-23 01:19:46 +08:00
|
|
|
sqlite_query(NULL, db, sql, sql_len, mode, 0, NULL, rres TSRMLS_CC);
|
2003-06-24 03:37:48 +08:00
|
|
|
if (db->last_err_code != SQLITE_OK) {
|
|
|
|
efree(rres);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-06-10 07:14:25 +08:00
|
|
|
|
|
|
|
array_init(return_value);
|
|
|
|
|
|
|
|
while (rres->curr_row < rres->nrows) {
|
|
|
|
MAKE_STD_ZVAL(ent);
|
|
|
|
php_sqlite_fetch_array(rres, mode, decode_binary, 1, ent TSRMLS_CC);
|
|
|
|
add_next_index_zval(return_value, ent);
|
|
|
|
}
|
|
|
|
real_result_dtor(rres TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-06-27 03:26:26 +08:00
|
|
|
/* {{{ php_sqlite_fetch_single */
|
|
|
|
static void php_sqlite_fetch_single(struct php_sqlite_result *res, zend_bool decode_binary, zval *return_value TSRMLS_DC)
|
2003-05-14 07:51:25 +08:00
|
|
|
{
|
2003-06-26 00:59:24 +08:00
|
|
|
const char **rowdata;
|
2003-06-26 07:21:10 +08:00
|
|
|
char *decoded;
|
2003-05-14 07:51:25 +08:00
|
|
|
int decoded_len;
|
2003-06-26 00:59:24 +08:00
|
|
|
|
|
|
|
/* check range of the row */
|
2003-05-14 07:51:25 +08:00
|
|
|
if (res->curr_row >= res->nrows) {
|
2003-06-26 00:59:24 +08:00
|
|
|
/* no more */
|
2003-05-14 07:51:25 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-06-26 00:59:24 +08:00
|
|
|
|
2003-05-14 07:51:25 +08:00
|
|
|
if (res->buffered) {
|
|
|
|
rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
|
|
|
|
} else {
|
|
|
|
rowdata = (const char**)res->table;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (decode_binary && rowdata[0] != NULL && rowdata[0][0] == '\x01') {
|
2003-06-15 02:16:47 +08:00
|
|
|
decoded = emalloc(strlen(rowdata[0]));
|
2003-05-14 07:51:25 +08:00
|
|
|
decoded_len = sqlite_decode_binary(rowdata[0]+1, decoded);
|
2003-06-15 02:16:47 +08:00
|
|
|
if (!res->buffered) {
|
|
|
|
efree((char*)rowdata[0]);
|
|
|
|
rowdata[0] = NULL;
|
|
|
|
}
|
2003-06-26 00:59:24 +08:00
|
|
|
} else if (rowdata[0]) {
|
|
|
|
decoded_len = strlen((char*)rowdata[0]);
|
|
|
|
if (res->buffered) {
|
|
|
|
decoded = estrndup((char*)rowdata[0], decoded_len);
|
2003-06-15 02:16:47 +08:00
|
|
|
} else {
|
2003-06-26 00:59:24 +08:00
|
|
|
decoded = (char*)rowdata[0];
|
|
|
|
rowdata[0] = NULL;
|
2003-06-15 02:16:47 +08:00
|
|
|
}
|
2003-06-26 07:21:10 +08:00
|
|
|
} else {
|
|
|
|
decoded = NULL;
|
|
|
|
decoded_len = 0;
|
2003-05-14 07:51:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!res->buffered) {
|
|
|
|
/* non buffered: fetch next row */
|
|
|
|
php_sqlite_fetch(res TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* advance the row pointer */
|
|
|
|
res->curr_row++;
|
|
|
|
|
|
|
|
if (decoded == NULL) {
|
|
|
|
RETURN_NULL();
|
|
|
|
} else {
|
2003-06-15 02:16:47 +08:00
|
|
|
RETURN_STRINGL(decoded, decoded_len, 0);
|
2003-05-14 07:51:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-06-26 00:59:24 +08:00
|
|
|
|
|
|
|
/* {{{ proto array sqlite_single_query(resource db, string query [ , bool single_row, bool decode_binary ])
|
|
|
|
Executes a query against a given database and returns an array */
|
|
|
|
PHP_FUNCTION(sqlite_single_query)
|
|
|
|
{
|
|
|
|
zval *zdb, *ent;
|
|
|
|
struct php_sqlite_db *db;
|
|
|
|
struct php_sqlite_result *rres;
|
|
|
|
char *sql;
|
|
|
|
long sql_len;
|
|
|
|
char *errtext = NULL;
|
|
|
|
zend_bool decode_binary = 1;
|
|
|
|
zend_bool srow = 1;
|
|
|
|
zval *object = getThis();
|
|
|
|
|
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", &sql, &sql_len, &srow, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
|
|
|
|
ZEND_NUM_ARGS() TSRMLS_CC, "sr|bb", &sql, &sql_len, &zdb, &srow, &decode_binary) &&
|
|
|
|
FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|bb", &zdb, &sql, &sql_len, &srow, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* avoid doing work if we can */
|
|
|
|
if (!return_value_used) {
|
|
|
|
db->last_err_code = sqlite_exec(db->db, sql, NULL, NULL, &errtext);
|
|
|
|
|
|
|
|
if (db->last_err_code != SQLITE_OK) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
|
|
|
|
sqlite_freemem(errtext);
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
rres = (struct php_sqlite_result *)emalloc(sizeof(*rres));
|
|
|
|
sqlite_query(NULL, db, sql, sql_len, PHPSQLITE_NUM, 0, NULL, rres TSRMLS_CC);
|
|
|
|
if (db->last_err_code != SQLITE_OK) {
|
|
|
|
efree(rres);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!srow) {
|
|
|
|
array_init(return_value);
|
|
|
|
}
|
|
|
|
|
|
|
|
while (rres->curr_row < rres->nrows) {
|
|
|
|
MAKE_STD_ZVAL(ent);
|
2003-06-27 03:26:26 +08:00
|
|
|
php_sqlite_fetch_single(rres, decode_binary, ent TSRMLS_CC);
|
2003-06-26 00:59:24 +08:00
|
|
|
|
|
|
|
/* if set and we only have 1 row in the result set, return the result as a string. */
|
|
|
|
if (srow) {
|
|
|
|
if (rres->curr_row == 1 && rres->curr_row >= rres->nrows) {
|
|
|
|
*return_value = *ent;
|
|
|
|
zval_copy_ctor(return_value);
|
|
|
|
zval_dtor(ent);
|
|
|
|
FREE_ZVAL(ent);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
srow = 0;
|
|
|
|
array_init(return_value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
add_next_index_zval(return_value, ent);
|
|
|
|
}
|
|
|
|
|
|
|
|
real_result_dtor(rres TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
|
|
|
/* {{{ proto string sqlite_fetch_array(resource result [, bool decode_binary])
|
|
|
|
Fetches first column of a result set as a string */
|
2003-06-27 03:26:26 +08:00
|
|
|
PHP_FUNCTION(sqlite_fetch_single)
|
2003-06-26 00:59:24 +08:00
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
zend_bool decode_binary = 1;
|
|
|
|
struct php_sqlite_result *res;
|
|
|
|
zval *object = getThis();
|
|
|
|
|
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|b", &zres, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
|
|
|
}
|
|
|
|
|
2003-06-27 03:26:26 +08:00
|
|
|
php_sqlite_fetch_single(res, decode_binary, return_value TSRMLS_CC);
|
2003-06-26 00:59:24 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* {{{ proto array sqlite_fetch_array(resource result [, int result_type, bool decode_binary])
|
2003-05-03 20:51:13 +08:00
|
|
|
Fetches the current row from a result set as an array */
|
2003-05-03 06:09:54 +08:00
|
|
|
PHP_FUNCTION(sqlite_current)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
int mode = PHPSQLITE_BOTH;
|
|
|
|
zend_bool decode_binary = 1;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-05-03 06:09:54 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() && FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|lb", &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
if (!ZEND_NUM_ARGS()) {
|
|
|
|
mode = res->mode;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
|
|
|
if (ZEND_NUM_ARGS() < 2) {
|
|
|
|
mode = res->mode;
|
|
|
|
}
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
php_sqlite_fetch_array(res, mode, decode_binary, 0, return_value TSRMLS_CC);
|
|
|
|
}
|
2003-04-17 09:29:45 +08:00
|
|
|
/* }}} */
|
|
|
|
|
2003-06-21 20:29:32 +08:00
|
|
|
/* {{{ proto mixed sqlite_column(resource result, mixed index_or_name [, bool decode_binary])
|
|
|
|
Fetches a column from the current row of a result set */
|
2003-05-03 20:51:13 +08:00
|
|
|
PHP_FUNCTION(sqlite_column)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
zval *which;
|
|
|
|
zend_bool decode_binary = 1;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-05-03 20:51:13 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &which, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zres, &which, &decode_binary)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-05-03 20:51:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
php_sqlite_fetch_column(res, which, decode_binary, return_value TSRMLS_CC);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
/* {{{ proto string sqlite_libversion()
|
|
|
|
Returns the version of the linked SQLite library */
|
|
|
|
PHP_FUNCTION(sqlite_libversion)
|
|
|
|
{
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
RETURN_STRING((char*)sqlite_libversion(), 1);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string sqlite_libencoding()
|
|
|
|
Returns the encoding (iso8859 or UTF-8) of the linked SQLite library */
|
|
|
|
PHP_FUNCTION(sqlite_libencoding)
|
|
|
|
{
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT;
|
|
|
|
}
|
|
|
|
RETURN_STRING((char*)sqlite_libencoding(), 1);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto int sqlite_changes(resource db)
|
|
|
|
Returns the number of rows that were changed by the most recent SQL statement */
|
|
|
|
PHP_FUNCTION(sqlite_changes)
|
|
|
|
{
|
|
|
|
zval *zdb;
|
2003-04-18 04:08:00 +08:00
|
|
|
struct php_sqlite_db *db;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-18 04:08:00 +08:00
|
|
|
RETURN_LONG(sqlite_changes(db->db));
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto int sqlite_last_insert_rowid(resource db)
|
|
|
|
Returns the rowid of the most recently inserted row */
|
|
|
|
PHP_FUNCTION(sqlite_last_insert_rowid)
|
|
|
|
{
|
|
|
|
zval *zdb;
|
2003-04-18 04:08:00 +08:00
|
|
|
struct php_sqlite_db *db;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-18 04:08:00 +08:00
|
|
|
RETURN_LONG(sqlite_last_insert_rowid(db->db));
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto int sqlite_num_rows(resource result)
|
|
|
|
Returns the number of rows in a result set */
|
|
|
|
PHP_FUNCTION(sqlite_num_rows)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-18 20:22:43 +08:00
|
|
|
if (res->buffered) {
|
|
|
|
RETURN_LONG(res->nrows);
|
|
|
|
} else {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Row count is not available for unbuffered queries");
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
/* {{{ proto bool sqlite_has_more(resource result)
|
|
|
|
Returns whether or not more rows are available */
|
|
|
|
PHP_FUNCTION(sqlite_has_more)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-05-03 06:09:54 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
RETURN_BOOL(res->curr_row < res->nrows && res->nrows); /* curr_row may be -1 */
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
/* {{{ proto int sqlite_num_fields(resource result)
|
|
|
|
Returns the number of fields in a result set */
|
|
|
|
PHP_FUNCTION(sqlite_num_fields)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-27 21:25:10 +08:00
|
|
|
RETURN_LONG(res->ncolumns);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string sqlite_field_name(resource result, int field)
|
|
|
|
Returns the name of a particular field */
|
|
|
|
PHP_FUNCTION(sqlite_field_name)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
struct php_sqlite_result *res;
|
|
|
|
int field;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|l", &field)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|l", &zres, &field)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-27 21:25:10 +08:00
|
|
|
if (field < 0 || field >= res->ncolumns) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %d out of range", field);
|
2003-04-17 09:29:45 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
2003-04-27 21:25:10 +08:00
|
|
|
|
|
|
|
RETURN_STRING(res->col_names[field], 1);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto bool sqlite_seek(resource result, int row)
|
|
|
|
Seek to a particular row number */
|
|
|
|
PHP_FUNCTION(sqlite_seek)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
struct php_sqlite_result *res;
|
|
|
|
int row;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 09:29:45 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &row)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl", &zres, &row)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-04-17 09:29:45 +08:00
|
|
|
}
|
|
|
|
|
2003-04-18 20:22:43 +08:00
|
|
|
if (!res->buffered) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set");
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
if (row < 1 || row >= res->nrows) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "row %d out of range", row);
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
2003-05-03 06:09:54 +08:00
|
|
|
res->curr_row = row;
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto bool sqlite_rewind(resource result)
|
|
|
|
Seek to first row number */
|
|
|
|
PHP_FUNCTION(sqlite_rewind)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-05-03 06:09:54 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!res->buffered) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot seek an unbuffered result set");
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!res->nrows) {
|
2003-06-07 03:00:16 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_NOTICE, "no rows received");
|
2003-05-03 06:09:54 +08:00
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
res->curr_row = 0;
|
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto bool sqlite_next(resource result)
|
|
|
|
Seek to next row number */
|
|
|
|
PHP_FUNCTION(sqlite_next)
|
|
|
|
{
|
|
|
|
zval *zres;
|
|
|
|
struct php_sqlite_result *res;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-05-03 06:09:54 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
RES_FROM_OBJECT(res, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zres)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
|
2003-05-03 06:09:54 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!res->buffered && res->vm) {
|
|
|
|
php_sqlite_fetch(res TSRMLS_CC);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (res->curr_row >= res->nrows) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "no more rows available");
|
|
|
|
RETURN_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
res->curr_row++;
|
|
|
|
|
2003-04-17 09:29:45 +08:00
|
|
|
RETURN_TRUE;
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-17 10:20:26 +08:00
|
|
|
/* {{{ proto string sqlite_escape_string(string item)
|
|
|
|
Escapes a string for use as a query parameter */
|
|
|
|
PHP_FUNCTION(sqlite_escape_string)
|
|
|
|
{
|
2003-04-19 20:54:17 +08:00
|
|
|
char *string = NULL;
|
2003-04-17 10:20:26 +08:00
|
|
|
long stringlen;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &stringlen)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2003-04-19 20:54:17 +08:00
|
|
|
if (stringlen && (string[0] == '\x01' || memchr(string, '\0', stringlen) != NULL)) {
|
|
|
|
/* binary string */
|
|
|
|
int enclen;
|
|
|
|
|
|
|
|
ret = emalloc( 1 + ((256 * stringlen + 1262) / 253) );
|
|
|
|
ret[0] = '\x01';
|
|
|
|
enclen = sqlite_encode_binary((const unsigned char*)string, stringlen, ret+1);
|
|
|
|
RETVAL_STRINGL(ret, enclen+1, 0);
|
|
|
|
|
|
|
|
} else {
|
|
|
|
ret = sqlite_mprintf("%q", string);
|
|
|
|
if (ret) {
|
|
|
|
RETVAL_STRING(ret, 1);
|
|
|
|
sqlite_freemem(ret);
|
|
|
|
}
|
2003-04-17 10:20:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
2003-04-18 04:08:00 +08:00
|
|
|
/* {{{ proto int sqlite_last_error(resource db)
|
|
|
|
Returns the error code of the last error for a database */
|
|
|
|
PHP_FUNCTION(sqlite_last_error)
|
|
|
|
{
|
|
|
|
zval *zdb;
|
|
|
|
struct php_sqlite_db *db;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
2003-04-17 10:20:26 +08:00
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
if (object) {
|
|
|
|
if (ZEND_NUM_ARGS() != 0) {
|
|
|
|
WRONG_PARAM_COUNT
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zdb)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-18 04:08:00 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
RETURN_LONG(db->last_err_code);
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string sqlite_error_string(int error_code)
|
|
|
|
Returns the textual description of an error code */
|
|
|
|
PHP_FUNCTION(sqlite_error_string)
|
|
|
|
{
|
|
|
|
long code;
|
|
|
|
const char *msg;
|
|
|
|
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &code)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
msg = sqlite_error_string(code);
|
|
|
|
|
|
|
|
if (msg) {
|
|
|
|
RETURN_STRING((char*)msg, 1);
|
|
|
|
} else {
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
2003-04-20 21:08:22 +08:00
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
/* manages duplicate registrations of a particular function, and
|
|
|
|
* also handles the case where the db is using a persistent connection */
|
|
|
|
enum callback_prep_t { DO_REG, SKIP_REG, ERR };
|
|
|
|
|
|
|
|
static enum callback_prep_t prep_callback_struct(struct php_sqlite_db *db, int is_agg,
|
|
|
|
char *funcname,
|
|
|
|
zval *step, zval *fini, struct php_sqlite_agg_functions **funcs)
|
|
|
|
{
|
|
|
|
struct php_sqlite_agg_functions *alloc_funcs, func_tmp;
|
|
|
|
char *hashkey;
|
|
|
|
int hashkeylen;
|
|
|
|
enum callback_prep_t ret;
|
|
|
|
|
|
|
|
hashkeylen = spprintf(&hashkey, 0, "%s-%s", is_agg ? "agg" : "reg", funcname);
|
|
|
|
|
|
|
|
/* is it already registered ? */
|
|
|
|
if (SUCCESS == zend_hash_find(&db->callbacks, hashkey, hashkeylen+1, (void*)&alloc_funcs)) {
|
|
|
|
/* override the previous definition */
|
|
|
|
|
|
|
|
if (alloc_funcs->is_valid) {
|
|
|
|
/* release these */
|
|
|
|
|
|
|
|
if (alloc_funcs->step) {
|
|
|
|
zval_ptr_dtor(&alloc_funcs->step);
|
|
|
|
alloc_funcs->step = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (alloc_funcs->fini) {
|
|
|
|
zval_ptr_dtor(&alloc_funcs->fini);
|
|
|
|
alloc_funcs->fini = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret = SKIP_REG;
|
|
|
|
} else {
|
|
|
|
/* add a new one */
|
|
|
|
func_tmp.db = db;
|
|
|
|
|
|
|
|
ret = SUCCESS == zend_hash_update(&db->callbacks, hashkey, hashkeylen+1,
|
|
|
|
(void*)&func_tmp, sizeof(func_tmp), (void**)&alloc_funcs) ? DO_REG : ERR;
|
|
|
|
}
|
|
|
|
|
|
|
|
efree(hashkey);
|
|
|
|
|
|
|
|
MAKE_STD_ZVAL(alloc_funcs->step);
|
|
|
|
*(alloc_funcs->step) = *step;
|
|
|
|
zval_copy_ctor(alloc_funcs->step);
|
|
|
|
|
|
|
|
if (is_agg) {
|
|
|
|
MAKE_STD_ZVAL(alloc_funcs->fini);
|
|
|
|
*(alloc_funcs->fini) = *fini;
|
|
|
|
zval_copy_ctor(alloc_funcs->fini);
|
|
|
|
} else {
|
|
|
|
alloc_funcs->fini = NULL;
|
|
|
|
}
|
|
|
|
alloc_funcs->is_valid = 1;
|
|
|
|
*funcs = alloc_funcs;
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2003-04-20 21:31:36 +08:00
|
|
|
/* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args])
|
2003-04-20 21:08:22 +08:00
|
|
|
Registers an aggregated function for queries*/
|
|
|
|
PHP_FUNCTION(sqlite_create_aggregate)
|
|
|
|
{
|
|
|
|
char *funcname = NULL;
|
|
|
|
long funcname_len;
|
|
|
|
zval *zstep, *zfinal, *zdb;
|
|
|
|
struct php_sqlite_db *db;
|
|
|
|
struct php_sqlite_agg_functions *funcs;
|
|
|
|
char *callable = NULL;
|
|
|
|
long num_args = -1;
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
|
|
|
|
|
|
|
if (object) {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rszz|l", &zdb, &funcname, &funcname_len, &zstep, &zfinal, &num_args)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-20 21:08:22 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!zend_is_callable(zstep, 0, &callable)) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "step function `%s' is not callable", callable);
|
|
|
|
efree(callable);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
efree(callable);
|
|
|
|
|
|
|
|
if (!zend_is_callable(zfinal, 0, &callable)) {
|
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "finalize function `%s' is not callable", callable);
|
|
|
|
efree(callable);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
efree(callable);
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
if (prep_callback_struct(db, 1, funcname, zstep, zfinal, &funcs) == DO_REG) {
|
|
|
|
sqlite_create_aggregate(db->db, funcname, num_args,
|
|
|
|
php_sqlite_agg_step_function_callback,
|
|
|
|
php_sqlite_agg_fini_function_callback, funcs);
|
|
|
|
}
|
2003-04-20 21:08:22 +08:00
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
|
2003-04-20 21:08:22 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
2003-04-20 21:31:36 +08:00
|
|
|
|
|
|
|
/* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args])
|
|
|
|
Registers a "regular" function for queries */
|
|
|
|
PHP_FUNCTION(sqlite_create_function)
|
|
|
|
{
|
|
|
|
char *funcname = NULL;
|
|
|
|
long funcname_len;
|
|
|
|
zval *zcall, *zdb;
|
|
|
|
struct php_sqlite_db *db;
|
|
|
|
struct php_sqlite_agg_functions *funcs;
|
|
|
|
char *callable = NULL;
|
|
|
|
long num_args = -1;
|
|
|
|
|
2003-06-23 01:19:46 +08:00
|
|
|
zval *object = getThis();
|
|
|
|
|
|
|
|
if (object) {
|
2003-06-26 01:22:31 +08:00
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &funcname, &funcname_len, &zcall, &num_args)) {
|
2003-06-23 01:19:46 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_OBJECT(db, object);
|
|
|
|
} else {
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rsz|l", &zdb, &funcname, &funcname_len, &zcall, &num_args)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
DB_FROM_ZVAL(db, &zdb);
|
2003-04-20 21:31:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!zend_is_callable(zcall, 0, &callable)) {
|
2003-04-20 23:13:04 +08:00
|
|
|
php_error_docref(NULL TSRMLS_CC, E_WARNING, "function `%s' is not callable", callable);
|
2003-04-20 21:31:36 +08:00
|
|
|
efree(callable);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
efree(callable);
|
|
|
|
|
2003-04-20 23:13:04 +08:00
|
|
|
if (prep_callback_struct(db, 0, funcname, zcall, NULL, &funcs) == DO_REG) {
|
|
|
|
sqlite_create_function(db->db, funcname, num_args, php_sqlite_function_callback, funcs);
|
|
|
|
}
|
2003-04-20 21:31:36 +08:00
|
|
|
}
|
|
|
|
/* }}} */
|
2003-04-22 08:08:48 +08:00
|
|
|
|
2003-06-21 20:29:32 +08:00
|
|
|
/* {{{ proto string sqlite_udf_encode_binary(string data)
|
|
|
|
Apply binary encoding (if required) to a string to return from an UDF */
|
|
|
|
PHP_FUNCTION(sqlite_udf_encode_binary)
|
|
|
|
{
|
|
|
|
char *data = NULL;
|
|
|
|
long datalen;
|
|
|
|
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data == NULL) {
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
if (datalen && (data[0] == '\x01' || memchr(data, '\0', datalen) != NULL)) {
|
|
|
|
/* binary string */
|
|
|
|
int enclen;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
ret = emalloc( 1 + ((256 * datalen + 1262) / 253) );
|
|
|
|
ret[0] = '\x01';
|
|
|
|
enclen = sqlite_encode_binary((const unsigned char*)data, datalen, ret+1);
|
|
|
|
RETVAL_STRINGL(ret, enclen+1, 0);
|
|
|
|
} else {
|
|
|
|
RETVAL_STRINGL(data, datalen, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
/* {{{ proto string sqlite_udf_decode_binary(string data)
|
|
|
|
Decode binary encoding on a string parameter passed to an UDF */
|
|
|
|
PHP_FUNCTION(sqlite_udf_decode_binary)
|
|
|
|
{
|
|
|
|
char *data = NULL;
|
|
|
|
long datalen;
|
|
|
|
|
|
|
|
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s!", &data, &datalen)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (data == NULL) {
|
|
|
|
RETURN_NULL();
|
|
|
|
}
|
|
|
|
if (datalen && data[0] == '\x01') {
|
|
|
|
/* encoded string */
|
|
|
|
int enclen;
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
ret = emalloc(datalen);
|
|
|
|
enclen = sqlite_decode_binary((const unsigned char*)data+1, ret);
|
|
|
|
ret[enclen] = '\0';
|
|
|
|
RETVAL_STRINGL(ret, enclen, 0);
|
|
|
|
} else {
|
|
|
|
RETVAL_STRINGL(data, datalen, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* }}} */
|
|
|
|
|
|
|
|
|
2003-04-22 08:08:48 +08:00
|
|
|
/*
|
|
|
|
* Local variables:
|
|
|
|
* tab-width: 4
|
|
|
|
* c-basic-offset: 4
|
|
|
|
* End:
|
|
|
|
* vim600: sw=4 ts=4 fdm=marker
|
|
|
|
* vim<600: sw=4 ts=4
|
|
|
|
*/
|