]> granicus.if.org Git - php/commitdiff
Enable some more functions with unbuffered queries
authorMarcus Boerger <helly@php.net>
Sun, 27 Apr 2003 13:25:10 +0000 (13:25 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 27 Apr 2003 13:25:10 +0000 (13:25 +0000)
ext/sqlite/sqlite.c

index fb867615e9a1c074e7f22c60fe9cc4acf1f29a39..311cc7001afbbb3bfcf1f793046d843ae23a969d 100644 (file)
@@ -203,7 +203,10 @@ static void real_result_dtor(struct php_sqlite_result *res)
        if (res->vm) {
                sqlite_finalize(res->vm, NULL);
        }
-       
+
+       if (!res->buffered) {
+               res->nrows = 1; /* only one row is stored */
+       }
        for (i = 0; i < res->nrows; i++) {
                base = i * res->ncolumns;
                for (j = 0; j < res->ncolumns; j++) {
@@ -262,7 +265,7 @@ PHP_RSHUTDOWN_FUNCTION(sqlite)
 static void php_sqlite_generic_function_callback(sqlite_func *func, int argc, const char **argv)
 {
        zval *retval = NULL;
-       zval ***zargs;
+       zval ***zargs = NULL;
        zval funcname;
        int i, res;
        char *callable = NULL, *errbuf=NULL;
@@ -345,7 +348,7 @@ static void php_sqlite_generic_function_callback(sqlite_func *func, int argc, co
 static void php_sqlite_function_callback(sqlite_func *func, int argc, const char **argv)
 {
        zval *retval = NULL;
-       zval ***zargs;
+       zval ***zargs = NULL;
        int i, res;
        struct php_sqlite_agg_functions *funcs = sqlite_user_data(func);
        TSRMLS_FETCH();
@@ -801,6 +804,87 @@ PHP_FUNCTION(sqlite_close)
 }
 /* }}} */
 
+/* {{{ */
+int php_sqlite_fetch(struct php_sqlite_result *rres TSRMLS_DC)
+{
+       const char **rowdata, **colnames;
+       int ret, i, base;
+       char *errtext = NULL;
+
+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++) {
+                       rres->col_names[i] = estrdup(colnames[i]);
+               }
+               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;
+
+               case SQLITE_BUSY:
+               case SQLITE_ERROR:
+               case SQLITE_MISUSE:
+               default:
+                       /* fall through to finalize */
+                       ;
+
+               case SQLITE_DONE:
+                       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;
+       }
+       return ret;
+}
+/* }}} */
+
 /* {{{ proto resource sqlite_unbuffered_query(string query, resource db)
    Execute a query that does not prefetch and buffer all data */
 PHP_FUNCTION(sqlite_unbuffered_query)
@@ -846,7 +930,16 @@ PHP_FUNCTION(sqlite_unbuffered_query)
        rres = (struct php_sqlite_result*)emalloc(sizeof(*rres));
        memcpy(rres, &res, sizeof(*rres));
 
-       /* now the result set is ready for stepping */
+       /* now the result set is ready for stepping: get first row */
+       ret = php_sqlite_fetch(rres TSRMLS_CC);
+
+       db->last_err_code = ret;
+
+       if (ret != SQLITE_OK) {
+               real_result_dtor(rres);
+               RETURN_FALSE;
+       }
+       
        rres->curr_row = 0;
 
        ZEND_REGISTER_RESOURCE(return_value, rres, le_sqlite_result);
@@ -862,10 +955,9 @@ PHP_FUNCTION(sqlite_query)
        char *sql;
        long sql_len;
        struct php_sqlite_result res, *rres;
-       int ret, i, base;
+       int ret;
        char *errtext = NULL;
        const char *tail;
-       const char **rowdata, **colnames;
 
        if (FAILURE == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET,
                                ZEND_NUM_ARGS() TSRMLS_CC, "sr", &sql, &sql_len, &zdb) && 
@@ -902,56 +994,12 @@ PHP_FUNCTION(sqlite_query)
        rres = (struct php_sqlite_result*)emalloc(sizeof(*rres));
        memcpy(rres, &res, sizeof(*rres));
 
-next_row:
-       ret = sqlite_step(rres->vm, &rres->ncolumns, &rowdata, &colnames);
-       db->last_err_code = ret;
-
-       switch (ret) {
-               case SQLITE_ROW:
-                       /* 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;
-                               }
-                       }
+       ret = php_sqlite_fetch(rres TSRMLS_CC);
 
-                       rres->nrows++;
-                       goto next_row;
-
-               case SQLITE_DONE:
-                       /* no more rows - lets copy the column names */
-                       rres->col_names = emalloc(rres->ncolumns * sizeof(char *));
-                       for (i = 0; i < rres->ncolumns; i++) {
-                               rres->col_names[i] = estrdup(colnames[i]);
-                       }
-                       break;
-
-               case SQLITE_BUSY:
-               case SQLITE_ERROR:
-               case SQLITE_MISUSE:
-               default:
-                       /* fall through to finalize */
-                       ;
-       }
-
-       ret = sqlite_finalize(rres->vm, &errtext);
        db->last_err_code = ret;
-       rres->vm = NULL;
 
        if (ret != SQLITE_OK) {
-
                real_result_dtor(rres);
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
-               sqlite_freemem(errtext);
-               
                RETURN_FALSE;
        }
        
@@ -968,9 +1016,8 @@ PHP_FUNCTION(sqlite_fetch_array)
        zval *zres;
        struct php_sqlite_result *res;
        int mode = PHPSQLITE_BOTH;
-       int j, ret;
+       int j;
        const char **rowdata, **colnames;
-       char *errtext = NULL;
        zend_bool decode_binary = 1;
 
        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r|lb", &zres, &mode, &decode_binary)) {
@@ -979,47 +1026,16 @@ PHP_FUNCTION(sqlite_fetch_array)
 
        ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
        
+       /* check range of the row */
+       if (res->curr_row >= res->nrows) {
+               /* no more */
+               RETURN_FALSE;
+       }
+       colnames = (const char**)res->col_names;
        if (res->buffered) {
-               /* check range of the row */
-               if (res->curr_row >= res->nrows) {
-                       /* no more */
-                       RETURN_FALSE;
-               }
-
                rowdata = (const char**)&res->table[res->curr_row * res->ncolumns];
-               colnames = (const char**)res->col_names;
-               
        } else {
-               /* unbuffered; we need to manually fetch the row now */
-
-               if (res->vm == NULL) {
-                       /* sanity check */
-                       RETURN_FALSE;
-               }
-               
-               ret = sqlite_step(res->vm, &res->ncolumns, &rowdata, &colnames);
-               switch (ret) {
-                       case SQLITE_ROW:
-                               /* safe to fall through */
-                               break;
-                               
-                       case SQLITE_DONE:
-                               /* no more rows */
-                               RETURN_FALSE;
-                               
-                       case SQLITE_ERROR:
-                       case SQLITE_MISUSE:
-                       case SQLITE_BUSY:
-                       default:
-                               /* error; lets raise the error now */
-                               ret = sqlite_finalize(res->vm, &errtext);
-                               res->vm = NULL;
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", errtext);
-                               sqlite_freemem(errtext);
-                               RETURN_FALSE;
-               }
-
-               /* we got another row */
+               rowdata = (const char**)res->table;
        }
 
        /* now populate the result */
@@ -1037,6 +1053,8 @@ PHP_FUNCTION(sqlite_fetch_array)
                        decoded = (char*)rowdata[j];
                        if (decoded) {
                                decoded_len = strlen(decoded);
+                       } else {
+                               decoded_len = 0;
                        }
                }
                
@@ -1066,6 +1084,10 @@ PHP_FUNCTION(sqlite_fetch_array)
                }
        }
 
