Annotation of embedaddon/php/ext/pdo_sqlite/sqlite_driver.c, revision 1.1.1.4

1.1       misho       1: /*
                      2:   +----------------------------------------------------------------------+
                      3:   | PHP Version 5                                                        |
                      4:   +----------------------------------------------------------------------+
1.1.1.4 ! misho       5:   | Copyright (c) 1997-2014 The PHP Group                                |
1.1       misho       6:   +----------------------------------------------------------------------+
                      7:   | This source file is subject to version 3.01 of the PHP license,      |
                      8:   | that is bundled with this package in the file LICENSE, and is        |
                      9:   | available through the world-wide-web at the following url:           |
                     10:   | http://www.php.net/license/3_01.txt                                  |
                     11:   | If you did not receive a copy of the PHP license and are unable to   |
                     12:   | obtain it through the world-wide-web, please send a note to          |
                     13:   | license@php.net so we can mail you a copy immediately.               |
                     14:   +----------------------------------------------------------------------+
                     15:   | Author: Wez Furlong <wez@php.net>                                    |
                     16:   +----------------------------------------------------------------------+
                     17: */
                     18: 
1.1.1.2   misho      19: /* $Id$ */
1.1       misho      20: 
                     21: #ifdef HAVE_CONFIG_H
                     22: #include "config.h"
                     23: #endif
                     24: 
                     25: #include "php.h"
                     26: #include "php_ini.h"
                     27: #include "ext/standard/info.h"
                     28: #include "pdo/php_pdo.h"
                     29: #include "pdo/php_pdo_driver.h"
                     30: #include "php_pdo_sqlite.h"
                     31: #include "php_pdo_sqlite_int.h"
                     32: #include "zend_exceptions.h"
                     33: 
                     34: int _pdo_sqlite_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, const char *file, int line TSRMLS_DC) /* {{{ */
                     35: {
                     36:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                     37:        pdo_error_type *pdo_err = stmt ? &stmt->error_code : &dbh->error_code;
                     38:        pdo_sqlite_error_info *einfo = &H->einfo;
                     39: 
                     40:        einfo->errcode = sqlite3_errcode(H->db);
                     41:        einfo->file = file;
                     42:        einfo->line = line;
                     43: 
                     44:        if (einfo->errcode != SQLITE_OK) {
                     45:                if (einfo->errmsg) {
                     46:                        pefree(einfo->errmsg, dbh->is_persistent);
                     47:                }
                     48:                einfo->errmsg = pestrdup((char*)sqlite3_errmsg(H->db), dbh->is_persistent);
                     49:        } else { /* no error */
                     50:                strncpy(*pdo_err, PDO_ERR_NONE, sizeof(PDO_ERR_NONE));
                     51:                return 0;
                     52:        }
                     53:        switch (einfo->errcode) {
                     54:                case SQLITE_NOTFOUND:
                     55:                        strncpy(*pdo_err, "42S02", sizeof("42S02"));
                     56:                        break;  
                     57: 
                     58:                case SQLITE_INTERRUPT:
                     59:                        strncpy(*pdo_err, "01002", sizeof("01002"));
                     60:                        break;
                     61: 
                     62:                case SQLITE_NOLFS:
                     63:                        strncpy(*pdo_err, "HYC00", sizeof("HYC00"));
                     64:                        break;
                     65: 
                     66:                case SQLITE_TOOBIG:
                     67:                        strncpy(*pdo_err, "22001", sizeof("22001"));
                     68:                        break;
                     69:        
                     70:                case SQLITE_CONSTRAINT:
                     71:                        strncpy(*pdo_err, "23000", sizeof("23000"));
                     72:                        break;
                     73: 
                     74:                case SQLITE_ERROR:
                     75:                default:
                     76:                        strncpy(*pdo_err, "HY000", sizeof("HY000"));
                     77:                        break;
                     78:        }
                     79: 
                     80:        if (!dbh->methods) {
                     81:                zend_throw_exception_ex(php_pdo_get_exception(), einfo->errcode TSRMLS_CC, "SQLSTATE[%s] [%d] %s",
                     82:                                *pdo_err, einfo->errcode, einfo->errmsg);
                     83:        }
                     84:        
                     85:        return einfo->errcode;
                     86: }
                     87: /* }}} */
                     88: 
                     89: static int pdo_sqlite_fetch_error_func(pdo_dbh_t *dbh, pdo_stmt_t *stmt, zval *info TSRMLS_DC)
                     90: {
                     91:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                     92:        pdo_sqlite_error_info *einfo = &H->einfo;
                     93: 
                     94:        if (einfo->errcode) {
                     95:                add_next_index_long(info, einfo->errcode);
                     96:                add_next_index_string(info, einfo->errmsg, 1);
                     97:        }
                     98: 
                     99:        return 1;
                    100: }
                    101: 
                    102: static void pdo_sqlite_cleanup_callbacks(pdo_sqlite_db_handle *H TSRMLS_DC)
                    103: {
                    104:        struct pdo_sqlite_func *func;
                    105: 
                    106:        while (H->funcs) {
                    107:                func = H->funcs;
                    108:                H->funcs = func->next;
                    109: 
                    110:                if (H->db) {
                    111:                        /* delete the function from the handle */
                    112:                        sqlite3_create_function(H->db,
                    113:                                func->funcname,
                    114:                                func->argc,
                    115:                                SQLITE_UTF8,
                    116:                                func,
                    117:                                NULL, NULL, NULL);
                    118:                }
                    119: 
                    120:                efree((char*)func->funcname);
                    121:                if (func->func) {
                    122:                        zval_ptr_dtor(&func->func);
                    123:                }
                    124:                if (func->step) {
                    125:                        zval_ptr_dtor(&func->step);
                    126:                }
                    127:                if (func->fini) {
                    128:                        zval_ptr_dtor(&func->fini);
                    129:                }
                    130:                efree(func);
                    131:        }
1.1.1.2   misho     132: 
                    133:        while (H->collations) {
                    134:                struct pdo_sqlite_collation *collation;
                    135:                collation = H->collations;
                    136:                H->collations = collation->next;
                    137: 
                    138:                if (H->db) {
                    139:                        /* delete the collation from the handle */
                    140:                        sqlite3_create_collation(H->db,
                    141:                                collation->name,
                    142:                                SQLITE_UTF8,
                    143:                                collation,
                    144:                                NULL);
                    145:                }
                    146: 
                    147:                efree((char*)collation->name);
                    148:                if (collation->callback) {
                    149:                        zval_ptr_dtor(&collation->callback);
                    150:                }
                    151:                efree(collation);
                    152:        }
1.1       misho     153: }
                    154: 
                    155: static int sqlite_handle_closer(pdo_dbh_t *dbh TSRMLS_DC) /* {{{ */
                    156: {
                    157:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    158:        
                    159:        if (H) {
                    160:                pdo_sqlite_error_info *einfo = &H->einfo;
                    161: 
                    162:                pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
                    163:                if (H->db) {
                    164:                        sqlite3_close(H->db);
                    165:                        H->db = NULL;
                    166:                }
                    167:                if (einfo->errmsg) {
                    168:                        pefree(einfo->errmsg, dbh->is_persistent);
                    169:                        einfo->errmsg = NULL;
                    170:                }
                    171:                pefree(H, dbh->is_persistent);
                    172:                dbh->driver_data = NULL;
                    173:        }
                    174:        return 0;
                    175: }
                    176: /* }}} */
                    177: 
                    178: static int sqlite_handle_preparer(pdo_dbh_t *dbh, const char *sql, long sql_len, pdo_stmt_t *stmt, zval *driver_options TSRMLS_DC)
                    179: {
                    180:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    181:        pdo_sqlite_stmt *S = ecalloc(1, sizeof(pdo_sqlite_stmt));
                    182:        int i;
                    183:        const char *tail;
                    184: 
                    185:        S->H = H;
                    186:        stmt->driver_data = S;
                    187:        stmt->methods = &sqlite_stmt_methods;
                    188:        stmt->supports_placeholders = PDO_PLACEHOLDER_POSITIONAL|PDO_PLACEHOLDER_NAMED;
                    189: 
                    190:        if (PDO_CURSOR_FWDONLY != pdo_attr_lval(driver_options, PDO_ATTR_CURSOR, PDO_CURSOR_FWDONLY TSRMLS_CC)) {
                    191:                H->einfo.errcode = SQLITE_ERROR;
                    192:                pdo_sqlite_error(dbh);
                    193:                return 0;
                    194:        }
                    195: 
                    196:        i = sqlite3_prepare(H->db, sql, sql_len, &S->stmt, &tail);
                    197:        if (i == SQLITE_OK) {
                    198:                return 1;
                    199:        }
                    200: 
                    201:        pdo_sqlite_error(dbh);
                    202: 
                    203:        return 0;
                    204: }
                    205: 
                    206: static long sqlite_handle_doer(pdo_dbh_t *dbh, const char *sql, long sql_len TSRMLS_DC)
                    207: {
                    208:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    209:        char *errmsg = NULL;
                    210: 
                    211:        if (sqlite3_exec(H->db, sql, NULL, NULL, &errmsg) != SQLITE_OK) {
                    212:                pdo_sqlite_error(dbh);
                    213:                if (errmsg)
                    214:                        sqlite3_free(errmsg);
                    215: 
                    216:                return -1;
                    217:        } else {
                    218:                return sqlite3_changes(H->db);
                    219:        }
                    220: }
                    221: 
                    222: static char *pdo_sqlite_last_insert_id(pdo_dbh_t *dbh, const char *name, unsigned int *len TSRMLS_DC)
                    223: {
                    224:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    225:        char *id;
                    226:        
                    227:        id = php_pdo_int64_to_str(sqlite3_last_insert_rowid(H->db) TSRMLS_CC);
                    228:        *len = strlen(id);
                    229:        return id;
                    230: }
                    231: 
                    232: /* NB: doesn't handle binary strings... use prepared stmts for that */
                    233: static int sqlite_handle_quoter(pdo_dbh_t *dbh, const char *unquoted, int unquotedlen, char **quoted, int *quotedlen, enum pdo_param_type paramtype  TSRMLS_DC)
                    234: {
                    235:        *quoted = safe_emalloc(2, unquotedlen, 3);
                    236:        sqlite3_snprintf(2*unquotedlen + 3, *quoted, "'%q'", unquoted);
                    237:        *quotedlen = strlen(*quoted);
                    238:        return 1;
                    239: }
                    240: 
                    241: static int sqlite_handle_begin(pdo_dbh_t *dbh TSRMLS_DC)
                    242: {
                    243:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    244:        char *errmsg = NULL;
                    245: 
                    246:        if (sqlite3_exec(H->db, "BEGIN", NULL, NULL, &errmsg) != SQLITE_OK) {
                    247:                pdo_sqlite_error(dbh);
                    248:                if (errmsg)
                    249:                        sqlite3_free(errmsg);
                    250:                return 0;
                    251:        }
                    252:        return 1;
                    253: }
                    254: 
                    255: static int sqlite_handle_commit(pdo_dbh_t *dbh TSRMLS_DC)
                    256: {
                    257:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    258:        char *errmsg = NULL;
                    259: 
                    260:        if (sqlite3_exec(H->db, "COMMIT", NULL, NULL, &errmsg) != SQLITE_OK) {
                    261:                pdo_sqlite_error(dbh);
                    262:                if (errmsg)
                    263:                        sqlite3_free(errmsg);
                    264:                return 0;
                    265:        }
                    266:        return 1;
                    267: }
                    268: 
                    269: static int sqlite_handle_rollback(pdo_dbh_t *dbh TSRMLS_DC)
                    270: {
                    271:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    272:        char *errmsg = NULL;
                    273: 
                    274:        if (sqlite3_exec(H->db, "ROLLBACK", NULL, NULL, &errmsg) != SQLITE_OK) {
                    275:                pdo_sqlite_error(dbh);
                    276:                if (errmsg)
                    277:                        sqlite3_free(errmsg);
                    278:                return 0;
                    279:        }
                    280:        return 1;
                    281: }
                    282: 
                    283: static int pdo_sqlite_get_attribute(pdo_dbh_t *dbh, long attr, zval *return_value TSRMLS_DC)
                    284: {
                    285:        switch (attr) {
                    286:                case PDO_ATTR_CLIENT_VERSION:
                    287:                case PDO_ATTR_SERVER_VERSION:
                    288:                        ZVAL_STRING(return_value, (char *)sqlite3_libversion(), 1);
                    289:                        break;
                    290:                
                    291:                default:
                    292:                        return 0;       
                    293:        }
                    294: 
                    295:        return 1;
                    296: }
                    297: 
                    298: static int pdo_sqlite_set_attr(pdo_dbh_t *dbh, long attr, zval *val TSRMLS_DC)
                    299: {
                    300:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    301: 
                    302:        switch (attr) {
                    303:                case PDO_ATTR_TIMEOUT:
                    304:                        convert_to_long(val);
                    305:                        sqlite3_busy_timeout(H->db, Z_LVAL_P(val) * 1000);
                    306:                        return 1;
                    307:        }
                    308:        return 0;
                    309: }
                    310: 
                    311: static int do_callback(struct pdo_sqlite_fci *fc, zval *cb,
                    312:                int argc, sqlite3_value **argv, sqlite3_context *context,
                    313:                int is_agg TSRMLS_DC)
                    314: {
                    315:        zval ***zargs = NULL;
                    316:        zval *retval = NULL;
                    317:        int i;
                    318:        int ret;
                    319:        int fake_argc;
                    320:        zval **agg_context = NULL;
                    321:        
                    322:        if (is_agg) {
                    323:                is_agg = 2;
                    324:        }
                    325:        
                    326:        fake_argc = argc + is_agg;
                    327:        
                    328:        fc->fci.size = sizeof(fc->fci);
                    329:        fc->fci.function_table = EG(function_table);
                    330:        fc->fci.function_name = cb;
                    331:        fc->fci.symbol_table = NULL;
                    332:        fc->fci.object_ptr = NULL;
                    333:        fc->fci.retval_ptr_ptr = &retval;
                    334:        fc->fci.param_count = fake_argc;
                    335:        
                    336:        /* build up the params */
                    337: 
                    338:        if (fake_argc) {
                    339:                zargs = (zval ***)safe_emalloc(fake_argc, sizeof(zval **), 0);
                    340:        }
                    341: 
                    342:        if (is_agg) {
                    343:                /* summon the aggregation context */
                    344:                agg_context = (zval**)sqlite3_aggregate_context(context, sizeof(zval*));
                    345:                if (!*agg_context) {
                    346:                        MAKE_STD_ZVAL(*agg_context);
                    347:                        ZVAL_NULL(*agg_context);
                    348:                }
                    349:                zargs[0] = agg_context;
                    350: 
                    351:                zargs[1] = emalloc(sizeof(zval*));
                    352:                MAKE_STD_ZVAL(*zargs[1]);
                    353:                ZVAL_LONG(*zargs[1], sqlite3_aggregate_count(context));
                    354:        }
                    355:        
                    356:        for (i = 0; i < argc; i++) {
                    357:                zargs[i + is_agg] = emalloc(sizeof(zval *));
                    358:                MAKE_STD_ZVAL(*zargs[i + is_agg]);
                    359: 
                    360:                /* get the value */
                    361:                switch (sqlite3_value_type(argv[i])) {
                    362:                        case SQLITE_INTEGER:
                    363:                                ZVAL_LONG(*zargs[i + is_agg], sqlite3_value_int(argv[i]));
                    364:                                break;
                    365: 
                    366:                        case SQLITE_FLOAT:
                    367:                                ZVAL_DOUBLE(*zargs[i + is_agg], sqlite3_value_double(argv[i]));
                    368:                                break;
                    369: 
                    370:                        case SQLITE_NULL:
                    371:                                ZVAL_NULL(*zargs[i + is_agg]);
                    372:                                break;
                    373: 
                    374:                        case SQLITE_BLOB:
                    375:                        case SQLITE3_TEXT:
                    376:                        default:
                    377:                                ZVAL_STRINGL(*zargs[i + is_agg], (char*)sqlite3_value_text(argv[i]),
                    378:                                                sqlite3_value_bytes(argv[i]), 1);
                    379:                                break;
                    380:                }
                    381:        }
                    382: 
                    383: 
                    384:        fc->fci.params = zargs;
                    385: 
                    386: 
                    387:        if ((ret = zend_call_function(&fc->fci, &fc->fcc TSRMLS_CC)) == FAILURE) {
                    388:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
                    389:        }
                    390: 
                    391:        /* clean up the params */
                    392:        if (zargs) {
                    393:                for (i = is_agg; i < fake_argc; i++) {
                    394:                        zval_ptr_dtor(zargs[i]);
                    395:                        efree(zargs[i]);
                    396:                }
                    397:                if (is_agg) {
                    398:                        zval_ptr_dtor(zargs[1]);
                    399:                        efree(zargs[1]);
                    400:                }
                    401:                efree(zargs);
                    402:        }
                    403: 
                    404:        if (!is_agg || !argv) {
                    405:                /* only set the sqlite return value if we are a scalar function,
                    406:                 * or if we are finalizing an aggregate */
                    407:                if (retval) {
                    408:                        switch (Z_TYPE_P(retval)) {
                    409:                                case IS_LONG:
                    410:                                        sqlite3_result_int(context, Z_LVAL_P(retval));
                    411:                                        break;
                    412: 
                    413:                                case IS_NULL:
                    414:                                        sqlite3_result_null(context);
                    415:                                        break;
                    416: 
                    417:                                case IS_DOUBLE:
                    418:                                        sqlite3_result_double(context, Z_DVAL_P(retval));
                    419:                                        break;
                    420: 
                    421:                                default:
                    422:                                        convert_to_string_ex(&retval);
                    423:                                        sqlite3_result_text(context, Z_STRVAL_P(retval),
                    424:                                                Z_STRLEN_P(retval), SQLITE_TRANSIENT);
                    425:                                        break;
                    426:                        }
                    427:                } else {
                    428:                        sqlite3_result_error(context, "failed to invoke callback", 0);
                    429:                }
                    430: 
                    431:                if (agg_context) {
                    432:                        zval_ptr_dtor(agg_context);
                    433:                }
                    434:        } else {
                    435:                /* we're stepping in an aggregate; the return value goes into
                    436:                 * the context */
                    437:                if (agg_context) {
                    438:                        zval_ptr_dtor(agg_context);
                    439:                }
                    440:                if (retval) {
                    441:                        *agg_context = retval;
                    442:                        retval = NULL;
                    443:                } else {
                    444:                        *agg_context = NULL;
                    445:                }
                    446:        }
                    447: 
                    448:        if (retval) {
                    449:                zval_ptr_dtor(&retval);
                    450:        }
                    451: 
                    452:        return ret;
                    453: }
                    454: 
                    455: static void php_sqlite3_func_callback(sqlite3_context *context, int argc,
                    456:        sqlite3_value **argv)
                    457: {
                    458:        struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
                    459:        TSRMLS_FETCH();
                    460: 
                    461:        do_callback(&func->afunc, func->func, argc, argv, context, 0 TSRMLS_CC);
                    462: }
                    463: 
                    464: static void php_sqlite3_func_step_callback(sqlite3_context *context, int argc,
                    465:        sqlite3_value **argv)
                    466: {
                    467:        struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
                    468:        TSRMLS_FETCH();
                    469: 
                    470:        do_callback(&func->astep, func->step, argc, argv, context, 1 TSRMLS_CC);
                    471: }
                    472: 
                    473: static void php_sqlite3_func_final_callback(sqlite3_context *context)
                    474: {
                    475:        struct pdo_sqlite_func *func = (struct pdo_sqlite_func*)sqlite3_user_data(context);
                    476:        TSRMLS_FETCH();
                    477: 
                    478:        do_callback(&func->afini, func->fini, 0, NULL, context, 1 TSRMLS_CC);
                    479: }
                    480: 
