summaryrefslogtreecommitdiff
path: root/ext/sybase_ct
diff options
context:
space:
mode:
authorTimm Friebe <thekid@php.net>2002-11-05 08:29:57 +0000
committerTimm Friebe <thekid@php.net>2002-11-05 08:29:57 +0000
commit514b69824ea60417cc9b324c27e734e4c0240918 (patch)
tree827273425c240e4113aab72893823d32306aee92 /ext/sybase_ct
parentb899f9bf63acfbd3cc65551a97d041f09d4f4d8c (diff)
downloadphp-git-514b69824ea60417cc9b324c27e734e4c0240918.tar.gz
@- Implemented features/changes requested in Bug #16960 (Timm):
@ . Added a new function sybase_unbuffered_query() @ . Added a new function sybase_fetch_assoc() @ . Added sybase_set_message_handler() which enables users to handle @ server messages in a callback function @ . Added an ini entry for deadlock retries - retrying deadlocks @ can cause transaction state to break (sybct.deadlock_retry_count, @ defaults to -1 "forever"). @ . Fixed sybase_fetch_object() not to return objects with numeric @ members @ . Fixed issues with identical fieldnames @ . Made sybase_fetch_*() functions return correct datatypes @ . Made phpinfo() section more verbose @ . Made sybase_query() error messages more verbose
Diffstat (limited to 'ext/sybase_ct')
-rw-r--r--ext/sybase_ct/php_sybase_ct.c741
-rw-r--r--ext/sybase_ct/php_sybase_ct.h23
2 files changed, 548 insertions, 216 deletions
diff --git a/ext/sybase_ct/php_sybase_ct.c b/ext/sybase_ct/php_sybase_ct.c
index 75f5d3f28f..e61d2cda3a 100644
--- a/ext/sybase_ct/php_sybase_ct.c
+++ b/ext/sybase_ct/php_sybase_ct.c
@@ -14,6 +14,7 @@
+----------------------------------------------------------------------+
| Authors: Zeev Suraski <zeev@zend.com> |
| Tom May <tom@go2net.com> |
+ | Timm Friebe <php_sybase_ct@thekid.de> |
+----------------------------------------------------------------------+
*/
@@ -42,32 +43,38 @@ function_entry sybase_functions[] = {
PHP_FE(sybase_close, NULL)
PHP_FE(sybase_select_db, NULL)
PHP_FE(sybase_query, NULL)
+ PHP_FE(sybase_unbuffered_query, NULL)
PHP_FE(sybase_free_result, NULL)
PHP_FE(sybase_get_last_message, NULL)
PHP_FE(sybase_num_rows, NULL)
PHP_FE(sybase_num_fields, NULL)
PHP_FE(sybase_fetch_row, NULL)
PHP_FE(sybase_fetch_array, NULL)
+ PHP_FE(sybase_fetch_assoc, NULL)
PHP_FE(sybase_fetch_object, NULL)
PHP_FE(sybase_data_seek, NULL)
PHP_FE(sybase_fetch_field, NULL)
- PHP_FE(sybase_field_seek, NULL)
+ PHP_FE(sybase_field_seek, NULL)
PHP_FE(sybase_result, NULL)
PHP_FE(sybase_affected_rows, NULL)
PHP_FE(sybase_min_client_severity, NULL)
PHP_FE(sybase_min_server_severity, NULL)
+ PHP_FE(sybase_set_message_handler, NULL)
+ PHP_FE(sybase_deadlock_retry_count, NULL)
PHP_FALIAS(mssql_connect, sybase_connect, NULL)
PHP_FALIAS(mssql_pconnect, sybase_pconnect, NULL)
PHP_FALIAS(mssql_close, sybase_close, NULL)
PHP_FALIAS(mssql_select_db, sybase_select_db, NULL)
PHP_FALIAS(mssql_query, sybase_query, NULL)
+ PHP_FALIAS(mssql_unbuffered_query, sybase_unbuffered_query,NULL)
PHP_FALIAS(mssql_free_result, sybase_free_result, NULL)
PHP_FALIAS(mssql_get_last_message, sybase_get_last_message,NULL)
PHP_FALIAS(mssql_num_rows, sybase_num_rows, NULL)
PHP_FALIAS(mssql_num_fields, sybase_num_fields, NULL)
PHP_FALIAS(mssql_fetch_row, sybase_fetch_row, NULL)
PHP_FALIAS(mssql_fetch_array, sybase_fetch_array, NULL)
+ PHP_FALIAS(mssql_fetch_assoc, sybase_fetch_assoc, NULL)
PHP_FALIAS(mssql_fetch_object, sybase_fetch_object, NULL)
PHP_FALIAS(mssql_data_seek, sybase_data_seek, NULL)
PHP_FALIAS(mssql_fetch_field, sybase_fetch_field, NULL)
@@ -76,6 +83,8 @@ function_entry sybase_functions[] = {
PHP_FALIAS(mssql_affected_rows, sybase_affected_rows, NULL)
PHP_FALIAS(mssql_min_client_severity, sybase_min_client_severity, NULL)
PHP_FALIAS(mssql_min_server_severity, sybase_min_server_severity, NULL)
+ PHP_FALIAS(mssql_set_message_handler, sybase_set_message_handler, NULL)
+ PHP_FALIAS(mssql_deadlock_retry_count, sybase_deadlock_retry_count, NULL)
{NULL, NULL, NULL}
};
@@ -114,9 +123,9 @@ static void _free_sybase_result(sybase_result *result)
int i, j;
if (result->data) {
- for (i=0; i<result->num_rows; i++) {
+ for (i=0; i<(result->store ? result->num_rows : 0); i++) {
for (j=0; j<result->num_fields; j++) {
- pval_destructor(&result->data[i][j]);
+ zval_dtor(&result->data[i][j]);
}
efree(result->data[i]);
}
@@ -221,17 +230,47 @@ static CS_RETCODE CS_PUBLIC _client_message_handler(CS_CONTEXT *context, CS_CONN
return CS_FAIL;
}
- return CS_SUCCEED;
+ return CS_SUCCEED;
}
static CS_RETCODE CS_PUBLIC _server_message_handler(CS_CONTEXT *context, CS_CONNECTION *connection, CS_SERVERMSG *srvmsg)
{
+ zval *retval = NULL;
+ zval severity, msgnumber, state, line, text;
+ zval *ptrs[5]= {&msgnumber, &severity, &state, &line, &text};
+ zval **args[5]= {&ptrs[0], &ptrs[1], &ptrs[2], &ptrs[3], &ptrs[4]};
+ int handled= 0;
+
TSRMLS_FETCH();
if (srvmsg->severity >= SybCtG(min_server_severity)) {
- php_error(E_WARNING, "Sybase: Server message: %s (severity %d, procedure %s)",
+ if (SybCtG(callback_name) != NULL) {
+ INIT_ZVAL(msgnumber);
+ INIT_ZVAL(severity);
+ INIT_ZVAL(state);
+ INIT_ZVAL(line);
+ INIT_ZVAL(text);
+
+ ZVAL_LONG(&msgnumber, srvmsg->msgnumber);
+ ZVAL_LONG(&severity, srvmsg->severity);
+ ZVAL_LONG(&state, srvmsg->state);
+ ZVAL_LONG(&line, srvmsg->line);
+ ZVAL_STRING(&text, srvmsg->text, 0);
+
+ if (call_user_function_ex(EG(function_table), NULL, SybCtG(callback_name), &retval, 5, args, 0, NULL TSRMLS_CC)== FAILURE) {
+ php_error(E_WARNING, "Sybase: Cannot call the messagehandler %s", Z_STRVAL_P(SybCtG(callback_name)));
+ }
+ if (retval) {
+ handled= ((Z_TYPE_P(retval) != IS_BOOL) || (Z_BVAL_P(retval) != 0));
+ zval_ptr_dtor(&retval);
+ }
+ }
+
+ if (!handled) {
+ php_error(E_WARNING, "Sybase: Server message: %s (severity %d, procedure %s)",
srvmsg->text, srvmsg->severity, ((srvmsg->proclen>0) ? srvmsg->proc : "N/A"));
+ }
}
STR_FREE(SybCtG(server_message));
SybCtG(server_message) = estrdup(srvmsg->text);
@@ -244,14 +283,13 @@ static CS_RETCODE CS_PUBLIC _server_message_handler(CS_CONTEXT *context, CS_CONN
sybase_link *sybase;
if (ct_con_props(connection, CS_GET, CS_USERDATA, &sybase, CS_SIZEOF(sybase), NULL)==CS_SUCCEED) {
- sybase->deadlock = 1;
- }
- else {
+ sybase->deadlock = 1;
+ } else {
/* oh well */
}
}
- return CS_SUCCEED;
+ return CS_SUCCEED;
}
@@ -262,6 +300,7 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("sybct.min_server_severity", "10", PHP_INI_ALL, OnUpdateInt, min_server_severity, zend_sybase_globals, sybase_globals)
STD_PHP_INI_ENTRY("sybct.min_client_severity", "10", PHP_INI_ALL, OnUpdateInt, min_client_severity, zend_sybase_globals, sybase_globals)
STD_PHP_INI_ENTRY("sybct.hostname", NULL, PHP_INI_ALL, OnUpdateString, hostname, zend_sybase_globals, sybase_globals)
+ STD_PHP_INI_ENTRY_EX("sybct.deadlock_retry_count", "-1", PHP_INI_ALL, OnUpdateInt, deadlock_retry_count, zend_sybase_globals, sybase_globals, display_link_numbers)
PHP_INI_END()
@@ -317,13 +356,14 @@ static void php_sybase_init_globals(zend_sybase_globals *sybase_globals)
}
}
sybase_globals->num_persistent=0;
+ sybase_globals->callback_name = NULL;
}
static void php_sybase_destroy_globals(zend_sybase_globals *sybase_globals)
{
- ct_exit(sybase_globals->context, CS_UNUSED);
- cs_ctx_drop(sybase_globals->context);
+ ct_exit(sybase_globals->context, CS_UNUSED);
+ cs_ctx_drop(sybase_globals->context);
}
PHP_MINIT_FUNCTION(sybase)
@@ -366,6 +406,10 @@ PHP_MSHUTDOWN_FUNCTION(sybase)
PHP_RSHUTDOWN_FUNCTION(sybase)
{
efree(SybCtG(appname));
+ if (SybCtG(callback_name)) {
+ zval_dtor(SybCtG(callback_name));
+ SybCtG(callback_name)= NULL;
+ }
STR_FREE(SybCtG(server_message));
return SUCCESS;
}
@@ -397,7 +441,7 @@ static int php_sybase_do_connect_internal(sybase_link *sybase, char *host, char
}
if (appname) {
ct_con_props(sybase->connection, CS_SET, CS_APPNAME, appname, CS_NULLTERM, NULL);
- } else {
+ } else {
ct_con_props(sybase->connection, CS_SET, CS_APPNAME, SybCtG(appname), CS_NULLTERM, NULL);
}
@@ -425,6 +469,7 @@ static int php_sybase_do_connect_internal(sybase_link *sybase, char *host, char
sybase->valid = 1;
sybase->dead = 0;
+ sybase->active_result_index = 0;
/* create the link */
if (ct_connect(sybase->connection, host, CS_NULLTERM)!=CS_SUCCEED) {
@@ -459,7 +504,7 @@ static void php_sybase_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
strcpy(hashed_details, "sybase_____");
break;
case 1: {
- pval *yyhost;
+ zval *yyhost;
if (getParameters(ht, 1, &yyhost)==FAILURE) {
RETURN_FALSE;
@@ -473,7 +518,7 @@ static void php_sybase_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
break;
case 2: {
- pval *yyhost, *yyuser;
+ zval *yyhost, *yyuser;
if (getParameters(ht, 2, &yyhost, &yyuser)==FAILURE) {
RETURN_FALSE;
@@ -489,7 +534,7 @@ static void php_sybase_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
break;
case 3: {
- pval *yyhost, *yyuser, *yypasswd;
+ zval *yyhost, *yyuser, *yypasswd;
if (getParameters(ht, 3, &yyhost, &yyuser, &yypasswd) == FAILURE) {
RETURN_FALSE;
@@ -507,7 +552,7 @@ static void php_sybase_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
break;
case 4: {
- pval *yyhost, *yyuser, *yypasswd, *yycharset;
+ zval *yyhost, *yyuser, *yypasswd, *yycharset;
if (getParameters(ht, 4, &yyhost, &yyuser, &yypasswd, &yycharset) == FAILURE) {
RETURN_FALSE;
@@ -527,7 +572,7 @@ static void php_sybase_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
break;
case 5: {
- pval *yyhost, *yyuser, *yypasswd, *yycharset, *yyappname;
+ zval *yyhost, *yyuser, *yypasswd, *yycharset, *yyappname;
if (getParameters(ht, 5, &yyhost, &yyuser, &yypasswd, &yycharset, &yyappname) == FAILURE) {
RETURN_FALSE;
@@ -733,7 +778,7 @@ PHP_FUNCTION(sybase_pconnect)
Close Sybase connection */
PHP_FUNCTION(sybase_close)
{
- pval *sybase_link_index = 0;
+ zval *sybase_link_index = 0;
int id;
sybase_link *sybase_ptr;
@@ -849,7 +894,7 @@ static int exec_cmd(sybase_link *sybase_ptr, char *cmdbuf)
Select Sybase database */
PHP_FUNCTION(sybase_select_db)
{
- pval *db, *sybase_link_index;
+ zval *db, *sybase_link_index;
int id;
char *cmdbuf;
sybase_link *sybase_ptr;
@@ -890,176 +935,280 @@ PHP_FUNCTION(sybase_select_db)
/* }}} */
+static void php_sybase_finish_results (sybase_result *result)
+{
+ int i;
+ CS_RETCODE retcode;
+ CS_INT restype;
+
+ efree(result->datafmt);
+ efree(result->lengths);
+ efree(result->indicators);
+ efree(result->numerics);
+ efree(result->types);
+ for (i=0; i<result->num_fields; i++) {
+ efree(result->tmp_buffer[i]);
+ }
+ efree(result->tmp_buffer);
+
+ /* The only restype we should get now is CS_CMD_DONE, possibly
+ * followed by a CS_STATUS_RESULT/CS_CMD_SUCCEED/CS_CMD_DONE
+ * sequence if the command was a stored procedure call. But we
+ * still need to read and discard unexpected results. We might
+ * want to return a failure in this case because the application
+ * won't be getting all the results it asked for.
+ */
+ while ((retcode = ct_results(result->sybase_ptr->cmd, &restype))==CS_SUCCEED) {
+ switch ((int) restype) {
+ case CS_CMD_SUCCEED:
+ case CS_CMD_DONE:
+ break;
+
+ case CS_CMD_FAIL:
+ _free_sybase_result(result);
+ result = NULL;
+ break;
+
+ case CS_COMPUTE_RESULT:
+ case CS_CURSOR_RESULT:
+ case CS_PARAM_RESULT:
+ case CS_ROW_RESULT:
+ /* Unexpected results, cancel them. */
+ case CS_STATUS_RESULT:
+ ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_CURRENT);
+ break;
+
+ default:
+ ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL);
+ break;
+ }
+ }
+
+ switch (retcode) {
+ case CS_END_RESULTS:
+ /* Normal. */
+ break;
+
+ case CS_FAIL:
+ /* Hopefully this either cleans up the connection, or the
+ * connection ends up marked dead so it will be reopened
+ * if it is persistent. We may want to do
+ * ct_close(CS_FORCE_CLOSE) if ct_cancel() fails; see the
+ * doc for ct_results()==CS_FAIL.
+ */
+ ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL);
+ /* Don't take chances with the vagaries of ct-lib. Mark it
+ * dead ourselves.
+ */
+ result->sybase_ptr->dead = 1;
+
+ case CS_CANCELED:
+ default:
+ _free_sybase_result(result);
+ result = NULL;
+ break;
+ }
+
+ /* Indicate we have read all rows */
+ result->sybase_ptr->active_result_index= 0;
+}
+
+static int php_sybase_fetch_result_row (sybase_result *result, int numrows)
+{
+ int i, j;
+ CS_INT retcode;
+
+ /* We've already fetched everything */
+ if (result->last_retcode == CS_END_DATA) {
+ return CS_END_DATA;
+ }
+
+ if (numrows!=-1) numrows+= result->num_rows;
+ while ((retcode=ct_fetch(result->sybase_ptr->cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, NULL))==CS_SUCCEED
+ || retcode==CS_ROW_FAIL) {
+ /*
+ if (retcode==CS_ROW_FAIL) {
+ php_error(E_WARNING, "Sybase: Error reading row %d", result->num_rows);
+ }
+ */
+
+ /* i= result->num_rows++; */
+ result->num_rows++;
+ i= result->store ? result->num_rows- 1 : 0;
+ if (i >= result->blocks_initialized*SYBASE_ROWS_BLOCK) {
+ result->data = (zval **) erealloc(result->data, sizeof(zval *)*SYBASE_ROWS_BLOCK*(++result->blocks_initialized));
+ }
+ if (result->store || 1 == result->num_rows) {
+ result->data[i] = (zval *) emalloc(sizeof(zval)*result->num_fields);
+ }
-static sybase_result * php_sybase_fetch_result_set (sybase_link *sybase_ptr)
+ for (j=0; j<result->num_fields; j++) {
+ if (result->indicators[j] == -1) { /* null value */
+ ZVAL_NULL(&result->data[i][j]);
+ } else {
+ Z_STRLEN(result->data[i][j]) = result->lengths[j]-1; /* we don't need the NULL in the length */
+ Z_STRVAL(result->data[i][j]) = estrndup(result->tmp_buffer[j], result->lengths[j]);
+ Z_TYPE(result->data[i][j]) = IS_STRING;
+
+ switch (result->numerics[j]) {
+ case 1:
+ convert_to_long(&result->data[i][j]);
+ break;
+ case 2:
+ convert_to_double(&result->data[i][j]); result->numerics[j]= 1;
+ break;
+ }
+ }
+ }
+ if (numrows!=-1 && result->num_rows>=numrows) break;
+ }
+
+ result->last_retcode= retcode;
+
+ switch (retcode) {
+ case CS_END_DATA:
+ php_sybase_finish_results(result);
+ break;
+
+ case CS_ROW_FAIL:
+ case CS_SUCCEED:
+ break;
+
+ default:
+ _free_sybase_result(result);
+ result = NULL;
+ break;
+ }
+
+ return retcode;
+}
+
+static sybase_result * php_sybase_fetch_result_set (sybase_link *sybase_ptr, int buffered, int store)
{
int num_fields;
sybase_result *result;
- char **tmp_buffer;
- CS_INT *lengths;
- CS_SMALLINT *indicators;
- unsigned char *numerics;
- CS_INT *types;
- CS_DATAFMT *datafmt;
- int i, j, retcode;
- int blocks_initialized=1;
-
- /* The following is more or less the equivalent of mysql_store_result().
+ int i, j;
+ CS_INT retcode;
+
+ /* The following (if unbuffered) is more or less the equivalent of mysql_store_result().
* fetch all rows from the server into the row buffer, thus:
* 1) Being able to fire up another query without explicitly reading all rows
* 2) Having numrows accessible
*/
-
if (ct_res_info(sybase_ptr->cmd, CS_NUMDATA, &num_fields, CS_UNUSED, NULL)!=CS_SUCCEED) {
return NULL;
}
-
+
result = (sybase_result *) emalloc(sizeof(sybase_result));
- result->data = (pval **) emalloc(sizeof(pval *)*SYBASE_ROWS_BLOCK);
+ result->data = (zval **) emalloc(sizeof(zval *)*SYBASE_ROWS_BLOCK);
result->fields = NULL;
result->sybase_ptr = sybase_ptr;
result->cur_field=result->cur_row=result->num_rows=0;
result->num_fields = num_fields;
-
- tmp_buffer = (char **) emalloc(sizeof(char *)*num_fields);
- lengths = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
- indicators = (CS_SMALLINT *) emalloc(sizeof(CS_INT)*num_fields);
- datafmt = (CS_DATAFMT *) emalloc(sizeof(CS_DATAFMT)*num_fields);
- numerics = (unsigned char *) emalloc(sizeof(unsigned char)*num_fields);
- types = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
-
-
+ result->last_retcode = 0;
+ result->store= store;
+ result->blocks_initialized= 1;
+ result->tmp_buffer = (char **) emalloc(sizeof(char *)*num_fields);
+ result->lengths = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
+ result->indicators = (CS_SMALLINT *) emalloc(sizeof(CS_INT)*num_fields);
+ result->datafmt = (CS_DATAFMT *) emalloc(sizeof(CS_DATAFMT)*num_fields);
+ result->numerics = (unsigned char *) emalloc(sizeof(unsigned char)*num_fields);
+ result->types = (CS_INT *) emalloc(sizeof(CS_INT)*num_fields);
+
for (i=0; i<num_fields; i++) {
- ct_describe(sybase_ptr->cmd, i+1, &datafmt[i]);
- types[i] = datafmt[i].datatype;
- switch (datafmt[i].datatype) {
+ ct_describe(sybase_ptr->cmd, i+1, &result->datafmt[i]);
+ result->types[i] = result->datafmt[i].datatype;
+ switch (result->datafmt[i].datatype) {
case CS_CHAR_TYPE:
case CS_VARCHAR_TYPE:
case CS_TEXT_TYPE:
case CS_IMAGE_TYPE:
- datafmt[i].maxlength++;
- numerics[i] = 0;
+ result->datafmt[i].maxlength++;
+ result->numerics[i] = 0;
break;
case CS_BINARY_TYPE:
case CS_VARBINARY_TYPE:
- datafmt[i].maxlength *= 2;
- datafmt[i].maxlength++;
- numerics[i] = 0;
+ result->datafmt[i].maxlength *= 2;
+ result->datafmt[i].maxlength++;
+ result->numerics[i] = 0;
break;
case CS_BIT_TYPE:
case CS_TINYINT_TYPE:
- datafmt[i].maxlength = 4;
- numerics[i] = 1;
+ result->datafmt[i].maxlength = 4;
+ result->numerics[i] = 1;
break;
case CS_SMALLINT_TYPE:
- datafmt[i].maxlength = 7;
- numerics[i] = 1;
+ result->datafmt[i].maxlength = 7;
+ result->numerics[i] = 1;
break;
case CS_INT_TYPE:
- datafmt[i].maxlength = 12;
- numerics[i] = 1;
+ result->datafmt[i].maxlength = 12;
+ result->numerics[i] = 1;
break;
case CS_REAL_TYPE:
case CS_FLOAT_TYPE:
- datafmt[i].maxlength = 24;
- numerics[i] = 1;
+ result->datafmt[i].maxlength = 24;
+ result->numerics[i] = 2;
break;
case CS_MONEY_TYPE:
case CS_MONEY4_TYPE:
- datafmt[i].maxlength = 24;
- numerics[i] = 0;
+ result->datafmt[i].maxlength = 24;
+ result->numerics[i] = 2;
break;
case CS_DATETIME_TYPE:
case CS_DATETIME4_TYPE:
- datafmt[i].maxlength = 30;
- numerics[i] = 0;
+ result->datafmt[i].maxlength = 30;
+ result->numerics[i] = 0;
break;
case CS_NUMERIC_TYPE:
case CS_DECIMAL_TYPE:
- datafmt[i].maxlength = datafmt[i].precision + 3;
- numerics[i] = 1;
+ result->datafmt[i].maxlength = result->datafmt[i].precision + 3;
+ /* numeric(10) vs numeric(10, 1) */
+ result->numerics[i] = (result->datafmt[i].scale == 0) ? 1 : 2;
break;
default:
- datafmt[i].maxlength++;
- numerics[i] = 0;
+ result->datafmt[i].maxlength++;
+ result->numerics[i] = 0;
break;
}
- tmp_buffer[i] = (char *)emalloc(datafmt[i].maxlength);
- datafmt[i].datatype = CS_CHAR_TYPE;
- datafmt[i].format = CS_FMT_NULLTERM;
- ct_bind(sybase_ptr->cmd, i+1, &datafmt[i], tmp_buffer[i], &lengths[i], &indicators[i]);
- }
-
- while ((retcode=ct_fetch(sybase_ptr->cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED, NULL))==CS_SUCCEED
- || retcode==CS_ROW_FAIL) {
- /*
- if (retcode==CS_ROW_FAIL) {
- php_error(E_WARNING, "Sybase: Error reading row %d", result->num_rows);
- }
- */
- i = result->num_rows++;
- if (result->num_rows > blocks_initialized*SYBASE_ROWS_BLOCK) {
- result->data = (pval **) erealloc(result->data, sizeof(pval *)*SYBASE_ROWS_BLOCK*(++blocks_initialized));
- }
- result->data[i] = (pval *) emalloc(sizeof(pval)*num_fields);
- for (j=0; j<num_fields; j++) {
- if (indicators[j] == -1) { /* null value */
- ZVAL_FALSE(&result->data[i][j]);
- } else {
- Z_STRLEN(result->data[i][j]) = lengths[j]-1; /* we don't need the NULL in the length */
- Z_STRVAL(result->data[i][j]) = estrndup(tmp_buffer[j], lengths[j]);
- Z_TYPE(result->data[i][j]) = IS_STRING;
- }
- }
+ result->tmp_buffer[i] = (char *)emalloc(result->datafmt[i].maxlength);
+ result->datafmt[i].datatype = CS_CHAR_TYPE;
+ result->datafmt[i].format = CS_FMT_NULLTERM;
+ ct_bind(sybase_ptr->cmd, i+1, &result->datafmt[i], result->tmp_buffer[i], &result->lengths[i], &result->indicators[i]);
}
- if (retcode != CS_END_DATA) {
- _free_sybase_result(result);
- result = NULL;
- } else {
- result->fields = (sybase_field *) emalloc(sizeof(sybase_field)*num_fields);
- j=0;
- for (i=0; i<num_fields; i++) {
- char computed_buf[16];
+ result->fields = (sybase_field *) emalloc(sizeof(sybase_field)*num_fields);
+ j=0;
+ for (i=0; i<num_fields; i++) {
+ char computed_buf[16];
- if (datafmt[i].namelen>0) {
- result->fields[i].name = estrndup(datafmt[i].name, datafmt[i].namelen);
+ if (result->datafmt[i].namelen>0) {
+ result->fields[i].name = estrndup(result->datafmt[i].name, result->datafmt[i].namelen);
+ } else {
+ if (j>0) {
+ snprintf(computed_buf, 16, "computed%d", j);
} else {
- if (j>0) {
- snprintf(computed_buf, 16, "computed%d", j);
- } else {
- strcpy(computed_buf, "computed");
- }
- result->fields[i].name = estrdup(computed_buf);
- j++;
+ strcpy(computed_buf, "computed");
}
- result->fields[i].column_source = empty_string;
- result->fields[i].max_length = datafmt[i].maxlength-1;
- result->fields[i].numeric = numerics[i];
- Z_TYPE(result->fields[i]) = types[i];
+ result->fields[i].name = estrdup(computed_buf);
+ j++;
}
+ result->fields[i].column_source = empty_string;
+ result->fields[i].max_length = result->datafmt[i].maxlength-1;
+ result->fields[i].numeric = result->numerics[i];
+ Z_TYPE(result->fields[i]) = result->types[i];
}
- efree(datafmt);
- efree(lengths);
- efree(indicators);
- efree(numerics);
- efree(types);
- for (i=0; i<num_fields; i++) {
- efree(tmp_buffer[i]);
- }
- efree(tmp_buffer);
+ retcode= php_sybase_fetch_result_row(result, buffered ? 1 : -1);
return result;
}
-
-/* {{{ proto int sybase_query(string query [, int link_id])
- Send Sybase query */
-PHP_FUNCTION(sybase_query)
+static void php_sybase_query (INTERNAL_FUNCTION_PARAMETERS, int buffered)
{
- pval **query, **sybase_link_index=NULL;
- int id;
+ zval **query, **sybase_link_index=NULL;
+ zval **store_mode= NULL;
+ int id, deadlock_count, store;
sybase_link *sybase_ptr;
sybase_result *result;
CS_INT restype;
@@ -1070,6 +1219,7 @@ PHP_FUNCTION(sybase_query)
Q_FAILURE, /* Failure, no results. */
} status;
+ store= 1;
switch(ZEND_NUM_ARGS()) {
case 1:
if (zend_get_parameters_ex(1, &query)==FAILURE) {
@@ -1083,6 +1233,14 @@ PHP_FUNCTION(sybase_query)
}
id = -1;
break;
+ case 3:
+ if (zend_get_parameters_ex(3, &query, &sybase_link_index, &store_mode)==FAILURE) {
+ RETURN_FALSE;
+ }
+ id = -1;
+ convert_to_long_ex(store_mode);
+ store= (Z_LVAL_PP(store_mode) != 0);
+ break;
default:
WRONG_PARAM_COUNT;
break;
@@ -1093,13 +1251,23 @@ PHP_FUNCTION(sybase_query)
convert_to_string_ex(query);
/* Fail if we already marked this connection dead. */
-
if (sybase_ptr->dead) {
RETURN_FALSE;
}
+
+ /* Check to see if a previous sybase_unbuffered_query has read all rows */
+ if (sybase_ptr->active_result_index) {
+ zend_error(E_NOTICE, "Sybase: Called %s() without first fetching all rows from a previous unbuffered query",
+ get_active_function_name(TSRMLS_C));
+ if (sybase_ptr->cmd) {
+ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
+ }
+ zend_list_delete(sybase_ptr->active_result_index);
+ sybase_ptr->active_result_index= 0;
+ }
/* Repeat until we don't deadlock. */
-
+ deadlock_count= 0;
for (;;) {
result = NULL;
sybase_ptr->deadlock = 0;
@@ -1116,12 +1284,14 @@ PHP_FUNCTION(sybase_query)
* CS_BUSY for some reason.
*/
sybase_ptr->dead = 1;
- RETURN_FALSE;
+ zend_error(E_WARNING, "Sybase: Connection is dead");
+ RETURN_FALSE;
}
if (ct_send(sybase_ptr->cmd)!=CS_SUCCEED) {
ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
sybase_ptr->dead = 1;
+ zend_error(E_WARNING, "Sybase: Cannot send command");
RETURN_FALSE;
}
@@ -1134,9 +1304,10 @@ PHP_FUNCTION(sybase_query)
if (ct_results(sybase_ptr->cmd, &restype)!=CS_SUCCEED) {
ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
sybase_ptr->dead = 1;
+ zend_error(E_WARNING, "Sybase: Cannot read results");
RETURN_FALSE;
}
-
+
switch ((int) restype) {
case CS_CMD_FAIL:
default:
@@ -1154,6 +1325,7 @@ PHP_FUNCTION(sybase_query)
case CS_ROWFMT_RESULT:
case CS_DESCRIBE_RESULT:
case CS_MSG_RESULT:
+ buffered= 0; /* These queries have no need for buffering */
status = Q_SUCCESS;
break;
case CS_COMPUTE_RESULT:
@@ -1161,7 +1333,7 @@ PHP_FUNCTION(sybase_query)
case CS_PARAM_RESULT:
case CS_ROW_RESULT:
case CS_STATUS_RESULT:
- result = php_sybase_fetch_result_set(sybase_ptr);
+ result = php_sybase_fetch_result_set(sybase_ptr, buffered, store);
if (result == NULL) {
ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
sybase_ptr->dead = 1;
@@ -1170,63 +1342,68 @@ PHP_FUNCTION(sybase_query)
status = Q_RESULT;
break;
}
+
+ /* Check for left-over results */
+ if (!buffered && status != Q_RESULT) {
+ while ((retcode = ct_results(sybase_ptr->cmd, &restype))==CS_SUCCEED) {
+ switch ((int) restype) {
+ case CS_CMD_SUCCEED:
+ case CS_CMD_DONE:
+ break;
+
+ case CS_CMD_FAIL:
+ status = Q_FAILURE;
+ break;
+
+ case CS_COMPUTE_RESULT:
+ case CS_CURSOR_RESULT:
+ case CS_PARAM_RESULT:
+ case CS_ROW_RESULT:
+ /* Unexpected results, cancel them. */
+ case CS_STATUS_RESULT:
+ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_CURRENT);
+ break;
+
+ default:
+ status = Q_FAILURE;
+ break;
+ }
+ if (status == Q_FAILURE) {
+ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
+ }
+ }
- /* The only restype we should get now is CS_CMD_DONE, possibly
- * followed by a CS_STATUS_RESULT/CS_CMD_SUCCEED/CS_CMD_DONE
- * sequence if the command was a stored procedure call. But we
- * still need to read and discard unexpected results. We might
- * want to return a failure in this case because the application
- * won't be getting all the results it asked for.
- */
- while ((retcode = ct_results(sybase_ptr->cmd, &restype))==CS_SUCCEED) {
- switch ((int) restype) {
- case CS_CMD_SUCCEED:
- case CS_CMD_DONE:
- break;
-
- case CS_CMD_FAIL:
- status = Q_FAILURE;
- break;
-
- case CS_COMPUTE_RESULT:
- case CS_CURSOR_RESULT:
- case CS_PARAM_RESULT:
- case CS_ROW_RESULT:
- /* Unexpected results, cancel them. */
- case CS_STATUS_RESULT:
- ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_CURRENT);
+ switch (retcode) {
+ case CS_END_RESULTS:
+ /* Normal. */
break;
+ case CS_FAIL:
+ /* Hopefully this either cleans up the connection, or the
+ * connection ends up marked dead so it will be reopened
+ * if it is persistent. We may want to do
+ * ct_close(CS_FORCE_CLOSE) if ct_cancel() fails; see the
+ * doc for ct_results()==CS_FAIL.
+ */
+ ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
+ /* Don't take chances with the vagaries of ct-lib. Mark it
+ * dead ourselves.
+ */
+ sybase_ptr->dead = 1;
+ case CS_CANCELED:
default:
status = Q_FAILURE;
break;
}
- if (status == Q_FAILURE) {
- ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
- }
}
-
- switch (retcode) {
- case CS_END_RESULTS:
- /* Normal. */
- break;
-
- case CS_FAIL:
- /* Hopefully this either cleans up the connection, or the
- * connection ends up marked dead so it will be reopened
- * if it is persistent. We may want to do
- * ct_close(CS_FORCE_CLOSE) if ct_cancel() fails; see the
- * doc for ct_results()==CS_FAIL.
- */
- ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
- /* Don't take chances with the vagaries of ct-lib. Mark it
- * dead ourselves.
- */
- sybase_ptr->dead = 1;
- case CS_CANCELED:
- default:
- status = Q_FAILURE;
- break;
+
+ /* Retry deadlocks up until deadlock_retry_count times */
+ if (sybase_ptr->deadlock && SybCtG(deadlock_retry_count) != -1 && ++deadlock_count > SybCtG(deadlock_retry_count)) {
+ zend_error(E_WARNING, "Sybase: Retried deadlock %d times [max: %d], giving up\n", deadlock_count- 1, SybCtG(deadlock_retry_count));
+ if (result != NULL) {
+ _free_sybase_result(result);
+ }
+ break;
}
/* If query completed without deadlock, break out of the loop.
@@ -1260,16 +1437,32 @@ PHP_FUNCTION(sybase_query)
RETURN_FALSE;
}
- ZEND_REGISTER_RESOURCE(return_value, result, le_result);
+ /* Indicate we have data in case of buffered queries */
+ id= ZEND_REGISTER_RESOURCE(return_value, result, le_result);
+ sybase_ptr->active_result_index= buffered ? id : 0;
}
+/* {{{ proto int sybase_query(string query [, int link_id])
+ Send Sybase query */
+PHP_FUNCTION(sybase_query)
+{
+ php_sybase_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
+}
/* }}} */
+/* {{{ proto int sybase_unbuffered_query(string query [, int link_id])
+ Send Sybase query */
+PHP_FUNCTION(sybase_unbuffered_query)
+{
+ php_sybase_query(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+
+
/* {{{ proto bool sybase_free_result(int result)
Free result memory */
PHP_FUNCTION(sybase_free_result)
{
- pval *sybase_result_index;
+ zval *sybase_result_index;
sybase_result *result;
if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
@@ -1282,7 +1475,14 @@ PHP_FUNCTION(sybase_free_result)
}
ZEND_FETCH_RESOURCE(result, sybase_result *, &sybase_result_index, -1, "Sybase result", le_result);
-
+
+ /* Did we fetch up until the end? */
+ if (result->last_retcode != CS_END_DATA) {
+ /* zend_error(E_WARNING, "Sybase: Cancelling the rest of the results\n"); */
+ ct_cancel(NULL, result->sybase_ptr->cmd, CS_CANCEL_ALL);
+ php_sybase_finish_results(result);
+ }
+
zend_list_delete(Z_LVAL_P(sybase_result_index));
RETURN_TRUE;
}
@@ -1301,7 +1501,7 @@ PHP_FUNCTION(sybase_get_last_message)
Get number of rows in result */
PHP_FUNCTION(sybase_num_rows)
{
- pval *sybase_result_index;
+ zval *sybase_result_index;
sybase_result *result;
if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
@@ -1320,7 +1520,7 @@ PHP_FUNCTION(sybase_num_rows)
Get number of fields in result */
PHP_FUNCTION(sybase_num_fields)
{
- pval *sybase_result_index;
+ zval *sybase_result_index;
sybase_result *result;
if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
@@ -1339,40 +1539,48 @@ PHP_FUNCTION(sybase_num_fields)
Get row as enumerated array */
PHP_FUNCTION(sybase_fetch_row)
{
- pval *sybase_result_index;
+ zval *sybase_result_index;
int i;
sybase_result *result;
- pval *field_content;
+ zval *field_content;
if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
WRONG_PARAM_COUNT;
}
-
+
ZEND_FETCH_RESOURCE(result, sybase_result *, &sybase_result_index, -1, "Sybase result", le_result);
+ /* Unbuffered? */
+ if (result->last_retcode != CS_END_DATA) {
+ php_sybase_fetch_result_row(result, 1);
+ }
+
+ /* At the end? */
if (result->cur_row >= result->num_rows) {
+ result->sybase_ptr->active_result_index= 0;
RETURN_FALSE;
}
array_init(return_value);
for (i=0; i<result->num_fields; i++) {
ALLOC_ZVAL(field_content);
- *field_content = result->data[result->cur_row][i];
+ *field_content = result->data[result->store ? result->cur_row : 0][i];
INIT_PZVAL(field_content);
- pval_copy_constructor(field_content);
- zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *) &field_content, sizeof(pval* ), NULL);
+ zval_copy_ctor(field_content);
+ zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *) &field_content, sizeof(zval* ), NULL);
}
result->cur_row++;
}
/* }}} */
-static void php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS)
+static void php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int numerics)
{
- pval *sybase_result_index;
+ zval *sybase_result_index;
sybase_result *result;
- int i;
- pval *tmp;
+ int i, j;
+ zval *tmp;
+ char name[32];
if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &sybase_result_index)==FAILURE) {
WRONG_PARAM_COUNT;
@@ -1380,26 +1588,42 @@ static void php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS)
ZEND_FETCH_RESOURCE(result, sybase_result *, &sybase_result_index, -1, "Sybase result", le_result);
+ /* Unbuffered ? Fetch next row */
+ if (result->last_retcode != CS_END_DATA) {
+ php_sybase_fetch_result_row(result, 1);
+ }
+
+ /* At the end? */
if (result->cur_row >= result->num_rows) {
+ result->sybase_ptr->active_result_index= 0;
RETURN_FALSE;
}
if (array_init(return_value)==FAILURE) {
RETURN_FALSE;
}
-
+
+ j= 1;
for (i=0; i<result->num_fields; i++) {
ALLOC_ZVAL(tmp);
- *tmp = result->data[result->cur_row][i];
+ *tmp = result->data[result->store ? result->cur_row : 0][i];
INIT_PZVAL(tmp);
if (PG(magic_quotes_runtime) && Z_TYPE_P(tmp) == IS_STRING) {
Z_STRVAL_P(tmp) = php_addslashes(Z_STRVAL_P(tmp), Z_STRLEN_P(tmp), &Z_STRLEN_P(tmp), 0 TSRMLS_CC);
} else {
- pval_copy_constructor(tmp);
+ zval_copy_ctor(tmp);
+ }
+ if (numerics) {
+ zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *) &tmp, sizeof(zval *), NULL);
}
- zend_hash_index_update(Z_ARRVAL_P(return_value), i, (void *) &tmp, sizeof(pval *), NULL);
tmp->refcount++;
- zend_hash_update(Z_ARRVAL_P(return_value), result->fields[i].name, strlen(result->fields[i].name)+1, (void *) &tmp, sizeof(pval *), NULL);
+
+ if (zend_hash_exists(Z_ARRVAL_P(return_value), result->fields[i].name, strlen(result->fields[i].name)+1)) {
+ snprintf(name, 32, "%s%d", result->fields[i].name, j);
+ result->fields[i].name= estrdup(name);
+ j++;
+ }
+ zend_hash_update(Z_ARRVAL_P(return_value), result->fields[i].name, strlen(result->fields[i].name)+1, (void *) &tmp, sizeof(zval *), NULL);
}
result->cur_row++;
}
@@ -1409,7 +1633,7 @@ static void php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS)
Fetch row as object */
PHP_FUNCTION(sybase_fetch_object)
{
- php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
if (Z_TYPE_P(return_value)==IS_ARRAY) {
object_and_properties_init(return_value, ZEND_STANDARD_CLASS_DEF_PTR, Z_ARRVAL_P(return_value));
}
@@ -1420,7 +1644,15 @@ PHP_FUNCTION(sybase_fetch_object)
Fetch row as array */
PHP_FUNCTION(sybase_fetch_array)
{
- php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU);
+ php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
+}
+/* }}} */
+
+/* {{{ proto array sybase_fetch_assoc(int result)
+ Fetch row as array without numberic indices */
+PHP_FUNCTION(sybase_fetch_assoc)
+{
+ php_sybase_fetch_hash(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}
/* }}} */
@@ -1428,7 +1660,7 @@ PHP_FUNCTION(sybase_fetch_array)
Move internal row pointer */
PHP_FUNCTION(sybase_data_seek)
{
- pval *sybase_result_index, *offset;
+ zval *sybase_result_index, *offset;
sybase_result *result;
if (ZEND_NUM_ARGS()!=2 || getParameters(ht, 2, &sybase_result_index, &offset)==FAILURE) {
@@ -1439,6 +1671,12 @@ PHP_FUNCTION(sybase_data_seek)
ZEND_FETCH_RESOURCE(result, sybase_result *, &sybase_result_index, -1, "Sybase result", le_result);
convert_to_long(offset);
+
+ /* Unbuffered ? */
+ if (result->last_retcode != CS_END_DATA && Z_LVAL_P(offset)>=result->num_rows) {
+ php_sybase_fetch_result_row(result, Z_LVAL_P(offset));
+ }
+
if (Z_LVAL_P(offset)<0 || Z_LVAL_P(offset)>=result->num_rows) {
php_error(E_WARNING, "Sybase: Bad row offset");
RETURN_FALSE;
@@ -1497,7 +1735,7 @@ static char *php_sybase_get_field_name(CS_INT type)
Get field information */
PHP_FUNCTION(sybase_fetch_field)
{
- pval *sybase_result_index, *offset;
+ zval *sybase_result_index, *offset;
int field_offset;
sybase_result *result;
@@ -1550,7 +1788,7 @@ PHP_FUNCTION(sybase_fetch_field)
Set field offset */
PHP_FUNCTION(sybase_field_seek)
{
- pval *sybase_result_index, *offset;
+ zval *sybase_result_index, *offset;
int field_offset;
sybase_result *result;
@@ -1562,6 +1800,11 @@ PHP_FUNCTION(sybase_field_seek)
convert_to_long(offset);
field_offset = Z_LVAL_P(offset);
+
+ /* Unbuffered ? */
+ if (result->last_retcode != CS_END_DATA && field_offset>=result->num_rows) {
+ php_sybase_fetch_result_row(result, field_offset);
+ }
if (field_offset<0 || field_offset >= result->num_fields) {
php_error(E_WARNING, "Sybase: Bad column offset");
@@ -1578,7 +1821,7 @@ PHP_FUNCTION(sybase_field_seek)
Get result data */
PHP_FUNCTION(sybase_result)
{
- pval *row, *field, *sybase_result_index;
+ zval *row, *field, *sybase_result_index;
int field_offset=0;
sybase_result *result;
@@ -1590,6 +1833,8 @@ PHP_FUNCTION(sybase_result)
ZEND_FETCH_RESOURCE(result, sybase_result *, &sybase_result_index, -1, "Sybase result", le_result);
convert_to_long(row);
+
+
if (Z_LVAL_P(row)<0 || Z_LVAL_P(row)>=result->num_rows) {
php_error(E_WARNING, "Sybase: Bad row offset (%d)", Z_LVAL_P(row));
RETURN_FALSE;
@@ -1622,7 +1867,7 @@ PHP_FUNCTION(sybase_result)
}
*return_value = result->data[Z_LVAL_P(row)][field_offset];
- pval_copy_constructor(return_value);
+ zval_copy_ctor(return_value);
}
/* }}} */
@@ -1631,7 +1876,7 @@ PHP_FUNCTION(sybase_result)
Get number of affected rows in last query */
PHP_FUNCTION(sybase_affected_rows)
{
- pval *sybase_link_index;
+ zval *sybase_link_index;
sybase_link *sybase_ptr;
int id;
@@ -1668,7 +1913,13 @@ PHP_MINFO_FUNCTION(sybase)
php_info_print_table_row(2, "Active Persistent Links", buf);
sprintf(buf, "%ld", SybCtG(num_links));
php_info_print_table_row(2, "Active Links", buf);
+ sprintf(buf, "%ld", SybCtG(min_server_severity));
+ php_info_print_table_row(2, "Min server severity", buf);
+ sprintf(buf, "%ld", SybCtG(min_client_severity));
+ php_info_print_table_row(2, "Min client severity", buf);
php_info_print_table_row(2, "Application Name", SybCtG(appname));
+ sprintf(buf, "%ld", SybCtG(deadlock_retry_count));
+ php_info_print_table_row(2, "Deadlock retry count", buf);
php_info_print_table_end();
DISPLAY_INI_ENTRIES();
@@ -1679,7 +1930,7 @@ PHP_MINFO_FUNCTION(sybase)
Sets minimum client severity */
PHP_FUNCTION(sybase_min_client_severity)
{
- pval *severity;
+ zval *severity;
if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &severity)==FAILURE) {
WRONG_PARAM_COUNT;
@@ -1694,7 +1945,7 @@ PHP_FUNCTION(sybase_min_client_severity)
Sets minimum server severity */
PHP_FUNCTION(sybase_min_server_severity)
{
- pval *severity;
+ zval *severity;
if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &severity)==FAILURE) {
WRONG_PARAM_COUNT;
@@ -1704,6 +1955,70 @@ PHP_FUNCTION(sybase_min_server_severity)
}
/* }}} */
+/* {{{ proto void sybase_deadlock_retry_count(int retry_count)
+ Sets deadlock retry count */
+PHP_FUNCTION(sybase_deadlock_retry_count)
+{
+ zval *retry_count;
+
+ if (ZEND_NUM_ARGS()!=1 || getParameters(ht, 1, &retry_count)==FAILURE) {
+ WRONG_PARAM_COUNT;
+ }
+ convert_to_long(retry_count);
+ SybCtG(deadlock_retry_count) = Z_LVAL_P(retry_count);
+}
+/* }}} */
+
+
+/* {{{ proto bool sybase_set_message_handler(mixed error_func)
+ Set the error handler, to be called when a server message is raised.
+ If error_func is NULL the handler will be deleted */
+PHP_FUNCTION(sybase_set_message_handler)
+{
+ zval ***params;
+ zval *retval_ptr;
+ char *name;
+ int argc = ZEND_NUM_ARGS();
+
+ if (argc != 1) {
+ WRONG_PARAM_COUNT;
+ }
+
+ params = emalloc(sizeof(zval **) * argc);
+
+ if (zend_get_parameters_array_ex(argc, params) == FAILURE) {
+ efree(params);
+ RETURN_FALSE;
+ }
+
+ if (SybCtG(callback_name)) {
+ zval_dtor(SybCtG(callback_name));
+ SybCtG(callback_name)= NULL;
+ }
+
+ if (Z_TYPE_PP(params[0]) == IS_NULL) {
+ RETURN_TRUE;
+ }
+
+ if (!zend_is_callable(*params[0], 0, &name)) {
+ zend_error(E_WARNING, "%s(): First argumented is expected to be a valid callback, '%s' was given", get_active_function_name(TSRMLS_C), name);
+ efree(name);
+ efree(params);
+ RETURN_FALSE;
+ }
+
+ MAKE_STD_ZVAL(SybCtG(callback_name));
+
+ ALLOC_ZVAL(SybCtG(callback_name));
+ *SybCtG(callback_name) = **params[0];
+ INIT_PZVAL(SybCtG(callback_name));
+ zval_copy_ctor(SybCtG(callback_name));
+ efree(params);
+ efree(name);
+ RETURN_TRUE;
+}
+/* }}} */
+
#endif
diff --git a/ext/sybase_ct/php_sybase_ct.h b/ext/sybase_ct/php_sybase_ct.h
index 9176fcebf3..5a009741d8 100644
--- a/ext/sybase_ct/php_sybase_ct.h
+++ b/ext/sybase_ct/php_sybase_ct.h
@@ -12,7 +12,8 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Author: Zeev Suraski <zeev@zend.com> |
+ | Authors: Zeev Suraski <zeev@zend.com> |
+ | Timm Friebe <php_sybase_ct@thekid.de> |
+----------------------------------------------------------------------+
*/
@@ -39,12 +40,14 @@ PHP_FUNCTION(sybase_pconnect);
PHP_FUNCTION(sybase_close);
PHP_FUNCTION(sybase_select_db);
PHP_FUNCTION(sybase_query);
+PHP_FUNCTION(sybase_unbuffered_query);
PHP_FUNCTION(sybase_free_result);
PHP_FUNCTION(sybase_get_last_message);
PHP_FUNCTION(sybase_num_rows);
PHP_FUNCTION(sybase_num_fields);
PHP_FUNCTION(sybase_fetch_row);
PHP_FUNCTION(sybase_fetch_array);
+PHP_FUNCTION(sybase_fetch_assoc);
PHP_FUNCTION(sybase_fetch_object);
PHP_FUNCTION(sybase_data_seek);
PHP_FUNCTION(sybase_result);
@@ -53,7 +56,8 @@ PHP_FUNCTION(sybase_field_seek);
PHP_FUNCTION(sybase_min_client_severity);
PHP_FUNCTION(sybase_min_server_severity);
PHP_FUNCTION(sybase_fetch_field);
-
+PHP_FUNCTION(sybase_set_message_handler);
+PHP_FUNCTION(sybase_deadlock_retry_count);
#include <ctpublic.h>
@@ -66,6 +70,8 @@ ZEND_BEGIN_MODULE_GLOBALS(sybase)
char *hostname;
char *server_message;
long min_server_severity, min_client_severity;
+ long deadlock_retry_count;
+ zval *callback_name;
CS_CONTEXT *context;
ZEND_END_MODULE_GLOBALS(sybase)
@@ -75,6 +81,7 @@ typedef struct {
int valid;
int deadlock;
int dead;
+ int active_result_index;
long affected_rows;
} sybase_link;
@@ -92,9 +99,19 @@ typedef struct {
sybase_link *sybase_ptr;
int cur_row,cur_field;
int num_rows,num_fields;
+
+ /* For unbuffered reads */
+ CS_INT *lengths;
+ CS_SMALLINT *indicators;
+ char **tmp_buffer;
+ unsigned char *numerics;
+ CS_INT *types;
+ CS_DATAFMT *datafmt;
+ int blocks_initialized;
+ CS_RETCODE last_retcode;
+ int store;
} sybase_result;
-
#ifdef ZTS
# define SybCtG(v) TSRMG(sybase_globals_id, zend_sybase_globals *, v)
#else