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

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: 
        !            20: /* $Id: pdo_sql_parser.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            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>