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

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

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