1.1.1.2   misho     481: static int php_sqlite3_collation_callback(void *context,
                    482:        int string1_len, const void *string1,
                    483:        int string2_len, const void *string2)
                    484: {
                    485:        int ret;
                    486:        zval *zstring1, *zstring2;
                    487:        zval **zargs[2];
                    488:        zval *retval = NULL;
                    489:        struct pdo_sqlite_collation *collation = (struct pdo_sqlite_collation*) context;
                    490:        TSRMLS_FETCH();
                    491: 
                    492:        collation->fc.fci.size = sizeof(collation->fc.fci);
                    493:        collation->fc.fci.function_table = EG(function_table);
                    494:        collation->fc.fci.function_name = collation->callback;
                    495:        collation->fc.fci.symbol_table = NULL;
                    496:        collation->fc.fci.object_ptr = NULL;
                    497:        collation->fc.fci.retval_ptr_ptr = &retval;
                    498: 
                    499:        // Prepare the arguments.
                    500:        MAKE_STD_ZVAL(zstring1);
                    501:        ZVAL_STRINGL(zstring1, (char *) string1, string1_len, 1);
                    502:        zargs[0] = &zstring1;
                    503:        MAKE_STD_ZVAL(zstring2);
                    504:        ZVAL_STRINGL(zstring2, (char *) string2, string2_len, 1);
                    505:        zargs[1] = &zstring2;
                    506:        collation->fc.fci.param_count = 2;
                    507:        collation->fc.fci.params = zargs;
                    508: 
                    509:        if ((ret = zend_call_function(&collation->fc.fci, &collation->fc.fcc TSRMLS_CC)) == FAILURE) {
                    510:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "An error occurred while invoking the callback");
                    511:        }
                    512:        else if (retval) {
                    513:                if (Z_TYPE_P(retval) != IS_LONG) {
                    514:                        convert_to_long_ex(&retval);
                    515:                }
                    516:                ret = 0;
                    517:                if (Z_LVAL_P(retval) > 0) {
                    518:                        ret = 1;
                    519:                }
                    520:                else if (Z_LVAL_P(retval) < 0) {
                    521:                        ret = -1;
                    522:                }
                    523:                zval_ptr_dtor(&retval);
                    524:        }
                    525: 
                    526:        zval_ptr_dtor(zargs[0]);
                    527:        zval_ptr_dtor(zargs[1]);
                    528: 
                    529:        return ret;
                    530: }
                    531: 