+       if (!res->buffered) {
+               /* non buffered: fetch next row */
+               php_sqlite_fetch(res TSRMLS_CC);
+       }
        /* advance the row pointer */
        res->curr_row++;
 }
@@ -1162,13 +1184,7 @@ PHP_FUNCTION(sqlite_num_fields)
 
        ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
 
-       if (res->buffered) {
-               RETURN_LONG(res->ncolumns);
-       } else {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Number of fields not available for unbuffered queries");
-               RETURN_FALSE;
-       }
-       
+       RETURN_LONG(res->ncolumns);
 }
 /* }}} */
 
@@ -1186,17 +1202,12 @@ PHP_FUNCTION(sqlite_field_name)
 
        ZEND_FETCH_RESOURCE(res, struct php_sqlite_result *, &zres, -1, "sqlite result", le_sqlite_result);
 
-       if (res->buffered) {
-               if (field < 0 || field >= res->ncolumns) {
-                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %d out of range", field);
-                       RETURN_FALSE;
-               }
-
-               RETURN_STRING(res->col_names[field], 1);
-       } else {
-               php_error_docref(NULL TSRMLS_CC, E_WARNING, "Field name not available for unbuffered queries");
+       if (field < 0 || field >= res->ncolumns) {
+               php_error_docref(NULL TSRMLS_CC, E_WARNING, "field %d out of range", field);
                RETURN_FALSE;
        }
+
+       RETURN_STRING(res->col_names[field], 1);
 }
 /* }}} */