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

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

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