Annotation of embedaddon/php/ext/pdo/pdo_sql_parser.c, revision 1.1.1.2

1.1       misho       1: /* Generated by re2c 0.13.5 on Sat Jun  4 18:42:25 2011 */
                      2: /*
                      3:   +----------------------------------------------------------------------+
                      4:   | PHP Version 5                                                        |
                      5:   +----------------------------------------------------------------------+
                      6:   | Copyright (c) 1997-2012 The PHP Group                                |
                      7:   +----------------------------------------------------------------------+
                      8:   | This source file is subject to version 3.01 of the PHP license,      |
                      9:   | that is bundled with this package in the file LICENSE, and is        |
                     10:   | available through the world-wide-web at the following url:           |
                     11:   | http://www.php.net/license/3_01.txt                                  |
                     12:   | If you did not receive a copy of the PHP license and are unable to   |
                     13:   | obtain it through the world-wide-web, please send a note to          |
                     14:   | license@php.net so we can mail you a copy immediately.               |
                     15:   +----------------------------------------------------------------------+
                     16:   | Author: George Schlossnagle <george@omniti.com>                      |
                     17:   +----------------------------------------------------------------------+
                     18: */
                     19: 
1.1.1.2 ! misho      20: /* $Id$ */
1.1       misho      21: 
                     22: #include "php.h"
                     23: #include "php_pdo_driver.h"
                     24: #include "php_pdo_int.h"
                     25: 
                     26: #define PDO_PARSER_TEXT 1
                     27: #define PDO_PARSER_BIND 2
                     28: #define PDO_PARSER_BIND_POS 3
                     29: #define PDO_PARSER_EOI 4
                     30: 
                     31: #define RET(i) {s->cur = cursor; return i; }
                     32: #define SKIP_ONE(i) {s->cur = s->tok + 1; return i; }
                     33: 
                     34: #define YYCTYPE         unsigned char
                     35: #define YYCURSOR        cursor
                     36: #define YYLIMIT         cursor
                     37: #define YYMARKER        s->ptr
                     38: #define YYFILL(n)
                     39: 
                     40: typedef struct Scanner {
                     41:        char    *ptr, *cur, *tok;
                     42: } Scanner;
                     43: 
                     44: static int scan(Scanner *s) 
                     45: {
                     46:        char *cursor = s->cur;
                     47: 
                     48:        s->tok = cursor;
                     49: 
                     50: 
                     51:        
                     52: {
                     53:        YYCTYPE yych;
                     54:        unsigned int yyaccept = 0;
                     55: 
                     56:        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
                     57:        yych = *YYCURSOR;
                     58:        switch (yych) {
                     59:        case 0x00:      goto yy13;
                     60:        case '"':       goto yy2;
                     61:        case '\'':      goto yy4;
                     62:        case '-':       goto yy10;
                     63:        case '/':       goto yy8;
                     64:        case ':':       goto yy5;
                     65:        case '?':       goto yy6;
                     66:        default:        goto yy11;
                     67:        }
                     68: yy2:
                     69:        yyaccept = 0;
                     70:        yych = *(YYMARKER = ++YYCURSOR);
                     71:        if (yych >= 0x01) goto yy43;
                     72: yy3:
                     73:        { SKIP_ONE(PDO_PARSER_TEXT); }
                     74: yy4:
                     75:        yyaccept = 0;
                     76:        yych = *(YYMARKER = ++YYCURSOR);
                     77:        if (yych <= 0x00) goto yy3;
                     78:        goto yy37;
                     79: yy5:
                     80:        yych = *++YYCURSOR;
                     81:        switch (yych) {
                     82:        case '0':
                     83:        case '1':
                     84:        case '2':
                     85:        case '3':
                     86:        case '4':
                     87:        case '5':
                     88:        case '6':
                     89:        case '7':
                     90:        case '8':
                     91:        case '9':
                     92:        case 'A':
                     93:        case 'B':
                     94:        case 'C':
                     95:        case 'D':
                     96:        case 'E':
                     97:        case 'F':
                     98:        case 'G':
                     99:        case 'H':
                    100:        case 'I':
                    101:        case 'J':
                    102:        case 'K':
                    103:        case 'L':
                    104:        case 'M':
                    105:        case 'N':
                    106:        case 'O':
                    107:        case 'P':
                    108:        case 'Q':
                    109:        case 'R':
                    110:        case 'S':
                    111:        case 'T':
                    112:        case 'U':
                    113:        case 'V':
                    114:        case 'W':
                    115:        case 'X':
                    116:        case 'Y':
                    117:        case 'Z':
                    118:        case '_':
                    119:        case 'a':
                    120:        case 'b':
                    121:        case 'c':
                    122:        case 'd':
                    123:        case 'e':
                    124:        case 'f':
                    125:        case 'g':
                    126:        case 'h':
                    127:        case 'i':
                    128:        case 'j':
                    129:        case 'k':
                    130:        case 'l':
                    131:        case 'm':
                    132:        case 'n':
                    133:        case 'o':
                    134:        case 'p':
                    135:        case 'q':
                    136:        case 'r':
                    137:        case 's':
                    138:        case 't':
                    139:        case 'u':
                    140:        case 'v':
                    141:        case 'w':
                    142:        case 'x':
                    143:        case 'y':
                    144:        case 'z':       goto yy33;
                    145:        case ':':
                    146:        case '?':       goto yy30;
                    147:        default:        goto yy3;
                    148:        }
                    149: yy6:
                    150:        ++YYCURSOR;
                    151:        switch ((yych = *YYCURSOR)) {
                    152:        case ':':
                    153:        case '?':       goto yy30;
                    154:        default:        goto yy7;
                    155:        }
                    156: yy7:
                    157:        { RET(PDO_PARSER_BIND_POS); }
                    158: yy8:
                    159:        ++YYCURSOR;
                    160:        switch ((yych = *YYCURSOR)) {
                    161:        case '*':       goto yy20;
                    162:        default:        goto yy12;
                    163:        }
                    164: yy9:
                    165:        { RET(PDO_PARSER_TEXT); }
                    166: yy10:
                    167:        yych = *++YYCURSOR;
                    168:        switch (yych) {
                    169:        case '-':       goto yy15;
                    170:        default:        goto yy12;
                    171:        }
                    172: yy11:
                    173:        ++YYCURSOR;
                    174:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    175:        yych = *YYCURSOR;
                    176: yy12:
                    177:        switch (yych) {
                    178:        case 0x00:
                    179:        case '"':
                    180:        case '\'':
                    181:        case ':':
                    182:        case '?':       goto yy9;
                    183:        default:        goto yy11;
                    184:        }
                    185: yy13:
                    186:        ++YYCURSOR;
                    187:        { RET(PDO_PARSER_EOI); }
                    188: yy15:
                    189:        ++YYCURSOR;
                    190:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    191:        yych = *YYCURSOR;
                    192:        switch (yych) {
                    193:        case 0x00:
                    194:        case '"':
                    195:        case '\'':
                    196:        case ':':
                    197:        case '?':       goto yy18;
                    198:        case '\n':
                    199:        case '\r':      goto yy11;
                    200:        default:        goto yy15;
                    201:        }
                    202: yy17:
                    203:        { RET(PDO_PARSER_TEXT); }
                    204: yy18:
                    205:        ++YYCURSOR;
                    206:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    207:        yych = *YYCURSOR;
                    208:        switch (yych) {
                    209:        case '\n':
                    210:        case '\r':      goto yy17;
                    211:        default:        goto yy18;
                    212:        }
                    213: yy20:
                    214:        yyaccept = 1;
                    215:        YYMARKER = ++YYCURSOR;
                    216:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    217:        yych = *YYCURSOR;
                    218:        switch (yych) {
                    219:        case 0x00:
                    220:        case '"':
                    221:        case '\'':
                    222:        case ':':
                    223:        case '?':       goto yy22;
                    224:        case '*':       goto yy24;
                    225:        default:        goto yy20;
                    226:        }
                    227: yy22:
                    228:        ++YYCURSOR;
                    229:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    230:        yych = *YYCURSOR;
                    231:        switch (yych) {
                    232:        case '*':       goto yy27;
                    233:        default:        goto yy22;
                    234:        }
                    235: yy24:
                    236:        yyaccept = 1;
                    237:        YYMARKER = ++YYCURSOR;
                    238:        if ((YYLIMIT - YYCURSOR) < 2) YYFILL(2);
                    239:        yych = *YYCURSOR;
                    240:        switch (yych) {
                    241:        case 0x00:
                    242:        case '"':
                    243:        case '\'':
                    244:        case ':':
                    245:        case '?':       goto yy22;
                    246:        case '*':       goto yy24;
                    247:        case '/':       goto yy26;
                    248:        default:        goto yy20;
                    249:        }
                    250: yy26:
                    251:        yych = *++YYCURSOR;
                    252:        switch (yych) {
                    253:        case 0x00:
                    254:        case '"':
                    255:        case '\'':
                    256:        case ':':
                    257:        case '?':       goto yy17;
                    258:        default:        goto yy11;
                    259:        }
                    260: yy27:
                    261:        ++YYCURSOR;
                    262:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    263:        yych = *YYCURSOR;
                    264:        switch (yych) {
                    265:        case '*':       goto yy27;
                    266:        case '/':       goto yy29;
                    267:        default:        goto yy22;
                    268:        }
                    269: yy29:
                    270:        yych = *++YYCURSOR;
                    271:        goto yy17;
                    272: yy30:
                    273:        ++YYCURSOR;
                    274:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    275:        yych = *YYCURSOR;
                    276:        switch (yych) {
                    277:        case ':':
                    278:        case '?':       goto yy30;
                    279:        default:        goto yy32;
                    280:        }
                    281: yy32:
                    282:        { RET(PDO_PARSER_TEXT); }
                    283: yy33:
                    284:        ++YYCURSOR;
                    285:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    286:        yych = *YYCURSOR;
                    287:        switch (yych) {
                    288:        case '0':
                    289:        case '1':
                    290:        case '2':
                    291:        case '3':
                    292:        case '4':
                    293:        case '5':
                    294:        case '6':
                    295:        case '7':
                    296:        case '8':
                    297:        case '9':
                    298:        case 'A':
                    299:        case 'B':
                    300:        case 'C':
                    301:        case 'D':
                    302:        case 'E':
                    303:        case 'F':
                    304:        case 'G':
                    305:        case 'H':
                    306:        case 'I':
                    307:        case 'J':
                    308:        case 'K':
                    309:        case 'L':
                    310:        case 'M':
                    311:        case 'N':
                    312:        case 'O':
                    313:        case 'P':
                    314:        case 'Q':
                    315:        case 'R':
                    316:        case 'S':
                    317:        case 'T':
                    318:        case 'U':
                    319:        case 'V':
                    320:        case 'W':
                    321:        case 'X':
                    322:        case 'Y':
                    323:        case 'Z':
                    324:        case '_':
                    325:        case 'a':
                    326:        case 'b':
                    327:        case 'c':
                    328:        case 'd':
                    329:        case 'e':
                    330:        case 'f':
                    331:        case 'g':
                    332:        case 'h':
                    333:        case 'i':
                    334:        case 'j':
                    335:        case 'k':
                    336:        case 'l':
                    337:        case 'm':
                    338:        case 'n':
                    339:        case 'o':
                    340:        case 'p':
                    341:        case 'q':
                    342:        case 'r':
                    343:        case 's':
                    344:        case 't':
                    345:        case 'u':
                    346:        case 'v':
                    347:        case 'w':
                    348:        case 'x':
                    349:        case 'y':
                    350:        case 'z':       goto yy33;
                    351:        default:        goto yy35;
                    352:        }
                    353: yy35:
                    354:        { RET(PDO_PARSER_BIND); }
                    355: yy36:
                    356:        ++YYCURSOR;
                    357:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    358:        yych = *YYCURSOR;
                    359: yy37:
                    360:        switch (yych) {
                    361:        case 0x00:      goto yy38;
                    362:        case '\'':      goto yy40;
                    363:        case '\\':      goto yy39;
                    364:        default:        goto yy36;
                    365:        }
                    366: yy38:
                    367:        YYCURSOR = YYMARKER;
                    368:        switch (yyaccept) {
                    369:        case 0:         goto yy3;
                    370:        case 1:         goto yy9;
                    371:        }
                    372: yy39:
                    373:        ++YYCURSOR;
                    374:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    375:        yych = *YYCURSOR;
                    376:        if (yych <= 0x00) goto yy38;
                    377:        goto yy36;
                    378: yy40:
                    379:        ++YYCURSOR;
                    380:        { RET(PDO_PARSER_TEXT); }
                    381: yy42:
                    382:        ++YYCURSOR;
                    383:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    384:        yych = *YYCURSOR;
                    385: yy43:
                    386:        switch (yych) {
                    387:        case 0x00:      goto yy38;
                    388:        case '"':       goto yy45;
                    389:        case '\\':      goto yy44;
                    390:        default:        goto yy42;
                    391:        }
                    392: yy44:
                    393:        ++YYCURSOR;
                    394:        if (YYLIMIT <= YYCURSOR) YYFILL(1);
                    395:        yych = *YYCURSOR;
                    396:        if (yych <= 0x00) goto yy38;
                    397:        goto yy42;
                    398: yy45:
                    399:        ++YYCURSOR;
                    400:        { RET(PDO_PARSER_TEXT); }
                    401: }
                    402:        
                    403: }
                    404: 
                    405: struct placeholder {
                    406:        char *pos;
                    407:        int len;
                    408:        int bindno;
                    409:        int qlen;               /* quoted length of value */
                    410:        char *quoted;   /* quoted value */
                    411:        int freeq;
                    412:        struct placeholder *next;
                    413: };
                    414: 
                    415: PDO_API int pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, 
                    416:        char **outquery, int *outquery_len TSRMLS_DC)
                    417: {
                    418:        Scanner s;
                    419:        char *ptr, *newbuffer;
                    420:        int t;
                    421:        int bindno = 0;
                    422:        int ret = 0;
                    423:        int newbuffer_len;
                    424:        HashTable *params;
                    425:        struct pdo_bound_param_data *param;
                    426:        int query_type = PDO_PLACEHOLDER_NONE;
                    427:        struct placeholder *placeholders = NULL, *placetail = NULL, *plc = NULL;
                    428: 
                    429:        ptr = *outquery;
                    430:        s.cur = inquery;
                    431: 
                    432:        /* phase 1: look for args */
                    433:        while((t = scan(&s)) != PDO_PARSER_EOI) {
                    434:                if (t == PDO_PARSER_BIND || t == PDO_PARSER_BIND_POS) {
                    435:                        if (t == PDO_PARSER_BIND) {
                    436:                                int len = s.cur - s.tok;
                    437:                                if ((inquery < (s.cur - len)) && isalnum(*(s.cur - len - 1))) {
                    438:                                        continue;
                    439:                                }
                    440:                                query_type |= PDO_PLACEHOLDER_NAMED;
                    441:                        } else {
                    442:                                query_type |= PDO_PLACEHOLDER_POSITIONAL;
                    443:                        }
                    444: 
                    445:                        plc = emalloc(sizeof(*plc));
                    446:                        memset(plc, 0, sizeof(*plc));
                    447:                        plc->next = NULL;
                    448:                        plc->pos = s.tok;
                    449:                        plc->len = s.cur - s.tok;
                    450:                        plc->bindno = bindno++;
                    451: 
                    452:                        if (placetail) {
                    453:                                placetail->next = plc;
                    454:                        } else {
                    455:                                placeholders = plc;
                    456:                        }
                    457:                        placetail = plc;
                    458:                }
                    459:        }
                    460: 
                    461:        if (bindno == 0) {
                    462:                /* nothing to do; good! */
                    463:                return 0;
                    464:        }
                    465: 
                    466:        /* did the query make sense to me? */
                    467:        if (query_type == (PDO_PLACEHOLDER_NAMED|PDO_PLACEHOLDER_POSITIONAL)) {
                    468:                /* they mixed both types; punt */
                    469:                pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "mixed named and positional parameters" TSRMLS_CC);
                    470:                ret = -1;
                    471:                goto clean_up;
                    472:        }
                    473: 
                    474:        if (stmt->supports_placeholders == query_type && !stmt->named_rewrite_template) {
                    475:                /* query matches native syntax */
                    476:                ret = 0;
                    477:                goto clean_up;
                    478:        }
                    479: 
                    480:        if (stmt->named_rewrite_template) {
                    481:                /* magic/hack.
                    482:                 * We we pretend that the query was positional even if
                    483:                 * it was named so that we fall into the
                    484:                 * named rewrite case below.  Not too pretty,
                    485:                 * but it works. */
                    486:                query_type = PDO_PLACEHOLDER_POSITIONAL;
                    487:        }
                    488:        
                    489:        params = stmt->bound_params;
                    490:        
                    491:        /* Do we have placeholders but no bound params */
                    492:        if (bindno && !params && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
                    493:                pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "no parameters were bound" TSRMLS_CC);
                    494:                ret = -1;
                    495:                goto clean_up;
                    496:        }
                    497: 
                    498:        if (params && bindno != zend_hash_num_elements(params) && stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
                    499:                /* extra bit of validation for instances when same params are bound more then once */
                    500:                if (query_type != PDO_PLACEHOLDER_POSITIONAL && bindno > zend_hash_num_elements(params)) {
                    501:                        int ok = 1;
                    502:                        for (plc = placeholders; plc; plc = plc->next) {
                    503:                                if (zend_hash_find(params, plc->pos, plc->len, (void**) &param) == FAILURE) {
                    504:                                        ok = 0;
                    505:                                        break;
                    506:                                }
                    507:                        }
                    508:                        if (ok) {
                    509:                                goto safe;
                    510:                        }
                    511:                }
                    512:                pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "number of bound variables does not match number of tokens" TSRMLS_CC);
                    513:                ret = -1;
                    514:                goto clean_up;
                    515:        }
                    516: safe:
                    517:        /* what are we going to do ? */
                    518:        if (stmt->supports_placeholders == PDO_PLACEHOLDER_NONE) {
                    519:                /* query generation */
                    520: 
                    521:                newbuffer_len = inquery_len;
                    522: 
                    523:                /* let's quote all the values */        
                    524:                for (plc = placeholders; plc; plc = plc->next) {
                    525:                        if (query_type == PDO_PLACEHOLDER_POSITIONAL) {
                    526:                                ret = zend_hash_index_find(params, plc->bindno, (void**) &param);
                    527:                        } else {
                    528:                                ret = zend_hash_find(params, plc->pos, plc->len, (void**) &param);
                    529:                        }
                    530:                        if (ret == FAILURE) {
                    531:                                /* parameter was not defined */
                    532:                                ret = -1;
                    533:                                pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined" TSRMLS_CC);
                    534:                                goto clean_up;
                    535:                        }
                    536:                        if (stmt->dbh->methods->quoter) {
                    537:                                if (param->param_type == PDO_PARAM_LOB && Z_TYPE_P(param->parameter) == IS_RESOURCE) {
                    538:                                        php_stream *stm;
                    539: 
                    540:                                        php_stream_from_zval_no_verify(stm, &param->parameter);
                    541:                                        if (stm) {
                    542:                                                size_t len;
                    543:                                                char *buf = NULL;
                    544:                                        
                    545:                                                len = php_stream_copy_to_mem(stm, &buf, PHP_STREAM_COPY_ALL, 0);
                    546:                                                if (!stmt->dbh->methods->quoter(stmt->dbh, buf, len, &plc->quoted, &plc->qlen,
                    547:                                                                param->param_type TSRMLS_CC)) {
                    548:                                                        /* bork */
                    549:                                                        ret = -1;
                    550:                                                        strcpy(stmt->error_code, stmt->dbh->error_code);
                    551:                                                        if (buf) {
                    552:                                                                efree(buf);
                    553:                                                        }
                    554:                                                        goto clean_up;
                    555:                                                }
                    556:                                                if (buf) {
                    557:                                                        efree(buf);
                    558:                                                }
                    559:                                        } else {
                    560:                                                pdo_raise_impl_error(stmt->dbh, stmt, "HY105", "Expected a stream resource" TSRMLS_CC);
                    561:                                                ret = -1;
                    562:                                                goto clean_up;
                    563:                                        }
                    564:                                        plc->freeq = 1;
                    565:                                } else {
                    566:                                        switch (Z_TYPE_P(param->parameter)) {
                    567:                                                case IS_NULL:
                    568:                                                        plc->quoted = "NULL";
                    569:                                                        plc->qlen = sizeof("NULL")-1;
                    570:                                                        plc->freeq = 0;
                    571:                                                        break;
                    572: 
                    573:                                                case IS_LONG:
                    574:                                                case IS_DOUBLE:
                    575:                                                        convert_to_string(param->parameter);
                    576:                                                        plc->qlen = Z_STRLEN_P(param->parameter);
                    577:                                                        plc->quoted = Z_STRVAL_P(param->parameter);
                    578:                                                        plc->freeq = 0;
                    579:                                                        break;
                    580: 
                    581:                                                case IS_BOOL:
                    582:                                                        convert_to_long(param->parameter);
                    583:                                                default:
                    584:                                                        convert_to_string(param->parameter);
                    585:                                                        if (!stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter),
                    586:                                                                        Z_STRLEN_P(param->parameter), &plc->quoted, &plc->qlen,
                    587:                                                                        param->param_type TSRMLS_CC)) {
                    588:                                                                /* bork */
                    589:                                                                ret = -1;
                    590:                                                                strcpy(stmt->error_code, stmt->dbh->error_code);
                    591:                                                                goto clean_up;
                    592:                                                        }
                    593:                                                        plc->freeq = 1;
                    594:                                        }
                    595:                                }
                    596:                        } else {
                    597:                                plc->quoted = Z_STRVAL_P(param->parameter);
                    598:                                plc->qlen = Z_STRLEN_P(param->parameter);
                    599:                        }
                    600:                        newbuffer_len += plc->qlen;
                    601:                }
                    602: 
                    603: rewrite:
                    604:                /* allocate output buffer */
                    605:                newbuffer = emalloc(newbuffer_len + 1);
                    606:                *outquery = newbuffer;
                    607: 
                    608:                /* and build the query */
                    609:                plc = placeholders;
                    610:                ptr = inquery;
                    611: 
                    612:                do {
                    613:                        t = plc->pos - ptr;
                    614:                        if (t) {
                    615:                                memcpy(newbuffer, ptr, t);
                    616:                                newbuffer += t;
                    617:                        }
                    618:                        memcpy(newbuffer, plc->quoted, plc->qlen);
                    619:                        newbuffer += plc->qlen;
                    620:                        ptr = plc->pos + plc->len;
                    621: 
                    622:                        plc = plc->next;
                    623:                } while (plc);
                    624: 
                    625:                t = (inquery + inquery_len) - ptr;
                    626:                if (t) {
                    627:                        memcpy(newbuffer, ptr, t);
                    628:                        newbuffer += t;
                    629:                }
                    630:                *newbuffer = '\0';
                    631:                *outquery_len = newbuffer - *outquery;
                    632: 
                    633:                ret = 1;
                    634:                goto clean_up;
                    635: 
                    636:        } else if (query_type == PDO_PLACEHOLDER_POSITIONAL) {
                    637:                /* rewrite ? to :pdoX */
                    638:                char *name, *idxbuf;
                    639:                const char *tmpl = stmt->named_rewrite_template ? stmt->named_rewrite_template : ":pdo%d";
                    640:                int bind_no = 1;
                    641:                
                    642:                newbuffer_len = inquery_len;
                    643: 
                    644:                if (stmt->bound_param_map == NULL) {
                    645:                        ALLOC_HASHTABLE(stmt->bound_param_map);
                    646:                        zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
                    647:                }
                    648: 
                    649:                for (plc = placeholders; plc; plc = plc->next) {
                    650:                        int skip_map = 0;
                    651:                        char *p;
                    652:                        name = estrndup(plc->pos, plc->len);
                    653: 
                    654:                        /* check if bound parameter is already available */
                    655:                        if (!strcmp(name, "?") || zend_hash_find(stmt->bound_param_map, name, plc->len + 1, (void**) &p) == FAILURE) {
                    656:                                spprintf(&idxbuf, 0, tmpl, bind_no++);
                    657:                        } else {
                    658:                                idxbuf = estrdup(p);
                    659:                                skip_map = 1;
                    660:                        }
                    661: 
                    662:                        plc->quoted = idxbuf;
                    663:                        plc->qlen = strlen(plc->quoted);
                    664:                        plc->freeq = 1;
                    665:                        newbuffer_len += plc->qlen;
                    666: 
                    667:                        if (!skip_map && stmt->named_rewrite_template) {
                    668:                                /* create a mapping */
                    669:                                zend_hash_update(stmt->bound_param_map, name, plc->len + 1, idxbuf, plc->qlen + 1, NULL);
                    670:                        }
                    671: 
                    672:                        /* map number to name */
                    673:                        zend_hash_index_update(stmt->bound_param_map, plc->bindno, idxbuf, plc->qlen + 1, NULL);
                    674:                        
                    675:                        efree(name);
                    676:                }
                    677:                                
                    678:                goto rewrite;
                    679: 
                    680:        } else {
                    681:                /* rewrite :name to ? */
                    682:                
                    683:                newbuffer_len = inquery_len;
                    684:        
                    685:                if (stmt->bound_param_map == NULL) {
                    686:                        ALLOC_HASHTABLE(stmt->bound_param_map);
                    687:                        zend_hash_init(stmt->bound_param_map, 13, NULL, NULL, 0);
                    688:                }
                    689:                
                    690:                for (plc = placeholders; plc; plc = plc->next) {
                    691:                        char *name;
                    692:                        
                    693:                        name = estrndup(plc->pos, plc->len);
                    694:                        zend_hash_index_update(stmt->bound_param_map, plc->bindno, name, plc->len + 1, NULL);
                    695:                        efree(name);
                    696:                        plc->quoted = "?";
                    697:                        plc->qlen = 1;
                    698:                }
                    699: 
                    700:                goto rewrite;
                    701:        }
                    702: 
                    703: clean_up:
                    704: 
                    705:        while (placeholders) {
                    706:                plc = placeholders;
                    707:                placeholders = plc->next;
                    708: 
                    709:                if (plc->freeq) {
                    710:                        efree(plc->quoted);
                    711:                }
                    712: 
                    713:                efree(plc);
                    714:        }
                    715: 
                    716:        return ret;
                    717: }
                    718: 
                    719: #if 0
                    720: int old_pdo_parse_params(pdo_stmt_t *stmt, char *inquery, int inquery_len, char **outquery, 
                    721:                int *outquery_len TSRMLS_DC)
                    722: {
                    723:        Scanner s;
                    724:        char *ptr;
                    725:        int t;
                    726:        int bindno = 0;
                    727:        int newbuffer_len;
                    728:        int padding;
                    729:        HashTable *params = stmt->bound_params;
                    730:        struct pdo_bound_param_data *param;
                    731:        /* allocate buffer for query with expanded binds, ptr is our writing pointer */
                    732:        newbuffer_len = inquery_len;
                    733: 
                    734:        /* calculate the possible padding factor due to quoting */
                    735:        if(stmt->dbh->max_escaped_char_length) {
                    736:                padding = stmt->dbh->max_escaped_char_length;
                    737:        } else {
                    738:                padding = 3;
                    739:        }
                    740:        if(params) {
                    741:                zend_hash_internal_pointer_reset(params);
                    742:                while (SUCCESS == zend_hash_get_current_data(params, (void**)&param)) {
                    743:                        if(param->parameter) {
                    744:                                convert_to_string(param->parameter);
                    745:                                /* accomodate a string that needs to be fully quoted
                    746:                    bind placeholders are at least 2 characters, so
                    747:                    the accomodate their own "'s
                    748:                 */
                    749:                                newbuffer_len += padding * Z_STRLEN_P(param->parameter);
                    750:                        }
                    751:                        zend_hash_move_forward(params);
                    752:                }
                    753:        }
                    754:        *outquery = (char *) emalloc(newbuffer_len + 1);
                    755:        *outquery_len = 0;
                    756: 
                    757:        ptr = *outquery;
                    758:        s.cur = inquery;
                    759:        while((t = scan(&s)) != PDO_PARSER_EOI) {
                    760:                if(t == PDO_PARSER_TEXT) {
                    761:                        memcpy(ptr, s.tok, s.cur - s.tok);
                    762:                        ptr += (s.cur - s.tok);
                    763:                        *outquery_len += (s.cur - s.tok);
                    764:                }
                    765:                else if(t == PDO_PARSER_BIND) {
                    766:                        if(!params) { 
                    767:                                /* error */
                    768:                                efree(*outquery);
                    769:                                *outquery = NULL;
                    770:                                return (int) (s.cur - inquery);
                    771:                        }
                    772:                        /* lookup bind first via hash and then index */
                    773:                        /* stupid keys need to be null-terminated, even though we know their length */
                    774:                        if((SUCCESS == zend_hash_find(params, s.tok, s.cur-s.tok,(void **)&param))  
                    775:                            ||
                    776:                           (SUCCESS == zend_hash_index_find(params, bindno, (void **)&param))) 
                    777:                        {
                    778:                                char *quotedstr;
                    779:                                int quotedstrlen;
                    780:                                /* restore the in-string key, doesn't need null-termination here */
                    781:                                /* currently everything is a string here */
                    782:                                
                    783:                                /* quote the bind value if necessary */
                    784:                                if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), 
                    785:                                        Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen TSRMLS_CC))
                    786:                                {
                    787:                                        memcpy(ptr, quotedstr, quotedstrlen);
                    788:                                        ptr += quotedstrlen;
                    789:                                        *outquery_len += quotedstrlen;
                    790:                                        efree(quotedstr);
                    791:                                } else {
                    792:                                        memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter));
                    793:                                        ptr += Z_STRLEN_P(param->parameter);
                    794:                                        *outquery_len += (Z_STRLEN_P(param->parameter));
                    795:                                }
                    796:                        }
                    797:                        else {
                    798:                                /* error and cleanup */
                    799:                                efree(*outquery);
                    800:                                *outquery = NULL;
                    801:                                return (int) (s.cur - inquery);
                    802:                        }
                    803:                        bindno++;
                    804:                }
                    805:                else if(t == PDO_PARSER_BIND_POS) {
                    806:                        if(!params) { 
                    807:                                /* error */
                    808:                                efree(*outquery);
                    809:                                *outquery = NULL;
                    810:                                return (int) (s.cur - inquery);
                    811:                        }
                    812:                        /* lookup bind by index */
                    813:                        if(SUCCESS == zend_hash_index_find(params, bindno, (void **)&param)) 
                    814:                        {
                    815:                                char *quotedstr;
                    816:                                int quotedstrlen;
                    817:                                /* currently everything is a string here */
                    818:                                
                    819:                                /* quote the bind value if necessary */
                    820:                                if(stmt->dbh->methods->quoter(stmt->dbh, Z_STRVAL_P(param->parameter), 
                    821:                                        Z_STRLEN_P(param->parameter), &quotedstr, &quotedstrlen TSRMLS_CC))
                    822:                                {
                    823:                                        memcpy(ptr, quotedstr, quotedstrlen);
                    824:                                        ptr += quotedstrlen;
                    825:                                        *outquery_len += quotedstrlen;
                    826:                                        efree(quotedstr);
                    827:                                } else {
                    828:                                        memcpy(ptr, Z_STRVAL_P(param->parameter), Z_STRLEN_P(param->parameter));
                    829:                                        ptr += Z_STRLEN_P(param->parameter);
                    830:                                        *outquery_len += (Z_STRLEN_P(param->parameter));
                    831:                                }
                    832:                        }
                    833:                        else {
                    834:                                /* error and cleanup */
                    835:                                efree(*outquery);
                    836:                                *outquery = NULL;
                    837:                                return (int) (s.cur - inquery);
                    838:                        }
                    839:                        bindno++;
                    840:                }
                    841:        }       
                    842:        *ptr = '\0';
                    843:        return 0;
                    844: }
                    845: #endif
                    846: 
                    847: /*
                    848:  * Local variables:
                    849:  * tab-width: 4
                    850:  * c-basic-offset: 4
                    851:  * End:
                    852:  * vim600: noet sw=4 ts=4 fdm=marker ft=c
                    853:  * vim<600: noet sw=4 ts=4
                    854:  */

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