1.1       misho     532: /* {{{ bool SQLite::sqliteCreateFunction(string name, mixed callback [, int argcount])
                    533:    Registers a UDF with the sqlite db handle */
                    534: static PHP_METHOD(SQLite, sqliteCreateFunction)
                    535: {
                    536:        struct pdo_sqlite_func *func;
                    537:        zval *callback;
                    538:        char *func_name;
                    539:        int func_name_len;
                    540:        long argc = -1;
                    541:        char *cbname = NULL;
                    542:        pdo_dbh_t *dbh;
                    543:        pdo_sqlite_db_handle *H;
                    544:        int ret;
                    545: 
                    546:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l",
                    547:                        &func_name, &func_name_len, &callback, &argc)) {
                    548:                RETURN_FALSE;
                    549:        }
                    550:        
                    551:        dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
                    552:        PDO_CONSTRUCT_CHECK;
                    553: 
                    554:        if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
                    555:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
                    556:                efree(cbname);
                    557:                RETURN_FALSE;
                    558:        }
                    559:        efree(cbname);
                    560:        
                    561:        H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    562: 
                    563:        func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
                    564: 
                    565:        ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
                    566:                        func, php_sqlite3_func_callback, NULL, NULL);
                    567:        if (ret == SQLITE_OK) {
                    568:                func->funcname = estrdup(func_name);
                    569:                
                    570:                MAKE_STD_ZVAL(func->func);
                    571:                MAKE_COPY_ZVAL(&callback, func->func);
                    572:                
                    573:                func->argc = argc;
                    574: 
                    575:                func->next = H->funcs;
                    576:                H->funcs = func;
                    577: 
                    578:                RETURN_TRUE;
                    579:        }
                    580: 
                    581:        efree(func);
                    582:        RETURN_FALSE;
                    583: }
                    584: /* }}} */
                    585: 
                    586: /* {{{ bool SQLite::sqliteCreateAggregate(string name, mixed step, mixed fini [, int argcount])
                    587:    Registers a UDF with the sqlite db handle */
                    588: 
                    589: /* The step function should have the prototype:
                    590:    mixed step(mixed $context, int $rownumber, $value [, $value2 [, ...]])
                    591: 
                    592:    $context will be null for the first row; on subsequent rows it will have
                    593:    the value that was previously returned from the step function; you should
                    594:    use this to maintain state for the aggregate.
                    595: 
                    596:    The fini function should have the prototype:
                    597:    mixed fini(mixed $context, int $rownumber)
                    598: 
                    599:    $context will hold the return value from the very last call to the step function.
                    600:    rownumber will hold the number of rows over which the aggregate was performed.
                    601:    The return value of this function will be used as the return value for this
                    602:    aggregate UDF.
                    603: */
                    604:    
                    605: static PHP_METHOD(SQLite, sqliteCreateAggregate)
                    606: {
                    607:        struct pdo_sqlite_func *func;
                    608:        zval *step_callback, *fini_callback;
                    609:        char *func_name;
                    610:        int func_name_len;
                    611:        long argc = -1;
                    612:        char *cbname = NULL;
                    613:        pdo_dbh_t *dbh;
                    614:        pdo_sqlite_db_handle *H;
                    615:        int ret;
                    616: 
                    617:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l",
                    618:                        &func_name, &func_name_len, &step_callback, &fini_callback, &argc)) {
                    619:                RETURN_FALSE;
                    620:        }
                    621:        
                    622:        dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
                    623:        PDO_CONSTRUCT_CHECK;
                    624: 
                    625:        if (!zend_is_callable(step_callback, 0, &cbname TSRMLS_CC)) {
                    626:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
                    627:                efree(cbname);
                    628:                RETURN_FALSE;
                    629:        }
                    630:        efree(cbname);
                    631:        if (!zend_is_callable(fini_callback, 0, &cbname TSRMLS_CC)) {
                    632:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
                    633:                efree(cbname);
                    634:                RETURN_FALSE;
                    635:        }
                    636:        efree(cbname);
                    637:        
                    638:        H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    639: 
                    640:        func = (struct pdo_sqlite_func*)ecalloc(1, sizeof(*func));
                    641: 
                    642:        ret = sqlite3_create_function(H->db, func_name, argc, SQLITE_UTF8,
                    643:                        func, NULL, php_sqlite3_func_step_callback, php_sqlite3_func_final_callback);
                    644:        if (ret == SQLITE_OK) {
                    645:                func->funcname = estrdup(func_name);
                    646:                
                    647:                MAKE_STD_ZVAL(func->step);
                    648:                MAKE_COPY_ZVAL(&step_callback, func->step);
                    649: 
                    650:                MAKE_STD_ZVAL(func->fini);
                    651:                MAKE_COPY_ZVAL(&fini_callback, func->fini);
                    652:                
                    653:                func->argc = argc;
                    654: 
                    655:                func->next = H->funcs;
                    656:                H->funcs = func;
                    657: 
                    658:                RETURN_TRUE;
                    659:        }
                    660: 
                    661:        efree(func);
                    662:        RETURN_FALSE;
                    663: }
                    664: /* }}} */
