Annotation of embedaddon/php/ext/pdo_firebird/firebird_statement.c, revision 1.1

1.1     ! misho       1: /*
        !             2:   +----------------------------------------------------------------------+
        !             3:   | PHP Version 5                                                        |
        !             4:   +----------------------------------------------------------------------+
        !             5:   | Copyright (c) 1997-2012 The PHP Group                                |
        !             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: Ard Biesheuvel <abies@php.net>                               |
        !            16:   +----------------------------------------------------------------------+
        !            17: */
        !            18: 
        !            19: /* $Id: firebird_statement.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            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_firebird.h"
        !            31: #include "php_pdo_firebird_int.h"
        !            32: 
        !            33: #include <time.h>
        !            34:        
        !            35: #define RECORD_ERROR(stmt) _firebird_error(NULL, stmt,  __FILE__, __LINE__ TSRMLS_CC)
        !            36: 
        !            37: /* free the allocated space for passing field values to the db and back */
        !            38: static void free_sqlda(XSQLDA const *sqlda) /* {{{ */
        !            39: {
        !            40:        int i;
        !            41:        
        !            42:        for (i = 0; i < sqlda->sqld; ++i) {
        !            43:                XSQLVAR const *var = &sqlda->sqlvar[i];
        !            44:                
        !            45:                if (var->sqlind) {
        !            46:                        efree(var->sqlind);
        !            47:                }
        !            48:        }
        !            49: }
        !            50: /* }}} */
        !            51:        
        !            52: /* called by PDO to clean up a statement handle */
        !            53: static int firebird_stmt_dtor(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
        !            54: {
        !            55:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !            56:        int result = 1, i;
        !            57:        
        !            58:        /* release the statement */
        !            59:        if (isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_drop)) {
        !            60:                RECORD_ERROR(stmt);
        !            61:                result = 0;
        !            62:        }
        !            63: 
        !            64:        /* clean up the fetch buffers if they have been used */
        !            65:        for (i = 0; i < S->out_sqlda.sqld; ++i) {
        !            66:                if (S->fetch_buf[i]) {
        !            67:                        efree(S->fetch_buf[i]);
        !            68:                }
        !            69:        }
        !            70:        efree(S->fetch_buf);
        !            71:        
        !            72:        zend_hash_destroy(S->named_params);
        !            73:        FREE_HASHTABLE(S->named_params);
        !            74:        
        !            75:        /* clean up the input descriptor */
        !            76:        if (S->in_sqlda) {
        !            77:                free_sqlda(S->in_sqlda);
        !            78:                efree(S->in_sqlda);
        !            79:        }
        !            80: 
        !            81:        free_sqlda(&S->out_sqlda);
        !            82:        efree(S);
        !            83:        
        !            84:        return result;
        !            85: }
        !            86: /* }}} */
        !            87: 
        !            88: /* called by PDO to execute a prepared query */
        !            89: static int firebird_stmt_execute(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
        !            90: {
        !            91:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !            92:        pdo_firebird_db_handle *H = S->H;
        !            93:        unsigned long affected_rows = 0;
        !            94:        static char info_count[] = {isc_info_sql_records};
        !            95:        char result[64];
        !            96: 
        !            97:        do {
        !            98:                /* named or open cursors should be closed first */
        !            99:                if ((*S->name || S->cursor_open) && isc_dsql_free_statement(H->isc_status, &S->stmt, DSQL_close)) {
        !           100:                        break;
        !           101:                }
        !           102:                S->cursor_open = 0;
        !           103:                /* assume all params have been bound */
        !           104:        
        !           105:                if (isc_dsql_execute(H->isc_status, &H->tr, &S->stmt, PDO_FB_SQLDA_VERSION, S->in_sqlda)) {
        !           106:                        break;
        !           107:                }
        !           108:                
        !           109:                /* Determine how many rows have changed. In this case we are
        !           110:                 * only interested in rows changed, not rows retrieved. That
        !           111:                 * should be handled by the client when fetching. */
        !           112:                stmt->row_count = affected_rows;
        !           113:                
        !           114:                switch (S->statement_type) {
        !           115:                        case isc_info_sql_stmt_insert:
        !           116:                        case isc_info_sql_stmt_update:
        !           117:                        case isc_info_sql_stmt_delete:
        !           118:                        case isc_info_sql_stmt_exec_procedure:
        !           119:                                if (isc_dsql_sql_info(H->isc_status, &S->stmt, sizeof ( info_count),
        !           120:                                        info_count, sizeof(result), result)) {
        !           121:                                        break;
        !           122:                                }
        !           123:                                if (result[0] == isc_info_sql_records) {
        !           124:                                        unsigned i = 3, result_size = isc_vax_integer(&result[1], 2);
        !           125:                                        while (result[i] != isc_info_end && i < result_size) {
        !           126:                                                short len = (short) isc_vax_integer(&result[i + 1], 2);
        !           127:                                                if (result[i] != isc_info_req_select_count) {
        !           128:                                                        affected_rows += isc_vax_integer(&result[i + 3], len);
        !           129:                                                }
        !           130:                                                i += len + 3;
        !           131:                                        }
        !           132:                                        stmt->row_count = affected_rows;
        !           133:                                }
        !           134:                        default:
        !           135:                                ;
        !           136:                }
        !           137: 
        !           138:                /* commit? */
        !           139:                if (stmt->dbh->auto_commit && isc_commit_retaining(H->isc_status, &H->tr)) {
        !           140:                        break;
        !           141:                }
        !           142:        
        !           143:                *S->name = 0;
        !           144:                S->cursor_open = (S->out_sqlda.sqln > 0);       /* A cursor is opened, when more than zero columns returned */
        !           145:                S->exhausted = !S->cursor_open;
        !           146:                
        !           147:                return 1;
        !           148:        } while (0);
        !           149: 
        !           150:        RECORD_ERROR(stmt);     
        !           151: 
        !           152:        return 0;
        !           153: }
        !           154: /* }}} */
        !           155: 
        !           156: /* called by PDO to fetch the next row from a statement */
        !           157: static int firebird_stmt_fetch(pdo_stmt_t *stmt, /* {{{ */
        !           158:        enum pdo_fetch_orientation ori, long offset TSRMLS_DC)
        !           159: {
        !           160:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           161:        pdo_firebird_db_handle *H = S->H;
        !           162: 
        !           163:        if (!stmt->executed) {
        !           164:                strcpy(stmt->error_code, "HY000");
        !           165:                H->last_app_error = "Cannot fetch from a closed cursor";
        !           166:        } else if (!S->exhausted) {
        !           167:                if (isc_dsql_fetch(H->isc_status, &S->stmt, PDO_FB_SQLDA_VERSION, &S->out_sqlda)) {
        !           168:                        if (H->isc_status[0] && H->isc_status[1]) {
        !           169:                                RECORD_ERROR(stmt);
        !           170:                        }
        !           171:                        S->exhausted = 1;
        !           172:                        return 0;
        !           173:                }
        !           174:                if (S->statement_type == isc_info_sql_stmt_exec_procedure) {
        !           175:                        S->exhausted = 1;
        !           176:                }
        !           177:                stmt->row_count++;
        !           178:                return 1;
        !           179:        }
        !           180:        return 0;
        !           181: }
        !           182: /* }}} */
        !           183: 
        !           184: /* called by PDO to retrieve information about the fields being returned */
        !           185: static int firebird_stmt_describe(pdo_stmt_t *stmt, int colno TSRMLS_DC) /* {{{ */
        !           186: {
        !           187:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           188:        struct pdo_column_data *col = &stmt->columns[colno];
        !           189:        XSQLVAR *var = &S->out_sqlda.sqlvar[colno];
        !           190:        int colname_len;
        !           191:        char *cp;
        !           192:        
        !           193:        /* allocate storage for the column */
        !           194:        var->sqlind = (void*)ecalloc(1, var->sqllen + 2*sizeof(short));
        !           195:        var->sqldata = &((char*)var->sqlind)[sizeof(short)];
        !           196: 
        !           197:        colname_len = (S->H->fetch_table_names && var->relname_length)
        !           198:                                        ? (var->aliasname_length + var->relname_length + 1)
        !           199:                                        : (var->aliasname_length);
        !           200:        col->precision = -var->sqlscale;
        !           201:        col->maxlen = var->sqllen;
        !           202:        col->namelen = colname_len;
        !           203:        col->name = cp = emalloc(colname_len + 1);
        !           204:        if (colname_len > var->aliasname_length) {
        !           205:                memmove(cp, var->relname, var->relname_length);
        !           206:                cp += var->relname_length;
        !           207:                *cp++ = '.';
        !           208:        }
        !           209:        memmove(cp, var->aliasname, var->aliasname_length);
        !           210:        *(cp+var->aliasname_length) = '\0';
        !           211:        col->param_type = PDO_PARAM_STR;
        !           212: 
        !           213:        return 1;
        !           214: }
        !           215: /* }}} */
        !           216: 
        !           217: #define FETCH_BUF(buf,type,len,lenvar) ((buf) = (buf) ? (buf) : \
        !           218:        emalloc((len) ? (len * sizeof(type)) : ((*(unsigned long*)lenvar) = sizeof(type))))
        !           219: 
        !           220: #define CHAR_BUF_LEN 24
        !           221: 
        !           222: /* fetch a blob into a fetch buffer */
        !           223: static int firebird_fetch_blob(pdo_stmt_t *stmt, int colno, char **ptr, /* {{{ */
        !           224:        unsigned long *len, ISC_QUAD *blob_id TSRMLS_DC)
        !           225: {
        !           226:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           227:        pdo_firebird_db_handle *H = S->H;
        !           228:        isc_blob_handle blobh = NULL;
        !           229:        char const bl_item = isc_info_blob_total_length;
        !           230:        char bl_info[20];
        !           231:        unsigned short i;
        !           232:        int result = *len = 0;
        !           233: 
        !           234:        if (isc_open_blob(H->isc_status, &H->db, &H->tr, &blobh, blob_id)) {
        !           235:                RECORD_ERROR(stmt);
        !           236:                return 0;
        !           237:        }
        !           238: 
        !           239:        if (isc_blob_info(H->isc_status, &blobh, 1, const_cast(&bl_item),
        !           240:                        sizeof(bl_info), bl_info)) {
        !           241:                RECORD_ERROR(stmt);
        !           242:                goto fetch_blob_end;
        !           243:        }
        !           244: 
        !           245:        /* find total length of blob's data */
        !           246:        for (i = 0; i < sizeof(bl_info); ) {
        !           247:                unsigned short item_len;
        !           248:                char item = bl_info[i++];
        !           249: 
        !           250:                if (item == isc_info_end || item == isc_info_truncated || item == isc_info_error
        !           251:                                || i >= sizeof(bl_info)) {
        !           252:                        H->last_app_error = "Couldn't determine BLOB size";
        !           253:                        goto fetch_blob_end;
        !           254:                }                                                               
        !           255: 
        !           256:                item_len = (unsigned short) isc_vax_integer(&bl_info[i], 2);
        !           257: 
        !           258:                if (item == isc_info_blob_total_length) {
        !           259:                        *len = isc_vax_integer(&bl_info[i+2], item_len);
        !           260:                        break;
        !           261:                }
        !           262:                i += item_len+2;
        !           263:        }
        !           264: 
        !           265:        /* we've found the blob's length, now fetch! */
        !           266:        
        !           267:        if (*len) {
        !           268:                unsigned long cur_len;
        !           269:                unsigned short seg_len;
        !           270:                ISC_STATUS stat;
        !           271: 
        !           272:                *ptr = S->fetch_buf[colno] = erealloc(*ptr, *len+1);
        !           273:        
        !           274:                for (cur_len = stat = 0; (!stat || stat == isc_segment) && cur_len < *len; cur_len += seg_len) {
        !           275:        
        !           276:                        unsigned short chunk_size = (*len-cur_len) > USHRT_MAX ? USHRT_MAX
        !           277:                                : (unsigned short)(*len-cur_len);
        !           278:        
        !           279:                        stat = isc_get_segment(H->isc_status, &blobh, &seg_len, chunk_size, &(*ptr)[cur_len]);
        !           280:                }
        !           281:        
        !           282:                (*ptr)[*len++] = '\0';
        !           283:        
        !           284:                if (H->isc_status[0] == 1 && (stat != 0 && stat != isc_segstr_eof && stat != isc_segment)) {
        !           285:                        H->last_app_error = "Error reading from BLOB";
        !           286:                        goto fetch_blob_end;
        !           287:                }
        !           288:        }
        !           289:        result = 1;
        !           290: 
        !           291: fetch_blob_end:
        !           292:        if (isc_close_blob(H->isc_status, &blobh)) {
        !           293:                RECORD_ERROR(stmt);
        !           294:                return 0;
        !           295:        }
        !           296:        return result;
        !           297: }
        !           298: /* }}} */
        !           299: 
        !           300: static int firebird_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,  /* {{{ */
        !           301:        unsigned long *len, int *caller_frees TSRMLS_DC)
        !           302: {
        !           303:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           304:        XSQLVAR const *var = &S->out_sqlda.sqlvar[colno];
        !           305: 
        !           306:        if (*var->sqlind == -1) {
        !           307:                /* A NULL value */
        !           308:                *ptr = NULL;
        !           309:                *len = 0;
        !           310:        } else {
        !           311:                if (var->sqlscale < 0) {
        !           312:                        static ISC_INT64 const scales[] = { 1, 10, 100, 1000, 
        !           313:                                10000, 
        !           314:                                100000, 
        !           315:                                1000000, 
        !           316:                                10000000,
        !           317:                                100000000, 
        !           318:                                1000000000, 
        !           319:                                LL_LIT(10000000000), 
        !           320:                                LL_LIT(100000000000),
        !           321:                                LL_LIT(1000000000000), 
        !           322:                                LL_LIT(10000000000000), 
        !           323:                                LL_LIT(100000000000000),
        !           324:                                LL_LIT(1000000000000000),
        !           325:                                LL_LIT(10000000000000000), 
        !           326:                                LL_LIT(100000000000000000), 
        !           327:                                LL_LIT(1000000000000000000)
        !           328:                        };
        !           329:                        ISC_INT64 n, f = scales[-var->sqlscale];
        !           330: 
        !           331:                        switch (var->sqltype & ~1) {
        !           332:                                case SQL_SHORT:
        !           333:                                        n = *(short*)var->sqldata;
        !           334:                                        break;
        !           335:                                case SQL_LONG:
        !           336:                                        n = *(ISC_LONG*)var->sqldata;
        !           337:                                        break;
        !           338:                                case SQL_INT64:
        !           339:                                        n = *(ISC_INT64*)var->sqldata;
        !           340:                        }
        !           341:                                
        !           342:                        *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
        !           343:                        
        !           344:                        if (n >= 0) {
        !           345:                                *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d", 
        !           346:                                        n / f, -var->sqlscale, n % f);
        !           347:                        } else if (n < -f) {
        !           348:                                *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d.%0*" LL_MASK "d",
        !           349:                                        n / f, -var->sqlscale, -n % f);                         
        !           350:                         } else {
        !           351:                                *len = slprintf(*ptr, CHAR_BUF_LEN, "-0.%0*" LL_MASK "d", -var->sqlscale, -n % f);
        !           352:                        }
        !           353:                } else {
        !           354:                        switch (var->sqltype & ~1) {
        !           355:                                struct tm t;
        !           356:                                char *fmt;                              
        !           357: 
        !           358:                                case SQL_VARYING:
        !           359:                                        *ptr = &var->sqldata[2];
        !           360:                                        *len = *(short*)var->sqldata;
        !           361:                                        break;
        !           362:                                case SQL_TEXT:
        !           363:                                        *ptr = var->sqldata;
        !           364:                                        *len = var->sqllen;
        !           365:                                        break;
        !           366:                                case SQL_SHORT:
        !           367:                                    *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
        !           368:                                        *len = slprintf(*ptr, CHAR_BUF_LEN, "%d", *(short*)var->sqldata);
        !           369:                                        break;
        !           370:                                case SQL_LONG:
        !           371:                                        *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
        !           372:                                        *len = slprintf(*ptr, CHAR_BUF_LEN, "%ld", *(ISC_LONG*)var->sqldata);
        !           373:                                        break;
        !           374:                                case SQL_INT64:
        !           375:                                        *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
        !           376:                                        *len = slprintf(*ptr, CHAR_BUF_LEN, "%" LL_MASK "d", *(ISC_INT64*)var->sqldata);
        !           377:                                        break;
        !           378:                                case SQL_FLOAT:
        !           379:                                        *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
        !           380:                                        *len = slprintf(*ptr, CHAR_BUF_LEN, "%F", *(float*)var->sqldata);
        !           381:                                        break;
        !           382:                                case SQL_DOUBLE:
        !           383:                                        *ptr = FETCH_BUF(S->fetch_buf[colno], char, CHAR_BUF_LEN, NULL);
        !           384:                                        *len = slprintf(*ptr, CHAR_BUF_LEN, "%F" , *(double*)var->sqldata);
        !           385:                                        break;
        !           386:                                case SQL_TYPE_DATE:
        !           387:                                        isc_decode_sql_date((ISC_DATE*)var->sqldata, &t);
        !           388:                                        fmt = S->H->date_format ? S->H->date_format : PDO_FB_DEF_DATE_FMT;
        !           389:                                        if (0) {
        !           390:                                case SQL_TYPE_TIME:
        !           391:                                                isc_decode_sql_time((ISC_TIME*)var->sqldata, &t);
        !           392:                                                fmt = S->H->time_format ? S->H->time_format : PDO_FB_DEF_TIME_FMT;
        !           393:                                        } else if (0) {
        !           394:                                case SQL_TIMESTAMP:
        !           395:                                                isc_decode_timestamp((ISC_TIMESTAMP*)var->sqldata, &t);
        !           396:                                                fmt = S->H->timestamp_format ? S->H->timestamp_format : PDO_FB_DEF_TIMESTAMP_FMT;
        !           397:                                        }
        !           398:                                        /* convert the timestamp into a string */
        !           399:                                        *len = 80;
        !           400:                                        *ptr = FETCH_BUF(S->fetch_buf[colno], char, *len, NULL);
        !           401:                                        *len = strftime(*ptr, *len, fmt, &t);
        !           402:                                        break;
        !           403:                                case SQL_BLOB:
        !           404:                                        return firebird_fetch_blob(stmt,colno,ptr,len,
        !           405:                                                (ISC_QUAD*)var->sqldata TSRMLS_CC);
        !           406:                        }
        !           407:                }
        !           408:        }
        !           409:        return 1;
        !           410: }
        !           411: /* }}} */
        !           412: 
        !           413: static int firebird_bind_blob(pdo_stmt_t *stmt, ISC_QUAD *blob_id, zval *param TSRMLS_DC)
        !           414: {
        !           415:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           416:        pdo_firebird_db_handle *H = S->H;
        !           417:        isc_blob_handle h = NULL;
        !           418:        unsigned long put_cnt = 0, rem_cnt;
        !           419:        unsigned short chunk_size;
        !           420:        int result = 1;
        !           421:        
        !           422:        if (isc_create_blob(H->isc_status, &H->db, &H->tr, &h, blob_id)) {
        !           423:                RECORD_ERROR(stmt);
        !           424:                return 0;
        !           425:        }
        !           426: 
        !           427:        SEPARATE_ZVAL(&param);
        !           428: 
        !           429:        convert_to_string_ex(&param);
        !           430:        
        !           431:        for (rem_cnt = Z_STRLEN_P(param); rem_cnt > 0; rem_cnt -= chunk_size)  {
        !           432: 
        !           433:                chunk_size = rem_cnt > USHRT_MAX ? USHRT_MAX : (unsigned short)rem_cnt;
        !           434: 
        !           435:                if (isc_put_segment(H->isc_status, &h, chunk_size, &Z_STRVAL_P(param)[put_cnt])) {
        !           436:                        RECORD_ERROR(stmt);
        !           437:                        result = 0;
        !           438:                        break;
        !           439:                }
        !           440:                put_cnt += chunk_size;
        !           441:        }
        !           442:        
        !           443:        zval_dtor(param);
        !           444: 
        !           445:        if (isc_close_blob(H->isc_status, &h)) {
        !           446:                RECORD_ERROR(stmt);
        !           447:                return 0;
        !           448:        }
        !           449:        return result;
        !           450: }      
        !           451: 
        !           452: static int firebird_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *param, /* {{{ */
        !           453:        enum pdo_param_event event_type TSRMLS_DC)
        !           454: {
        !           455:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           456:        XSQLDA *sqlda = param->is_param ? S->in_sqlda : &S->out_sqlda;
        !           457:        XSQLVAR *var;
        !           458: 
        !           459:        if (event_type == PDO_PARAM_EVT_FREE) { /* not used */
        !           460:                return 1;
        !           461:        }
        !           462: 
        !           463:        if (!sqlda || param->paramno >= sqlda->sqld) {
        !           464:                strcpy(stmt->error_code, "HY093");
        !           465:                S->H->last_app_error = "Invalid parameter index";
        !           466:                return 0;
        !           467:        }
        !           468:        if (param->is_param && param->paramno == -1) {
        !           469:                long *index;
        !           470: 
        !           471:                /* try to determine the index by looking in the named_params hash */
        !           472:                if (SUCCESS == zend_hash_find(S->named_params, param->name, param->namelen+1, (void*)&index)) {
        !           473:                        param->paramno = *index;
        !           474:                } else {
        !           475:                        /* ... or by looking in the input descriptor */
        !           476:                        int i;
        !           477: 
        !           478:                        for (i = 0; i < sqlda->sqld; ++i) {
        !           479:                                XSQLVAR *var = &sqlda->sqlvar[i];
        !           480: 
        !           481:                                if ((var->aliasname_length && !strncasecmp(param->name, var->aliasname, 
        !           482:                                                min(param->namelen, var->aliasname_length))) 
        !           483:                                                || (var->sqlname_length && !strncasecmp(param->name, var->sqlname,
        !           484:                                                min(param->namelen, var->sqlname_length)))) {
        !           485:                                        param->paramno = i;
        !           486:                                        break;
        !           487:                                }
        !           488:                        }
        !           489:                        if (i >= sqlda->sqld) {
        !           490:                                strcpy(stmt->error_code, "HY093");
        !           491:                                S->H->last_app_error = "Invalid parameter name";
        !           492:                                return 0;
        !           493:                        }
        !           494:                }
        !           495:        }
        !           496: 
        !           497:        var = &sqlda->sqlvar[param->paramno];
        !           498:        
        !           499:        switch (event_type) {
        !           500:                char *value;
        !           501:                unsigned long value_len;
        !           502:                int caller_frees;
        !           503:                        
        !           504:                case PDO_PARAM_EVT_ALLOC:
        !           505:                        if (param->is_param) {
        !           506:                                /* allocate the parameter */
        !           507:                                if (var->sqlind) {
        !           508:                                        efree(var->sqlind);
        !           509:                                }
        !           510:                                var->sqlind = (void*)emalloc(var->sqllen + 2*sizeof(short));
        !           511:                                var->sqldata = &((char*)var->sqlind)[sizeof(short)];
        !           512:                        }
        !           513:                        break;
        !           514:                        
        !           515:                case PDO_PARAM_EVT_EXEC_PRE:
        !           516:                        if (!param->is_param) {
        !           517:                                break;
        !           518:                        }
        !           519: 
        !           520:                        *var->sqlind = 0;
        !           521: 
        !           522:                        switch (var->sqltype & ~1) {
        !           523:                                case SQL_ARRAY:
        !           524:                                        strcpy(stmt->error_code, "HY000");
        !           525:                                        S->H->last_app_error = "Cannot bind to array field";
        !           526:                                        return 0;
        !           527:        
        !           528:                                case SQL_BLOB:
        !           529:                                        return firebird_bind_blob(stmt, (ISC_QUAD*)var->sqldata,
        !           530:                                                param->parameter TSRMLS_CC);
        !           531:                        }
        !           532:                                                        
        !           533:                        /* check if a NULL should be inserted */
        !           534:                        switch (Z_TYPE_P(param->parameter)) {
        !           535:                                int force_null;
        !           536:                                
        !           537:                                case IS_LONG:
        !           538:                                        var->sqltype = sizeof(long) == 8 ? SQL_INT64 : SQL_LONG;
        !           539:                                        var->sqldata = (void*)&Z_LVAL_P(param->parameter);
        !           540:                                        var->sqllen = sizeof(long);
        !           541:                                        break;
        !           542:                                case IS_DOUBLE:
        !           543:                                        var->sqltype = SQL_DOUBLE;
        !           544:                                        var->sqldata = (void*)&Z_DVAL_P(param->parameter);
        !           545:                                        var->sqllen = sizeof(double);
        !           546:                                        break;
        !           547:                                case IS_STRING:
        !           548:                                        force_null = 0;
        !           549:        
        !           550:                                        /* for these types, an empty string can be handled like a NULL value */
        !           551:                                        switch (var->sqltype & ~1) {
        !           552:                                                case SQL_SHORT:
        !           553:                                                case SQL_LONG:
        !           554:                                                case SQL_INT64:
        !           555:                                                case SQL_FLOAT:
        !           556:                                                case SQL_DOUBLE:
        !           557:                                                case SQL_TIMESTAMP:
        !           558:                                                case SQL_TYPE_DATE:
        !           559:                                                case SQL_TYPE_TIME:
        !           560:                                                        force_null = (Z_STRLEN_P(param->parameter) == 0);
        !           561:                                        }
        !           562:                                        if (!force_null) {
        !           563:                                                var->sqltype = SQL_TEXT;
        !           564:                                                var->sqldata = Z_STRVAL_P(param->parameter);
        !           565:                                                var->sqllen      = Z_STRLEN_P(param->parameter);
        !           566:                                                break;
        !           567:                                        }
        !           568:                                case IS_NULL:
        !           569:                                        /* complain if this field doesn't allow NULL values */
        !           570:                                        if (~var->sqltype & 1) {
        !           571:                                                strcpy(stmt->error_code, "HY105");
        !           572:                                                S->H->last_app_error = "Parameter requires non-null value";
        !           573:                                                return 0;
        !           574:                                        }
        !           575:                                        *var->sqlind = -1;
        !           576:                                        break;
        !           577:                                default:
        !           578:                                        strcpy(stmt->error_code, "HY105");
        !           579:                                        S->H->last_app_error = "Binding arrays/objects is not supported";
        !           580:                                        return 0;
        !           581:                        }
        !           582:                        break;
        !           583: 
        !           584:                case PDO_PARAM_EVT_FETCH_POST:
        !           585:                         if (param->paramno == -1) {
        !           586:                             return 0;
        !           587:                         }
        !           588:                        if (param->is_param) {
        !           589:                                break;
        !           590:                        }
        !           591:                        value = NULL;
        !           592:                        value_len = 0;
        !           593:                        caller_frees = 0;
        !           594:                        
        !           595:                        if (firebird_stmt_get_col(stmt, param->paramno, &value, &value_len, &caller_frees TSRMLS_CC)) {
        !           596:                                switch (PDO_PARAM_TYPE(param->param_type)) {
        !           597:                                        case PDO_PARAM_STR:
        !           598:                                                if (value) {
        !           599:                                                        ZVAL_STRINGL(param->parameter, value, value_len, 1);
        !           600:                                                        break;
        !           601:                                                }
        !           602:                                        case PDO_PARAM_INT:
        !           603:                                                if (value) {
        !           604:                                                        ZVAL_LONG(param->parameter, *(long*)value);
        !           605:                                                        break;
        !           606:                                                }
        !           607:                                         case PDO_PARAM_EVT_NORMALIZE:
        !           608:                                                  if (!param->is_param) {
        !           609:                                                       char *s = param->name;
        !           610:                                                       while (*s != '\0') {
        !           611:                                                            *s = toupper(*s);
        !           612:                                                             s++;
        !           613:                                                       }
        !           614:                                                  }
        !           615:                                                         break;
        !           616:                                        default:
        !           617:                                                ZVAL_NULL(param->parameter);
        !           618:                                }
        !           619:                                if (value && caller_frees) {
        !           620:                                        efree(value);
        !           621:                                }
        !           622:                                return 1;
        !           623:                        }
        !           624:                        return 0;
        !           625:                default:
        !           626:                        ;
        !           627:        }               
        !           628:        return 1;
        !           629: }
        !           630: /* }}} */
        !           631: 
        !           632: static int firebird_stmt_set_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */
        !           633: {
        !           634:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           635:        
        !           636:        switch (attr) {
        !           637:                default:
        !           638:                        return 0;
        !           639:                case PDO_ATTR_CURSOR_NAME:
        !           640:                        convert_to_string(val);
        !           641:                        
        !           642:                        if (isc_dsql_set_cursor_name(S->H->isc_status, &S->stmt, Z_STRVAL_P(val),0)) {
        !           643:                                RECORD_ERROR(stmt);
        !           644:                                return 0;
        !           645:                        }
        !           646:                        strlcpy(S->name, Z_STRVAL_P(val), sizeof(S->name));
        !           647:                        break;
        !           648:        }
        !           649:        return 1;
        !           650: }
        !           651: /* }}} */
        !           652: 
        !           653: static int firebird_stmt_get_attribute(pdo_stmt_t *stmt, long attr, zval *val TSRMLS_DC) /* {{{ */
        !           654: {
        !           655:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           656:        
        !           657:        switch (attr) {
        !           658:                default:
        !           659:                        return 0;
        !           660:                case PDO_ATTR_CURSOR_NAME:
        !           661:                        if (*S->name) {
        !           662:                                ZVAL_STRING(val,S->name,1);
        !           663:                        } else {
        !           664:                                ZVAL_NULL(val);
        !           665:                        }
        !           666:                        break;
        !           667:        }
        !           668:        return 1;
        !           669: }
        !           670: /* }}} */
        !           671: 
        !           672: static int firebird_stmt_cursor_closer(pdo_stmt_t *stmt TSRMLS_DC) /* {{{ */
        !           673: {
        !           674:        pdo_firebird_stmt *S = (pdo_firebird_stmt*)stmt->driver_data;
        !           675:        
        !           676:        /* close the statement handle */
        !           677:        if ((*S->name || S->cursor_open) && isc_dsql_free_statement(S->H->isc_status, &S->stmt, DSQL_close)) {
        !           678:                RECORD_ERROR(stmt);
        !           679:                return 0;
        !           680:        }
        !           681:        *S->name = 0;
        !           682:        S->cursor_open = 0;
        !           683:        return 1;
        !           684: }
        !           685: /* }}} */
        !           686: 
        !           687: 
        !           688: struct pdo_stmt_methods firebird_stmt_methods = { /* {{{ */
        !           689:        firebird_stmt_dtor,
        !           690:        firebird_stmt_execute,
        !           691:        firebird_stmt_fetch,
        !           692:        firebird_stmt_describe,
        !           693:        firebird_stmt_get_col,
        !           694:        firebird_stmt_param_hook,
        !           695:        firebird_stmt_set_attribute,
        !           696:        firebird_stmt_get_attribute,
        !           697:        NULL, /* get_column_meta_func */
        !           698:        NULL, /* next_rowset_func */
        !           699:        firebird_stmt_cursor_closer
        !           700: };
        !           701: /* }}} */
        !           702: 
        !           703: /*
        !           704:  * Local variables:
        !           705:  * tab-width: 4
        !           706:  * c-basic-offset: 4
        !           707:  * End:
        !           708:  * vim600: noet sw=4 ts=4 fdm=marker
        !           709:  * vim<600: noet sw=4 ts=4
        !           710:  */

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