Hi there,

here's a small patch for sybase_query() in ext/sybase_ct.c which gives
some extended functionality in that it allows to send batch queries from
php to the Sybase backend.
Currently it's only possible to send single queries via sybase_query(),
but in some cases it can be convenient to construct SQL batches and send
them as a single sequence of queries to the DB. The only restriction
then is (AFAIK) that, if you want to return a result, it has to be the
last SQL statement in the batch. It can be preceeded by any (reasonable)
number of "preparing" queries, which only return some SUCCEED/FAIL
status.

Here's an example:

$sql  ="SELECT id, name INTO #tmp1 FROM person ";
$sql .= INSERT #tmp1 VALUES (some_id, "some_name") ";
$sql .= DELETE FROM #tmp1 WHERE some_condition ";
$sql .= SELECT * FROM #tmp1";
$result_id = sybase_query($query, $conn_id);

Well, if this does not make too much sense ... I hope you get the idea
;-)

I've just adapted the code for 4.3.0, but we've been using this without
any bad experience in production on 4.2.1 for some time now.

I'd like to ask the sybase_ct maintainer, if he sees any conflicts with
the code for sybase_unbuffered_query() that was newly introduced in
4.3.0.

If you think the new functionality is useful, feel free to use it ... 

Best regards ... Michael U.
--- php-4.3.0/ext/sybase_ct/php_sybase_ct.c.orig        Fri Feb 14 12:45:56 2003
+++ php-4.3.0/ext/sybase_ct/php_sybase_ct.c     Fri Feb 14 13:45:32 2003
@@ -1297,6 +1297,7 @@
        deadlock_count= 0;
        for (;;) {
                result = NULL;
+                status = Q_FAILURE;
                sybase_ptr->deadlock = 0;
                sybase_ptr->affected_rows = 0;
 
@@ -1322,81 +1323,94 @@
                        RETURN_FALSE;
                }
 
-               /* Use the first result set or succeed/fail status and discard the
-                * others.  Applications really shouldn't be making calls that
+               /* Use the first result set preceeded by an arbitrary number of
+                 * succeed/fail stati from other queries and discard any result
+                 * sets following the first.
+                 *
+                 * Example: Batch Query (may not make too much sense ...)
+                 *
+                 * SELECT id, name INTO #tmp1 FROM person       // returns only status
+                 * INSERT #tmp1 VALUES (some_id, "some_name")   //    "     "     "
+                 * DELETE FROM #tmp1 WHERE some_condition       //    "     "     "
+                 * SELECT * FORM #tmp1                          // returns result set
+                 *
+                 * Applications really shouldn't be making calls that
                 * return multiple result sets, but if they do then we need to
                 * properly read or cancel them or the connection will become
                 * unusable.
                 */
-               if (ct_results(sybase_ptr->cmd, &restype)!=CS_SUCCEED) {
-                       ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
-                       sybase_ptr->dead = 1;
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "Sybase:  Cannot 
read results");
-                       RETURN_FALSE;
-               }
-    
-               switch ((int) restype) {
-                       case CS_CMD_FAIL:
-                       default:
-                               status = Q_FAILURE;
-                               break;
-                       case CS_CMD_SUCCEED:
-                       case CS_CMD_DONE: {
+  
+                while ((retcode = ct_results(sybase_ptr->cmd, &restype)) == 
+CS_SUCCEED) { 
+                       switch ((int) restype) {
+                               case CS_CMD_FAIL:
+                               default:
+                                       status = Q_FAILURE;
+                                       break;
+                               case CS_CMD_SUCCEED:
+                               case CS_CMD_DONE: {
                                        CS_INT row_count;
                                        if (ct_res_info(sybase_ptr->cmd, CS_ROW_COUNT, 
&row_count, CS_UNUSED, NULL)==CS_SUCCEED) {
                                                sybase_ptr->affected_rows = 
(long)row_count;
                                        }
                                }
                                /* Fall through */
-                       case CS_COMPUTEFMT_RESULT:
-                       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:
-                       case CS_CURSOR_RESULT:
-                       case CS_PARAM_RESULT:
-                       case CS_ROW_RESULT:
-                       case CS_STATUS_RESULT:
-                               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;
-                                       RETURN_FALSE;
-                               }
-                               status = Q_RESULT;
+                               case CS_COMPUTEFMT_RESULT:
+                               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:
+                               case CS_CURSOR_RESULT:
+                               case CS_PARAM_RESULT:
+                               case CS_ROW_RESULT:
+                               case CS_STATUS_RESULT:
+                                       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;
+                                               RETURN_FALSE;
+                                       }
+                                       status = Q_RESULT;
+                                       break;
+                       }
+                        if (status == Q_RESULT) {
                                break;
+                        } else if (status == Q_FAILURE) {
+                               ct_cancel(NULL, sybase_ptr->cmd, CS_CANCEL_ALL);
+                       }
                }
                
                /* 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);
+                       if (retcode != CS_END_RESULTS) {
+                               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);
+                                       }
                                }
                        }
 
@@ -1422,7 +1436,7 @@
                                        status = Q_FAILURE;
                                        break;
                        }
-               }
+               } // END - if(!buffered && status != Q_RESULT)
                
                /* Retry deadlocks up until deadlock_retry_count times */              
 
                if (sybase_ptr->deadlock && SybCtG(deadlock_retry_count) != -1 && 
++deadlock_count > SybCtG(deadlock_retry_count)) {
@@ -1451,7 +1465,7 @@
                if (result != NULL) {
                        _free_sybase_result(result);
                }
-       }
+       } // END - for(;;)
 
        if (status == Q_SUCCESS) {
                RETURN_TRUE;

-- 
PHP Development Mailing List <http://www.php.net/>
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to