1.1.1.2   misho     665: 
                    666: /* {{{ bool SQLite::sqliteCreateCollation(string name, mixed callback)
                    667:    Registers a collation with the sqlite db handle */
                    668: static PHP_METHOD(SQLite, sqliteCreateCollation)
                    669: {
                    670:        struct pdo_sqlite_collation *collation;
                    671:        zval *callback;
                    672:        char *collation_name;
                    673:        int collation_name_len;
                    674:        char *cbname = NULL;
                    675:        pdo_dbh_t *dbh;
                    676:        pdo_sqlite_db_handle *H;
                    677:        int ret;
                    678: 
                    679:        if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz",
                    680:                &collation_name, &collation_name_len, &callback)) {
                    681:                RETURN_FALSE;
                    682:        }
                    683: 
                    684:        dbh = zend_object_store_get_object(getThis() TSRMLS_CC);
                    685:        PDO_CONSTRUCT_CHECK;
                    686: 
                    687:        if (!zend_is_callable(callback, 0, &cbname TSRMLS_CC)) {
                    688:                php_error_docref(NULL TSRMLS_CC, E_WARNING, "function '%s' is not callable", cbname);
                    689:                efree(cbname);
                    690:                RETURN_FALSE;
                    691:        }
                    692:        efree(cbname);
                    693: 
                    694:        H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    695: 
                    696:        collation = (struct pdo_sqlite_collation*)ecalloc(1, sizeof(*collation));
                    697: 
                    698:        ret = sqlite3_create_collation(H->db, collation_name, SQLITE_UTF8, collation, php_sqlite3_collation_callback);
                    699:        if (ret == SQLITE_OK) {
                    700:                collation->name = estrdup(collation_name);
                    701: 
                    702:                MAKE_STD_ZVAL(collation->callback);
                    703:                MAKE_COPY_ZVAL(&callback, collation->callback);
                    704: 
                    705:                collation->next = H->collations;
                    706:                H->collations = collation;
                    707: 
                    708:                RETURN_TRUE;
                    709:        }
                    710: 
                    711:        efree(collation);
                    712:        RETURN_FALSE;
                    713: }
                    714: /* }}} */
                    715: 
