Back to index

php5  5.3.10
php_ibase_udf.c
Go to the documentation of this file.
00001 /*
00002    +----------------------------------------------------------------------+
00003    | PHP Version 5                                                        |
00004    +----------------------------------------------------------------------+
00005    | Copyright (c) 1997-2012 The PHP Group                                |
00006    +----------------------------------------------------------------------+
00007    | This source file is subject to version 3.01 of the PHP license,      |
00008    | that is bundled with this package in the file LICENSE, and is        |
00009    | available through the world-wide-web at the following url:           |
00010    | http://www.php.net/license/3_01.txt                                  |
00011    | If you did not receive a copy of the PHP license and are unable to   |
00012    | obtain it through the world-wide-web, please send a note to          |
00013    | license@php.net so we can mail you a copy immediately.               |
00014    +----------------------------------------------------------------------+
00015    | Author: Ard Biesheuvel <a.k.biesheuvel@ewi.tudelft.nl>               |
00016    +----------------------------------------------------------------------+
00017  */
00018 
00019 /* $Id: php_ibase_udf.c 321634 2012-01-01 13:15:04Z felipe $ */
00020 
00097 #include "zend.h"
00098 #include "zend_API.h"
00099 
00100 #include "php.h"
00101 #include "php_ini.h"
00102 
00103 #include "ibase.h"
00104 
00105 #define min(a,b) ((a)<(b)?(a):(b))
00106 
00107 #ifdef PHP_WIN32
00108 #define LL_LIT(lit) lit ## I64
00109 #else
00110 #define LL_LIT(lit) lit ## ll
00111 #endif
00112 
00113 #ifdef ZTS
00114 #  include <pthread.h>
00115 
00116 static void ***tsrm_ls;
00117 pthread_mutex_t mtx_res = PTHREAD_MUTEX_INITIALIZER;
00118 
00119 #define LOCK() do { pthread_mutex_lock(&mtx_res); } while (0)
00120 #define UNLOCK() do { pthread_mutex_unlock(&mtx_res); } while (0)
00121 #else
00122 #define LOCK()
00123 #define UNLOCK()
00124 #endif
00125 
00126 #ifdef PHP_EMBED
00127 # include "php_main.h"
00128 # include "sapi/embed/php_embed.h"
00129 
00130 static void __attribute__((constructor)) init()
00131 {
00132        php_embed_init(0, NULL PTSRMLS_CC);
00133 }
00134 
00135 static void __attribute__((destructor)) fini()
00136 {
00137        php_embed_shutdown(TSRMLS_C);
00138 }
00139 
00140 #endif
00141 
00145 void exec_php(BLOBCALLBACK b, PARAMDSC *res, ISC_SHORT *init)
00146 {
00147        int result, remaining = b->blob_total_length, i = 0;
00148        char *code = pemalloc(remaining+1, 1);
00149        ISC_USHORT read;
00150 
00151        for (code[remaining] = '\0'; remaining > 0; remaining -= read)
00152               b->blob_get_segment(b->blob_handle, &code[i++<<16],min(0x10000,remaining), &read); 
00153 
00154        LOCK();
00155 
00156        switch (init && *init) {
00157 
00158               default:
00159 #ifdef PHP_EMBED
00160                      php_request_shutdown(NULL);
00161                      if (FAILURE == (result = php_request_startup(TSRMLS_C))) {
00162                             break;
00163                      }
00164               case 0:
00165 #endif
00166                      /* feed it to the parser */
00167                      zend_first_try {
00168                             result = zend_eval_stringl(code, b->blob_total_length, NULL, "Firebird Embedded PHP engine" TSRMLS_CC);
00169                      } zend_end_try();
00170        }
00171        
00172        UNLOCK();
00173 
00174        free(code);
00175 
00176        res->dsc_dtype = dtype_long;
00177        *(ISC_LONG*)res->dsc_address = (result == SUCCESS);
00178 }
00179 
00180 static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 100000000, 1000000000,
00181        1000000000, LL_LIT(10000000000),LL_LIT(100000000000),LL_LIT(10000000000000),LL_LIT(100000000000000),
00182        LL_LIT(1000000000000000),LL_LIT(1000000000000000),LL_LIT(1000000000000000000) };
00183 
00184 
00185 static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv)
00186 {
00187        do {
00188               zval callback, args[4], *argp[4], return_value;
00189               PARAMVARY *res = (PARAMVARY*)r->dsc_address;
00190               int i;
00191 
00192               INIT_ZVAL(callback);
00193               ZVAL_STRING(&callback,name,0);
00194 
00195               LOCK();
00196               
00197               /* check if the requested function exists */
00198               if (!zend_is_callable(&callback, 0, NULL TSRMLS_CC)) {
00199                      break;
00200               }
00201               
00202               UNLOCK();
00203        
00204               /* create the argument array */
00205               for (i = 0; i < argc; ++i) {
00206 
00207                      INIT_ZVAL(args[i]);
00208                      argp[i] = &args[i];
00209                      
00210                      /* test arg for null */
00211                      if (argv[i]->dsc_flags & DSC_null) {
00212                             ZVAL_NULL(argp[i]);
00213                             continue;
00214                      }
00215 
00216                      switch (argv[i]->dsc_dtype) {
00217                             ISC_INT64 l;
00218                             struct tm t;
00219                             char const *fmt;
00220                             char d[64];
00221 
00222                             case dtype_cstring:
00223                                    ZVAL_STRING(argp[i], (char*)argv[i]->dsc_address,0);
00224                                    break;
00225 
00226                             case dtype_text:
00227                                    ZVAL_STRINGL(argp[i], (char*)argv[i]->dsc_address, argv[i]->dsc_length,0);
00228                                    break;
00229 
00230                             case dtype_varying:
00231                                    ZVAL_STRINGL(argp[i], ((PARAMVARY*)argv[i]->dsc_address)->vary_string,
00232                                           ((PARAMVARY*)argv[i]->dsc_address)->vary_length,0);
00233                                    break;
00234 
00235                             case dtype_short:
00236                                    if (argv[i]->dsc_scale == 0) {
00237                                           ZVAL_LONG(argp[i], *(short*)argv[i]->dsc_address);
00238                                    } else {
00239                                           ZVAL_DOUBLE(argp[i],
00240                                                  ((double)*(short*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]);
00241                                    }
00242                                    break;
00243 
00244                             case dtype_long:
00245                                    if (argv[i]->dsc_scale == 0) {
00246                                           ZVAL_LONG(argp[i], *(ISC_LONG*)argv[i]->dsc_address);
00247                                    } else {
00248                                           ZVAL_DOUBLE(argp[i],
00249                                                  ((double)*(ISC_LONG*)argv[i]->dsc_address)/scales[-argv[i]->dsc_scale]);
00250                                    }
00251                                    break;
00252 
00253                             case dtype_int64:
00254                                    l = *(ISC_INT64*)argv[i]->dsc_address;
00255 
00256                                    if (argv[i]->dsc_scale == 0 && l <= LONG_MAX && l >= LONG_MIN) {
00257                                           ZVAL_LONG(argp[i], (long)l);
00258                                    } else {
00259                                           ZVAL_DOUBLE(argp[i], ((double)l)/scales[-argv[i]->dsc_scale]);
00260                                    }
00261                                    break;
00262 
00263                             case dtype_real:
00264                                    ZVAL_DOUBLE(argp[i], *(float*)argv[i]->dsc_address);
00265                                    break;
00266 
00267                             case dtype_double:
00268                                    ZVAL_DOUBLE(argp[i], *(double*)argv[i]->dsc_address);
00269                                    break;
00270 
00271                             case dtype_sql_date:
00272                                    isc_decode_sql_date((ISC_DATE*)argv[i]->dsc_address, &t);
00273                                    ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.dateformat"), &t),1); 
00274                                    break;
00275 
00276                             case dtype_sql_time:
00277                                    isc_decode_sql_time((ISC_TIME*)argv[i]->dsc_address, &t);
00278                                    ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timeformat"), &t),1); 
00279                                    break;
00280 
00281                             case dtype_timestamp:
00282                                    isc_decode_timestamp((ISC_TIMESTAMP*)argv[i]->dsc_address, &t);
00283                                    ZVAL_STRINGL(argp[i], d, strftime(d, sizeof(d), INI_STR("ibase.timestampformat"), &t),1); 
00284                                    break;
00285                      }
00286               }
00287 
00288               LOCK();
00289 
00290               /* now call the function */
00291               if (FAILURE == call_user_function(EG(function_table), NULL,
00292                             &callback, &return_value, argc, argp TSRMLS_CC)) {
00293                      UNLOCK();
00294                      break;
00295               }
00296               
00297               UNLOCK();
00298 
00299               for (i = 0; i < argc; ++i) {
00300                      switch (argv[i]->dsc_dtype) {
00301                             case dtype_sql_date:
00302                             case dtype_sql_time:
00303                             case dtype_timestamp:
00304                                    zval_dtor(argp[i]);
00305                                    
00306                      }
00307               }
00308 
00309               /* return whatever type we got back from the callback: let DB handle conversion */
00310               switch (Z_TYPE(return_value)) {
00311 
00312                      case IS_LONG:
00313                             r->dsc_dtype = dtype_long;
00314                             *(long*)r->dsc_address = Z_LVAL(return_value);
00315                             r->dsc_length = sizeof(long);
00316                             break;
00317 
00318                      case IS_DOUBLE:
00319                             r->dsc_dtype = dtype_double;
00320                             *(double*)r->dsc_address = Z_DVAL(return_value);
00321                             r->dsc_length = sizeof(double);
00322                             break;
00323 
00324                      case IS_NULL:
00325                             r->dsc_flags |= DSC_null;
00326                             break;
00327 
00328                      default:
00329                             convert_to_string(&return_value);
00330 
00331                      case IS_STRING:
00332                             r->dsc_dtype = dtype_varying;
00333                             memcpy(res->vary_string, Z_STRVAL(return_value),
00334                                    (res->vary_length = min(r->dsc_length-2,Z_STRLEN(return_value))));
00335                             r->dsc_length = res->vary_length+2;
00336                             break;
00337               }
00338                             
00339               zval_dtor(&return_value);
00340 
00341               return;
00342 
00343        } while (0);
00344        
00349        LOCK();
00350        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error calling function '%s' from database", name);
00351        UNLOCK();
00352 }
00353 
00354 
00355 /* Entry points for the DB engine */
00356 
00357 void udf_call_php1(char *name, PARAMDSC *r, PARAMDSC *arg1)
00358 {
00359        PARAMDSC *args[1] = { arg1 };
00360        call_php(name, r, 1, args);
00361 }
00362 
00363 void udf_call_php2(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2)
00364 {
00365        PARAMDSC *args[2] = { arg1, arg2 };
00366        call_php(name, r, 2, args);
00367 }
00368 
00369 void udf_call_php3(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3)
00370 {
00371        PARAMDSC *args[3] = { arg1, arg2, arg3 };
00372        call_php(name, r, 3, args);
00373 }
00374 
00375 void udf_call_php4(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, 
00376        PARAMDSC *arg4)
00377 {
00378        PARAMDSC *args[4] = { arg1, arg2, arg3, arg4 };
00379        call_php(name, r, 4, args);
00380 }
00381 
00382 void udf_call_php5(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, 
00383        PARAMDSC *arg4, PARAMDSC *arg5)
00384 {
00385        PARAMDSC *args[5] = { arg1, arg2, arg3, arg4, arg5 };
00386        call_php(name, r, 5, args);
00387 }
00388 
00389 void udf_call_php6(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, 
00390        PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6)
00391 {
00392        PARAMDSC *args[6] = { arg1, arg2, arg3, arg4, arg5, arg6 };
00393        call_php(name, r, 6, args);
00394 }
00395 
00396 void udf_call_php7(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, 
00397        PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6, PARAMDSC *arg7)
00398 {
00399        PARAMDSC *args[7] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7 };
00400        call_php(name, r, 7, args);
00401 }
00402 
00403 void udf_call_php8(char *name, PARAMDSC *r, PARAMDSC *arg1, PARAMDSC *arg2, PARAMDSC *arg3, 
00404        PARAMDSC *arg4, PARAMDSC *arg5, PARAMDSC *arg6, PARAMDSC *arg7, PARAMDSC *arg8)
00405 {
00406        PARAMDSC *args[8] = { arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8 };
00407        call_php(name, r, 8, args);
00408 }
00409