#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
+#include "ext/standard/file.h"
+#include "ext/standard/php_string.h"
#if HAVE_PHP_SESSION && !defined(COMPILE_DL_SESSION)
#include "ext/session/php_session.h"
#endif
+#include <sqlite.h>
#include "php_sqlite.h"
#if HAVE_TIME_H
#include <unistd.h>
#endif
-#include <sqlite.h>
+
+#ifdef SQLITE_UTF8
+#define SQLITE2_CONV UG(utf8_conv)
+#else /* ISO 8859 */
+#define SQLITE2_CONV SQLITE_G(iso8859_conv)
+#endif
#include "zend_exceptions.h"
#include "zend_interfaces.h"
}
}
+#ifdef SQLITE_ISO8859
+static ZEND_INI_MH(OnUpdateEncodingISO8859)
+{
+ UConverter **converter;
+#ifndef ZTS
+ char *base = (char *) mh_arg2;
+#else
+ char *base = (char *) ts_resource(*((int *) mh_arg2));
+#endif
+ char encoding[sizeof("iso-8859-999")];
+
+ converter = (UConverter **) (base+(size_t) mh_arg1);
+ if (new_value_length > 3) {
+ /* Really, 2 is sufficient, but be generous, the zend_set_converter_encoding call will find it out */
+ zend_error(E_CORE_ERROR, "Unrecognized locale '%s' for iso-8859 encoding used for %s", new_value ? new_value : "1", entry->name);
+ return FAILURE;
+ }
+
+ snprintf(encoding, sizeof("iso-8859-999"), "iso-8859-%s", new_value ? new_value : "1");
+
+ if (zend_set_converter_encoding(converter, encoding) == FAILURE) {
+ zend_error(E_CORE_ERROR, "Unrecognized locale '%s' for iso-8859 encoding used for %s", new_value ? new_value : "1", entry->name);
+ return FAILURE;
+ }
+
+ if (*converter) {
+ zend_set_converter_error_mode(*converter, ZEND_FROM_UNICODE, UG(from_error_mode));
+ zend_set_converter_error_mode(*converter, ZEND_TO_UNICODE, UG(to_error_mode));
+ zend_set_converter_subst_char(*converter, UG(from_subst_char));
+ }
+
+ return SUCCESS;
+}
+#endif /* ISO8859 */
+
/* {{{ PHP_INI
*/
PHP_INI_BEGIN()
-STD_PHP_INI_ENTRY_EX("sqlite.assoc_case", "0", PHP_INI_ALL, OnUpdateLong, assoc_case, zend_sqlite_globals, sqlite_globals, display_link_numbers)
+ STD_PHP_INI_ENTRY_EX("sqlite.assoc_case", "0", PHP_INI_ALL, OnUpdateLong, assoc_case, zend_sqlite_globals, sqlite_globals, display_link_numbers)
+#ifdef SQLITE_ISO8859
+ STD_PHP_INI_ENTRY("sqlite.iso8859.locale", "1", PHP_INI_ALL, OnUpdateEncodingISO8859, iso8859_conv, zend_sqlite_globals, sqlite_globals)
+#endif
PHP_INI_END()
/* }}} */
for (i = 0; i < argc-1; i++) {
zargs[i] = emalloc(sizeof(zval *));
MAKE_STD_ZVAL(*zargs[i]);
- ZVAL_STRING(*zargs[i], (char*)argv[i+1], 1);
+ ZVAL_U_STRING(SQLITE2_CONV, *zargs[i], (char*)argv[i+1], ZSTR_DUPLICATE);
}
}
sqlite_set_result_string(func, NULL, 0);
} else {
switch (Z_TYPE_P(retval)) {
+ case IS_UNICODE:
+ {
+ char *str;
+ int str_len;
+
+ if (SUCCESS == zend_unicode_to_string(SQLITE2_CONV, &str, &str_len, Z_USTRVAL_P(retval), Z_USTRLEN_P(retval) TSRMLS_CC)) {
+ sqlite_set_result_string(func, str, str_len);
+ efree(str);
+ } else {
+ /* zuts raised an error for us */
+ sqlite_set_result_string(func, "*unicode conversion error*", sizeof("*unicode conversion error*") - 1);
+ }
+ break;
+ }
case IS_STRING:
sqlite_set_result_string(func, Z_STRVAL_P(retval), Z_STRLEN_P(retval));
break;
if (argv[i] == NULL) {
ZVAL_NULL(*zargs[i]);
} else {
- ZVAL_STRING(*zargs[i], (char*)argv[i], 1);
+ ZVAL_U_STRING(SQLITE2_CONV, *zargs[i], (char*)argv[i], ZSTR_DUPLICATE);
}
}
}
sqlite_set_result_string(func, NULL, 0);
} else {
switch (Z_TYPE_P(retval)) {
+ case IS_UNICODE:
+ {
+ char *str;
+ int str_len;
+
+ if (SUCCESS == zend_unicode_to_string(SQLITE2_CONV, &str, &str_len, Z_USTRVAL_P(retval), Z_USTRLEN_P(retval) TSRMLS_CC)) {
+ sqlite_set_result_string(func, str, str_len);
+ efree(str);
+ } else {
+ /* zuts raised an error for us */
+ sqlite_set_result_string(func, "*unicode conversion error*", sizeof("*unicode conversion error*") - 1);
+ }
+ break;
+ }
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));
if (argv[i] == NULL) {
ZVAL_NULL(*zargs[i+1]);
} else {
- ZVAL_STRING(*zargs[i+1], (char*)argv[i], 1);
+ ZVAL_U_STRING(SQLITE2_CONV, *zargs[i+1], (char*)argv[i], ZSTR_DUPLICATE);
}
}
sqlite_set_result_string(func, NULL, 0);
} else {
switch (Z_TYPE_P(retval)) {
+ case IS_UNICODE:
+ {
+ char *str;
+ int str_len;
+
+ if (SUCCESS == zend_unicode_to_string(SQLITE2_CONV, &str, &str_len, Z_USTRVAL_P(retval), Z_USTRLEN_P(retval) TSRMLS_CC)) {
+ sqlite_set_result_string(func, str, str_len);
+ efree(str);
+ } else {
+ /* zuts raised an error for us */
+ sqlite_set_result_string(func, "*unicode conversion error*", sizeof("*unicode conversion error*") - 1);
+ }
+ break;
+ }
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));
static PHP_GINIT_FUNCTION(sqlite)
{
sqlite_globals->assoc_case = 0;
+#ifdef SQLITE_ISO8859
+ sqlite_globals->iso8859_conv = 0;
+#endif
}
PHP_MINIT_FUNCTION(sqlite)
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
+ ZVAL_U_STRING(SQLITE2_CONV, errmsg, errtext, ZSTR_DUPLICATE);
}
sqlite_freemem(errtext);
return db;
}
-/* {{{ proto resource sqlite_popen(string filename [, int mode [, string &error_message]])
+/* {{{ proto resource sqlite_popen(string filename [, int mode [, string &error_message]]) U
Opens a persistent handle to a SQLite database. Will create the database if it does not exist. */
PHP_FUNCTION(sqlite_popen)
{
+ zval **ppfilename;
long mode = 0666;
char *filename, *fullpath, *hashkey;
int filename_len, hashkeylen;
struct php_sqlite_db *db = NULL;
zend_rsrc_list_entry *le;
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
- &filename, &filename_len, &mode, &errmsg)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lz/", &ppfilename, &mode, &errmsg) ||
+ FAILURE == php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, FG(default_context))) {
return;
}
if (errmsg) {
}
/* }}} */
-/* {{{ proto resource sqlite_open(string filename [, int mode [, string &error_message]])
+/* {{{ proto resource sqlite_open(string filename [, int mode [, string &error_message]]) U
Opens a SQLite database. Will create the database if it does not exist. */
PHP_FUNCTION(sqlite_open)
{
+ zval **ppfilename;
long mode = 0666;
char *filename, *fullpath = NULL;
int filename_len;
zval *object = getThis();
php_set_error_handling(object ? EH_THROW : EH_NORMAL, sqlite_ce_exception TSRMLS_CC);
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/",
- &filename, &filename_len, &mode, &errmsg)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lz/", &ppfilename, &mode, &errmsg) ||
+ FAILURE == php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, FG(default_context))) {
php_std_error_handling();
return;
}
}
/* }}} */
-/* {{{ proto object sqlite_factory(string filename [, int mode [, string &error_message]])
+/* {{{ proto object sqlite_factory(string filename [, int mode [, string &error_message]]) U
Opens a SQLite database and creates an object for it. Will create the database if it does not exist. */
PHP_FUNCTION(sqlite_factory)
{
+ zval **ppfilename;
long mode = 0666;
char *filename, *fullpath = NULL;
int 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)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|lz/", &ppfilename, &mode, &errmsg) ||
+ FAILURE == php_stream_path_param_encode(ppfilename, &filename, &filename_len, REPORT_ERRORS, FG(default_context))) {
php_std_error_handling();
RETURN_NULL();
}
}
/* }}} */
-/* {{{ proto void sqlite_busy_timeout(resource db, int ms)
+/* {{{ proto void sqlite_busy_timeout(resource db, int ms) U
Set busy timeout duration. If ms <= 0, all busy handlers are disabled. */
PHP_FUNCTION(sqlite_busy_timeout)
{
}
/* }}} */
-/* {{{ proto void sqlite_close(resource db)
+/* {{{ proto void sqlite_close(resource db) U
Closes an open sqlite database. */
PHP_FUNCTION(sqlite_close)
{
/* first row - lets copy the column names */
rres->col_names = safe_emalloc(rres->ncolumns, sizeof(char *), 0);
for (i = 0; i < rres->ncolumns; i++) {
+#ifdef SQLITE_UTF8
+ UChar *ucolname;
+ int ucolname_len;
+
+ if (SUCCESS == zend_string_to_unicode(SQLITE2_CONV, &ucolname, &ucolname_len, (char*)colnames[i], strlen((char*)colnames[i]) TSRMLS_CC)) {
+ char *scolname;
+ int scolname_len;
+
+ /* s->u was successful */
+ if (SQLITE_G(assoc_case) == 1) {
+ UChar *tmp;
+ int tmp_len = ucolname_len;
+
+ if ((tmp = php_u_strtoupper(ucolname, &tmp_len, UG(default_locale)))) {
+ efree(ucolname);
+ ucolname = tmp;
+ ucolname_len = tmp_len;
+ } else {
+ /* Case folding failed */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to translate column '%s' to uppercase", (char*)colnames[i]);
+ efree(ucolname);
+ ucolname = NULL;
+ }
+ } else if (SQLITE_G(assoc_case) == 2) {
+ UChar *tmp;
+ int tmp_len = ucolname_len;
+
+ if ((tmp = php_u_strtolower(ucolname, &tmp_len, UG(default_locale)))) {
+ efree(ucolname);
+ ucolname = tmp;
+ ucolname_len = tmp_len;
+ } else {
+ /* Case folding failed */
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to translate column '%s' to uppercase", (char*)colnames[i]);
+ efree(ucolname);
+ ucolname = NULL;
+ }
+ }
+
+ /* Return the ustr to localized format */
+ if (ucolname &&
+ SUCCESS == zend_unicode_to_string(SQLITE2_CONV, &scolname, &scolname_len, ucolname, ucolname_len TSRMLS_CC)) {
+ rres->col_names[i] = scolname;
+ efree(ucolname);
+ continue;
+ }
+
+ if (ucolname) {
+ /* s->u->case worked, but final u->s failed */
+ efree(ucolname);
+ }
+ }
+ /* Some UTF8 step failed, fallback on plain old ASCII case folding */
+#endif
rres->col_names[i] = estrdup((char*)colnames[i]);
if (SQLITE_G(assoc_case) == 1) {
if (ret != SQLITE_OK) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
+ ZVAL_U_STRING(SQLITE2_CONV, errmsg, errtext, ZSTR_DUPLICATE);
}
sqlite_freemem(errtext);
goto terminate;
}
/* }}} */
-/* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type [, string &error_message]])
+/* {{{ proto resource sqlite_unbuffered_query(string query, resource db [ , int result_type [, string &error_message]]) U
Executes a query that does not prefetch and buffer all data. */
PHP_FUNCTION(sqlite_unbuffered_query)
{
zval *object = getThis();
if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&|lz/", &sql, &sql_len, SQLITE2_CONV, &mode, &errmsg)) {
return;
}
DB_FROM_OBJECT(db, object);
} else {
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
+ ZEND_NUM_ARGS() TSRMLS_CC, "s&r|lz/", &sql, &sql_len, SQLITE2_CONV, &zdb, &mode, &errmsg) &&
+ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs&|lz/", &zdb, &sql, &sql_len, SQLITE2_CONV, &mode, &errmsg)) {
return;
}
DB_FROM_ZVAL(db, &zdb);
if (db->last_err_code != SQLITE_OK) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
+ ZVAL_U_STRING(SQLITE2_CONV, errmsg, errtext, ZSTR_DUPLICATE);
}
sqlite_freemem(errtext);
}
}
/* }}} */
-/* {{{ proto resource sqlite_fetch_column_types(string table_name, resource db [, int result_type])
+/* {{{ proto resource sqlite_fetch_column_types(string table_name, resource db [, int result_type]) U
Return an array of column types from a particular table. */
PHP_FUNCTION(sqlite_fetch_column_types)
{
long result_type = PHPSQLITE_ASSOC;
if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &tbl, &tbl_len, &result_type)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&|l", &tbl, &tbl_len, SQLITE2_CONV, &result_type)) {
return;
}
DB_FROM_OBJECT(db, object);
} else {
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|l", &tbl, &tbl_len, &zdb, &result_type) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|l", &zdb, &tbl, &tbl_len, &result_type)) {
+ ZEND_NUM_ARGS() TSRMLS_CC, "s&r|l", &tbl, &tbl_len, SQLITE2_CONV, &zdb, &result_type) &&
+ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs&|l", &zdb, &tbl, &tbl_len, SQLITE2_CONV, &result_type)) {
return;
}
DB_FROM_ZVAL(db, &zdb);
array_init(return_value);
for (i = 0; i < ncols; i++) {
- char *colname = estrdup((char *)colnames[i]);
+ zend_uchar colname_type;
+ zstr colname;
+ int colname_len;
+ zval *coltype;
+
+ MAKE_STD_ZVAL(coltype);
+ ZVAL_U_STRING(SQLITE2_CONV, coltype, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", ZSTR_DUPLICATE);
+ coltype->refcount = 0;
+
+ if (result_type == PHPSQLITE_NUM) {
+ ZVAL_ADDREF(coltype);
+ add_index_zval(return_value, i, coltype);
+ }
+
+ if (result_type == PHPSQLITE_ASSOC) {
+ if (UG(unicode) &&
+ SUCCESS == zend_string_to_unicode(SQLITE2_CONV, &(colname.u), &colname_len, (char*)colnames[i], strlen((char*)colnames[i]) TSRMLS_CC)) {
+ colname_type = IS_UNICODE;
+ if (SQLITE_G(assoc_case) == 1) {
+ UChar *tmp;
+ int tmp_len = colname_len;
+
+ if ((tmp = php_u_strtoupper(colname.u, &tmp_len, UG(default_locale)))) {
+ efree(colname.u);
+ colname.u = tmp;
+ colname_len = tmp_len;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to translate column '%s' to uppercase", (char*)colnames[i]);
+ }
+ } else if (SQLITE_G(assoc_case) == 2) {
+ UChar *tmp;
+ int tmp_len = colname_len;
+
+ if ((tmp = php_u_strtolower(colname.u, &tmp_len, UG(default_locale)))) {
+ efree(colname.u);
+ colname.u = tmp;
+ colname_len = tmp_len;
+ } else {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to translate column '%s' to lowercase", (char*)colnames[i]);
+ }
+ }
+ } else {
+ colname_type = IS_STRING;
+ colname_len = strlen(colnames[i]);
+ colname.s = estrndup((char *)colnames[i], colname_len);
+
+ if (SQLITE_G(assoc_case) == 1) {
+ php_sqlite_strtoupper(colname.s);
+ } else if (SQLITE_G(assoc_case) == 2) {
+ php_sqlite_strtolower(colname.s);
+ }
+ }
- if (SQLITE_G(assoc_case) == 1) {
- php_sqlite_strtoupper(colname);
- } else if (SQLITE_G(assoc_case) == 2) {
- php_sqlite_strtolower(colname);
+ ZVAL_ADDREF(coltype);
+ add_u_assoc_zval_ex(return_value, colname_type, colname, colname_len + 1, coltype);
+ efree(colname.v);
}
- if (UG(unicode)) {
- char *tmp = colnames[ncols + i] ? (char *)colnames[ncols + i] : "";
- UErrorCode status = U_ZERO_ERROR;
- UChar *u_str;
- int u_len;
-
- zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u_str, &u_len, tmp, strlen(tmp), &status);
- if (result_type == PHPSQLITE_ASSOC) {
- add_rt_assoc_unicode(return_value, colname, u_str, 1);
- }
- if (result_type == PHPSQLITE_NUM) {
- add_index_unicode(return_value, i, u_str, 1);
- }
- efree(u_str);
- } else {
- if (result_type == PHPSQLITE_ASSOC) {
- add_assoc_string(return_value, colname, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
- }
- if (result_type == PHPSQLITE_NUM) {
- add_index_string(return_value, i, colnames[ncols + i] ? (char *)colnames[ncols + i] : "", 1);
- }
+ if (coltype->refcount <= 0) {
+ /* Shouldn't happen (and probably can't) */
+ coltype->refcount = 1;
+ zval_ptr_dtor(&coltype);
}
- efree(colname);
}
+
if (res.vm) {
sqlite_finalize(res.vm, NULL);
}
}
/* }}} */
-/* {{{ proto resource sqlite_query(string query, resource db [, int result_type [, string &error_message]])
+/* {{{ proto resource sqlite_query(string query, resource db [, int result_type [, string &error_message]]) U
Executes a query against a given database and returns a result handle. */
PHP_FUNCTION(sqlite_query)
{
zval *object = getThis();
if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz/", &sql, &sql_len, &mode, &errmsg)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&|lz/", &sql, &sql_len, SQLITE2_CONV, &mode, &errmsg)) {
return;
}
DB_FROM_OBJECT(db, object);
} else {
if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr|lz/", &sql, &sql_len, &zdb, &mode, &errmsg) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|lz/", &zdb, &sql, &sql_len, &mode, &errmsg)) {
+ ZEND_NUM_ARGS() TSRMLS_CC, "s&r|lz/", &sql, &sql_len, SQLITE2_CONV, &zdb, &mode, &errmsg) &&
+ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs&|lz/", &zdb, &sql, &sql_len, SQLITE2_CONV, &mode, &errmsg)) {
return;
}
DB_FROM_ZVAL(db, &zdb);
if (db->last_err_code != SQLITE_OK) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
+ ZVAL_U_STRING(SQLITE2_CONV, errmsg, errtext, ZSTR_DUPLICATE);
}
sqlite_freemem(errtext);
}
}
/* }}} */
-/* {{{ proto boolean sqlite_exec(string query, resource db[, string &error_message])
+/* {{{ proto boolean sqlite_exec(string query, resource db[, string &error_message]) U
Executes a result-less query against a given database */
PHP_FUNCTION(sqlite_exec)
{
zval *object = getThis();
if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|z/", &sql, &sql_len, &errmsg)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&|z/", &sql, &sql_len, SQLITE2_CONV, &errmsg)) {
return;
}
DB_FROM_OBJECT(db, object);
} else {
if(FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
- ZEND_NUM_ARGS() TSRMLS_CC, "sr", &sql, &sql_len, &zdb) &&
- FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs|z/", &zdb, &sql, &sql_len, &errmsg)) {
+ ZEND_NUM_ARGS() TSRMLS_CC, "s&r", &sql, &sql_len, SQLITE2_CONV, &zdb) &&
+ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs&|z/", &zdb, &sql, &sql_len, SQLITE2_CONV, &errmsg)) {
return;
}
DB_FROM_ZVAL(db, &zdb);
if (db->last_err_code != SQLITE_OK) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
if (errmsg) {
- ZVAL_STRING(errmsg, errtext, 1);
+ ZVAL_U_STRING(SQLITE2_CONV, errmsg, errtext, 1);
}
sqlite_freemem(errtext);
RETURN_FALSE;
rowdata[j] = NULL;
}
} else {
- if (UG(unicode)) {
- UErrorCode status = U_ZERO_ERROR;
- UChar *u_str;
- int u_len;
-
- zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u_str, &u_len, (char*)rowdata[j], strlen((char*)rowdata[j]), &status);
- ZVAL_UNICODEL(decoded, u_str, u_len, 0);
- if (!buffered) {
- efree((char *)rowdata[j]);
- }
- } else {
- ZVAL_STRING(decoded, (char*)rowdata[j], buffered);
- }
+ ZVAL_U_STRING(SQLITE2_CONV, decoded, (char*)rowdata[j], buffered ? ZSTR_DUPLICATE : ZSTR_AUTOFREE);
if (!buffered) {
rowdata[j] = NULL;
}
}
+ decoded->refcount = 0;
if (mode & PHPSQLITE_NUM) {
- if (mode & PHPSQLITE_ASSOC) {
- add_index_zval(return_value, j, decoded);
- ZVAL_ADDREF(decoded);
- add_rt_assoc_zval(return_value, (char*)colnames[j], decoded);
+ ZVAL_ADDREF(decoded);
+ add_index_zval(return_value, j, decoded);
+ }
+ if ((mode & PHPSQLITE_ASSOC) || (!(mode & PHPSQLITE_NUM))) {
+ UChar *colname;
+ int colname_len;
+
+ ZVAL_ADDREF(decoded);
+
+ if (UG(unicode) &&
+ SUCCESS == zend_string_to_unicode(SQLITE2_CONV, &colname, &colname_len, (char*)colnames[j], strlen((char*)colnames[j]) TSRMLS_CC)) {
+ add_u_assoc_zval_ex(return_value, IS_UNICODE, ZSTR(colname), colname_len + 1, decoded);
+ efree(colname);
} else {
- add_next_index_zval(return_value, decoded);
+ add_assoc_zval(return_value, (char*)colnames[j], decoded);
}
- } else {
- add_rt_assoc_zval(return_value, (char*)colnames[j], decoded);
}
}
efree((char*)rowdata[j]);
rowdata[j] = NULL;
}
- } else if (UG(unicode)) {
- UErrorCode status = U_ZERO_ERROR;
- UChar *u_str;
- int u_len;
-
- zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u_str, &u_len, (char*)rowdata[j], strlen((char*)rowdata[j]), &status);
- RETVAL_UNICODEL(u_str, u_len, 0);
- if (!res->buffered) {
- efree((char *)rowdata[j]);
- rowdata[j] = NULL;
- }
} else {
- RETVAL_STRING((char*)rowdata[j], res->buffered);
+ RETVAL_U_STRING(SQLITE2_CONV, (char*)rowdata[j], res->buffered ? ZSTR_DUPLICATE : ZSTR_AUTOFREE);
if (!res->buffered) {
rowdata[j] = NULL;
}
}
/* }}} */
-/* {{{ proto array sqlite_fetch_all(resource result [, int result_type [, bool decode_binary]])
+/* {{{ proto array sqlite_fetch_all(resource result [, int result_type [, bool decode_binary]]) U
Fetches all rows from a result set as an array of arrays. */
PHP_FUNCTION(sqlite_fetch_all)
{
}
/* }}} */
-/* {{{ proto array sqlite_fetch_array(resource result [, int result_type [, bool decode_binary]])
+/* {{{ proto array sqlite_fetch_array(resource result [, int result_type [, bool decode_binary]]) U
Fetches the next row from a result set as an array. */
PHP_FUNCTION(sqlite_fetch_array)
{
}
/* }}} */
-/* {{{ proto object sqlite_fetch_object(resource result [, string class_name [, NULL|array ctor_params [, bool decode_binary]]])
+/* {{{ proto object sqlite_fetch_object(resource result [, string class_name [, NULL|array ctor_params [, bool decode_binary]]]) U
Fetches the next row from a result set as an object. */
/* note that you can do array(&$val) for param ctor_params */
PHP_FUNCTION(sqlite_fetch_object)
}
/* }}} */
-/* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type [, bool decode_binary]])
+/* {{{ proto array sqlite_array_query(resource db, string query [ , int result_type [, bool decode_binary]]) U
Executes a query against a given database and returns an array of arrays. */
PHP_FUNCTION(sqlite_array_query)
{
zval *object = getThis();
if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lb", &sql, &sql_len, &mode, &decode_binary)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&|lb", &sql, &sql_len, SQLITE2_CONV, &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)) {
+ ZEND_NUM_ARGS() TSRMLS_CC, "s&r|lb", &sql, &sql_len, SQLITE2_CONV, &zdb, &mode, &decode_binary) &&
+ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs&|lb", &zdb, &sql, &sql_len, SQLITE2_CONV, &mode, &decode_binary)) {
return;
}
DB_FROM_ZVAL(db, &zdb);
free_decoded = 1;
} else if (rowdata[0]) {
decoded_len = strlen((char*)rowdata[0]);
- if (res->buffered) {
- if (UG(unicode)) {
- decoded = (char*)rowdata[0];
- } else {
- decoded = estrndup((char*)rowdata[0], decoded_len);
- }
- } else {
+ decoded = (char*)rowdata[0];
+ if (!res->buffered) {
decoded = (char*)rowdata[0];
rowdata[0] = NULL;
free_decoded = 1;
if (decoded == NULL) {
RETURN_NULL();
- } else if (UG(unicode)) {
- UErrorCode status = U_ZERO_ERROR;
- UChar *u_str;
- int u_len;
-
- zend_string_to_unicode_ex(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &u_str, &u_len, decoded, decoded_len, &status);
- if (free_decoded) {
- efree(decoded);
- }
- RETURN_UNICODEL(u_str, u_len, 0);
} else {
- RETURN_STRINGL(decoded, decoded_len, 0);
+ RETURN_U_STRINGL(SQLITE2_CONV, decoded, decoded_len, free_decoded ? ZSTR_AUTOFREE : ZSTR_DUPLICATE);
}
}
/* }}} */
-/* {{{ proto array sqlite_single_query(resource db, string query [, bool first_row_only [, bool decode_binary]])
+/* {{{ proto array sqlite_single_query(resource db, string query [, bool first_row_only [, bool decode_binary]]) U
Executes a query and returns either an array for one single column or the value of the first row. */
PHP_FUNCTION(sqlite_single_query)
{
zval *object = getThis();
if (object) {
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|bb", &sql, &sql_len, &srow, &decode_binary)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&|bb", &sql, &sql_len, SQLITE2_CONV, &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)) {
+ ZEND_NUM_ARGS() TSRMLS_CC, "s&r|bb", &sql, &sql_len, SQLITE2_CONV, &zdb, &srow, &decode_binary) &&
+ FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rs&|bb", &zdb, &sql, &sql_len, SQLITE2_CONV, &srow, &decode_binary)) {
return;
}
DB_FROM_ZVAL(db, &zdb);
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 {
/* }}} */
-/* {{{ proto string sqlite_fetch_single(resource result [, bool decode_binary])
+/* {{{ proto string sqlite_fetch_single(resource result [, bool decode_binary]) U
Fetches the first column of a result set as a string. */
PHP_FUNCTION(sqlite_fetch_single)
{
}
/* }}} */
-/* {{{ proto array sqlite_current(resource result [, int result_type [, bool decode_binary]])
+/* {{{ proto array sqlite_current(resource result [, int result_type [, bool decode_binary]]) U
Fetches the current row from a result set as an array. */
PHP_FUNCTION(sqlite_current)
{
}
/* }}} */
-/* {{{ proto mixed sqlite_column(resource result, mixed index_or_name [, bool decode_binary])
+/* {{{ proto mixed sqlite_column(resource result, mixed index_or_name [, bool decode_binary]) U
Fetches a column from the current row of a result set. */
PHP_FUNCTION(sqlite_column)
{
}
/* }}} */
-/* {{{ proto string sqlite_libversion()
+/* {{{ proto string sqlite_libversion() U
Returns the version of the linked SQLite library. */
PHP_FUNCTION(sqlite_libversion)
{
if (ZEND_NUM_ARGS() != 0) {
WRONG_PARAM_COUNT;
}
- RETURN_ASCII_STRING((char*)sqlite_libversion(), 1);
+ RETURN_ASCII_STRING((char*)sqlite_libversion(), ZSTR_DUPLICATE);
}
/* }}} */
-/* {{{ proto string sqlite_libencoding()
+/* {{{ proto string sqlite_libencoding() U
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_ASCII_STRING((char*)sqlite_libencoding(), 1);
+ RETURN_ASCII_STRING((char*)sqlite_libencoding(), ZSTR_DUPLICATE);
}
/* }}} */
-/* {{{ proto int sqlite_changes(resource db)
+/* {{{ proto int sqlite_changes(resource db) U
Returns the number of rows that were changed by the most recent SQL statement. */
PHP_FUNCTION(sqlite_changes)
{
}
/* }}} */
-/* {{{ proto int sqlite_last_insert_rowid(resource db)
+/* {{{ proto int sqlite_last_insert_rowid(resource db) U
Returns the rowid of the most recently inserted row. */
PHP_FUNCTION(sqlite_last_insert_rowid)
{
}
} /* }}} */
-/* {{{ proto int sqlite_num_rows(resource result)
+/* {{{ proto int sqlite_num_rows(resource result) U
Returns the number of rows in a buffered result set. */
PHP_FUNCTION(sqlite_num_rows)
{
}
/* }}} */
-/* {{{ proto bool sqlite_valid(resource result)
+/* {{{ proto bool sqlite_valid(resource result) U
Returns whether more rows are available. */
PHP_FUNCTION(sqlite_valid)
{
}
/* }}} */
-/* {{{ proto bool sqlite_has_prev(resource result)
+/* {{{ proto bool sqlite_has_prev(resource result) U
* Returns whether a previous row is available. */
PHP_FUNCTION(sqlite_has_prev)
{
}
/* }}} */
-/* {{{ proto int sqlite_num_fields(resource result)
+/* {{{ proto int sqlite_num_fields(resource result) U
Returns the number of fields in a result set. */
PHP_FUNCTION(sqlite_num_fields)
{
}
/* }}} */
-/* {{{ proto string sqlite_field_name(resource result, int field_index)
+/* {{{ proto string sqlite_field_name(resource result, int field_index) U
Returns the name of a particular field of a result set. */
PHP_FUNCTION(sqlite_field_name)
{
php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %ld out of range", field);
RETURN_FALSE;
}
-
- RETURN_U_STRING(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), res->col_names[field], 1);
+ RETURN_U_STRING(SQLITE2_CONV, res->col_names[field], ZSTR_DUPLICATE);
}
/* }}} */
-/* {{{ proto bool sqlite_seek(resource result, int row)
+/* {{{ proto bool sqlite_seek(resource result, int row) U
Seek to a particular row number of a buffered result set. */
PHP_FUNCTION(sqlite_seek)
{
}
/* }}} */
-/* {{{ proto bool sqlite_rewind(resource result)
+/* {{{ proto bool sqlite_rewind(resource result) U
Seek to the first row number of a buffered result set. */
PHP_FUNCTION(sqlite_rewind)
{
}
/* }}} */
-/* {{{ proto bool sqlite_next(resource result)
+/* {{{ proto bool sqlite_next(resource result) U
Seek to the next row number of a result set. */
PHP_FUNCTION(sqlite_next)
{
}
/* }}} */
-/* {{{ proto int sqlite_key(resource result)
+/* {{{ proto int sqlite_key(resource result) U
Return the current row index of a buffered result. */
PHP_FUNCTION(sqlite_key)
{
}
/* }}} */
-/* {{{ proto bool sqlite_prev(resource result)
+/* {{{ proto bool sqlite_prev(resource result) U
* Seek to the previous row number of a result set. */
PHP_FUNCTION(sqlite_prev)
{
}
/* }}} */
-/* {{{ proto string sqlite_escape_string(string item)
+/* {{{ proto string sqlite_escape_string(string item) U
Escapes a string for use as a query parameter. */
PHP_FUNCTION(sqlite_escape_string)
{
int stringlen;
char *ret;
- if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &string, &stringlen)) {
+ if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s&", &string, &stringlen, SQLITE2_CONV)) {
return;
}
ret[0] = '\x01';
enclen = php_sqlite_encode_binary(string, stringlen, ret+1);
RETVAL_STRINGL(ret, enclen+1, 0);
-
} else if (stringlen) {
ret = sqlite_mprintf("%q", string);
if (ret) {
- RETVAL_STRING(ret, 1);
+ RETVAL_U_STRING(SQLITE2_CONV, ret, ZSTR_DUPLICATE);
sqlite_freemem(ret);
}
} else {
- RETURN_EMPTY_STRING();
+ RETURN_EMPTY_TEXT();
}
}
/* }}} */
-/* {{{ proto int sqlite_last_error(resource db)
+/* {{{ proto int sqlite_last_error(resource db) U
Returns the error code of the last error for a database. */
PHP_FUNCTION(sqlite_last_error)
{
}
/* }}} */
-/* {{{ proto string sqlite_error_string(int error_code)
+/* {{{ proto string sqlite_error_string(int error_code) U
Returns the textual description of an error code. */
PHP_FUNCTION(sqlite_error_string)
{
msg = sqlite_error_string(code);
if (msg) {
- RETURN_U_STRING(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), (char*)msg, 1);
+ RETURN_U_STRING(SQLITE2_CONV, (char*)msg, ZSTR_DUPLICATE);
} else {
RETURN_NULL();
}
}
-/* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args])
+/* {{{ proto bool sqlite_create_aggregate(resource db, string funcname, mixed step_func, mixed finalize_func[, long num_args]) U
Registers an aggregate function for queries. */
PHP_FUNCTION(sqlite_create_aggregate)
{
}
/* }}} */
-/* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args])
+/* {{{ proto bool sqlite_create_function(resource db, string funcname, mixed callback[, long num_args]) U
Registers a "regular" function for queries. */
PHP_FUNCTION(sqlite_create_function)
{
}
/* }}} */
-/* {{{ proto string sqlite_udf_encode_binary(string data)
+/* {{{ proto string sqlite_udf_encode_binary(string data) U
Apply binary encoding (if required) to a string to return from an UDF. */
PHP_FUNCTION(sqlite_udf_encode_binary)
{
char *data = NULL;
int datalen;
+ zend_uchar encode = 0;
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)) {
+ if (!datalen) {
+ RETURN_EMPTY_STRING();
+ }
+
+ if (data[0] == '\x01' || memchr(data, 0, datalen) != NULL) {
+ encode = 1;
+#ifdef SQLITE_UTF8
+ } else {
+ /* UTF8 doesn't like non-ascii which isn't utf8 encoded */
+ unsigned char *udata = (unsigned char*)data;
+ int i;
+
+ for(i = 0; i < datalen; i++) {
+ if (udata[i] > 0x7F) {
+ encode = 1;
+ break;
+ }
+ }
+#endif
+ }
+
+ if (encode) {
/* binary string */
int enclen;
char *ret;
}
/* }}} */
-/* {{{ proto string sqlite_udf_decode_binary(string data)
+/* {{{ proto string sqlite_udf_decode_binary(string data) U
Decode binary encoding on a string parameter passed to an UDF. */
PHP_FUNCTION(sqlite_udf_decode_binary)
{
if (data == NULL) {
RETURN_NULL();
}
- if (datalen && data[0] == '\x01') {
+
+ if (datalen <= 0) {
+ RETURN_EMPTY_STRING();
+ }
+
+ if (data[0] == '\x01') {
/* encoded string */
int enclen;
char *ret;