1.1       misho     716: static const zend_function_entry dbh_methods[] = {
                    717:        PHP_ME(SQLite, sqliteCreateFunction, NULL, ZEND_ACC_PUBLIC)
                    718:        PHP_ME(SQLite, sqliteCreateAggregate, NULL, ZEND_ACC_PUBLIC)
1.1.1.2   misho     719:        PHP_ME(SQLite, sqliteCreateCollation, NULL, ZEND_ACC_PUBLIC)
1.1       misho     720:        PHP_FE_END
                    721: };
                    722: 
                    723: static const zend_function_entry *get_driver_methods(pdo_dbh_t *dbh, int kind TSRMLS_DC)
                    724: {
                    725:        switch (kind) {
                    726:                case PDO_DBH_DRIVER_METHOD_KIND_DBH:
                    727:                        return dbh_methods;
                    728: 
                    729:                default:
                    730:                        return NULL;
                    731:        }
                    732: }
                    733: 
                    734: static void pdo_sqlite_request_shutdown(pdo_dbh_t *dbh TSRMLS_DC)
                    735: {
                    736:        pdo_sqlite_db_handle *H = (pdo_sqlite_db_handle *)dbh->driver_data;
                    737:        /* unregister functions, so that they don't linger for the next
                    738:         * request */
                    739:        if (H) {
                    740:                pdo_sqlite_cleanup_callbacks(H TSRMLS_CC);
                    741:        }
                    742: }
                    743: 
                    744: static struct pdo_dbh_methods sqlite_methods = {
                    745:        sqlite_handle_closer,
                    746:        sqlite_handle_preparer,
                    747:        sqlite_handle_doer,
                    748:        sqlite_handle_quoter,
                    749:        sqlite_handle_begin,
                    750:        sqlite_handle_commit,
                    751:        sqlite_handle_rollback,
                    752:        pdo_sqlite_set_attr,
                    753:        pdo_sqlite_last_insert_id,
                    754:        pdo_sqlite_fetch_error_func,
                    755:        pdo_sqlite_get_attribute,
                    756:        NULL,   /* check_liveness: not needed */
                    757:        get_driver_methods,
                    758:        pdo_sqlite_request_shutdown
                    759: };
                    760: 
                    761: static char *make_filename_safe(const char *filename TSRMLS_DC)
                    762: {
1.1.1.3   misho     763:        if (*filename && memcmp(filename, ":memory:", sizeof(":memory:"))) {
1.1       misho     764:                char *fullpath = expand_filepath(filename, NULL TSRMLS_CC);
                    765: 
                    766:                if (!fullpath) {
                    767:                        return NULL;
                    768:                }
                    769: 
                    770:                if (php_check_open_basedir(fullpath TSRMLS_CC)) {
                    771:                        efree(fullpath);
                    772:                        return NULL;
                    773:                }
                    774:                return fullpath;
                    775:        }
                    776:        return estrdup(filename);
                    777: }
                    778: 
                    779: static int authorizer(void *autharg, int access_type, const char *arg3, const char *arg4,
                    780:                const char *arg5, const char *arg6)
                    781: {
                    782:        char *filename;
                    783:        switch (access_type) {
                    784:                case SQLITE_COPY: {
                    785:                        TSRMLS_FETCH();
                    786:                        filename = make_filename_safe(arg4 TSRMLS_CC);
                    787:                        if (!filename) {
                    788:                                return SQLITE_DENY;
                    789:                        }
                    790:                        efree(filename);
                    791:                        return SQLITE_OK;
                    792:                }
                    793: 
                    794:                case SQLITE_ATTACH: {
                    795:                        TSRMLS_FETCH();
                    796:                        filename = make_filename_safe(arg3 TSRMLS_CC);
                    797:                        if (!filename) {
                    798:                                return SQLITE_DENY;
                    799:                        }
                    800:                        efree(filename);
                    801:                        return SQLITE_OK;
                    802:                }
                    803: 
                    804:                default:
                    805:                        /* access allowed */
                    806:                        return SQLITE_OK;
                    807:        }
                    808: }
                    809: 
                    810: static int pdo_sqlite_handle_factory(pdo_dbh_t *dbh, zval *driver_options TSRMLS_DC) /* {{{ */
                    811: {
                    812:        pdo_sqlite_db_handle *H;
                    813:        int i, ret = 0;
                    814:        long timeout = 60;
                    815:        char *filename;
                    816: 
                    817:        H = pecalloc(1, sizeof(pdo_sqlite_db_handle), dbh->is_persistent);
                    818:        
                    819:        H->einfo.errcode = 0;
                    820:        H->einfo.errmsg = NULL;
                    821:        dbh->driver_data = H;
                    822: 
                    823:        filename = make_filename_safe(dbh->data_source TSRMLS_CC);
                    824: 
                    825:        if (!filename) {
                    826:                zend_throw_exception_ex(php_pdo_get_exception(), 0 TSRMLS_CC,
1.1.1.2   misho     827:                        "open_basedir prohibits opening %s",
1.1       misho     828:                        dbh->data_source);
                    829:                goto cleanup;
                    830:        }
                    831: 
                    832:        i = sqlite3_open(filename, &H->db);
                    833:        efree(filename);
                    834: 
                    835:        if (i != SQLITE_OK) {
                    836:                pdo_sqlite_error(dbh);
                    837:                goto cleanup;
                    838:        }
                    839: 
1.1.1.2   misho     840:        if (PG(open_basedir) && *PG(open_basedir)) {
1.1       misho     841:                sqlite3_set_authorizer(H->db, authorizer, NULL);
                    842:        }
                    843: 
                    844:        if (driver_options) {
                    845:                timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, timeout TSRMLS_CC);
                    846:        }
                    847:        sqlite3_busy_timeout(H->db, timeout * 1000);
                    848: 
                    849:        dbh->alloc_own_columns = 1;
                    850:        dbh->max_escaped_char_length = 2;
                    851: 
                    852:        ret = 1;
                    853:        
                    854: cleanup:
                    855:        dbh->methods = &sqlite_methods;
                    856:        
                    857:        return ret;
                    858: }
                    859: /* }}} */
                    860: 
                    861: pdo_driver_t pdo_sqlite_driver = {
                    862:        PDO_DRIVER_HEADER(sqlite),
                    863:        pdo_sqlite_handle_factory
                    864: };
                    865: 
                    866: /*
                    867:  * Local variables:
                    868:  * tab-width: 4
                    869:  * c-basic-offset: 4
                    870:  * End:
                    871:  * vim600: noet sw=4 ts=4 fdm=marker
                    872:  * vim<600: noet sw=4 ts=4
                    873:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>