sql.y 19.5 KB
Newer Older
1 2 3 4 5
%{

/*
 * Implementation of the Microsoft Installer (msi.dll)
 *
6
 * Copyright 2002-2004 Mike McCormack for CodeWeavers
7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
20
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 22 23 24
 */


#include "config.h"
25 26

#include <stdarg.h>
27 28
#include <stdio.h>
#include <stdlib.h>
29 30 31

#include "windef.h"
#include "winbase.h"
32
#include "query.h"
33
#include "wine/list.h"
34 35 36 37 38
#include "wine/debug.h"

#define YYLEX_PARAM info
#define YYPARSE_PARAM info

39
static int sql_error(const char *str);
40 41 42

WINE_DEFAULT_DEBUG_CHANNEL(msi);

43
typedef struct tag_SQL_input
44 45 46 47 48
{
    MSIDATABASE *db;
    LPCWSTR command;
    DWORD n, len;
    MSIVIEW **view;  /* view structure for the resulting query */
49
    struct list *mem;
50
} SQL_input;
51

52
static LPWSTR SQL_getstring( void *info, const struct sql_str *str );
53
static INT SQL_getint( void *info );
54
static int sql_lex( void *SQL_lval, SQL_input *info );
55

56
static LPWSTR parser_add_table( LPWSTR list, LPWSTR table );
57
static void *parser_alloc( void *info, unsigned int sz );
58
static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column );
59

60
static BOOL SQL_MarkPrimaryKeys( column_info *cols, column_info *keys);
61 62

static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );
63
static struct expr * EXPR_unary( void *info, struct expr *l, UINT op );
64
static struct expr * EXPR_column( void *info, const column_info *column );
65
static struct expr * EXPR_ival( void *info, int val );
66
static struct expr * EXPR_sval( void *info, const struct sql_str *str );
67
static struct expr * EXPR_wildcard( void *info );
68 69 70 71 72 73 74

%}

%pure-parser

%union
{
75
    struct sql_str str;
76
    LPWSTR string;
77
    column_info *column_list;
78
    MSIVIEW *query;
79
    struct expr *expr;
80
    USHORT column_type;
81
    int integer;
82 83
}

84
%token TK_ALTER TK_AND TK_BY TK_CHAR TK_COMMA TK_CREATE TK_DELETE
85
%token TK_DISTINCT TK_DOT TK_EQ TK_FREE TK_FROM TK_GE TK_GT TK_HOLD TK_ADD
86 87
%token <str> TK_ID
%token TK_ILLEGAL TK_INSERT TK_INT
88
%token <str> TK_INTEGER
89 90 91 92
%token TK_INTO TK_IS TK_KEY TK_LE TK_LONG TK_LONGCHAR TK_LP TK_LT
%token TK_LOCALIZABLE TK_MINUS TK_NE TK_NOT TK_NULL
%token TK_OBJECT TK_OR TK_ORDER TK_PRIMARY TK_RP
%token TK_SELECT TK_SET TK_SHORT TK_SPACE TK_STAR
93
%token <str> TK_STRING
94
%token TK_TABLE TK_TEMPORARY TK_UPDATE TK_VALUES TK_WHERE TK_WILDCARD
95

96 97 98 99 100 101
/*
 * These are extra tokens used by the lexer but never seen by the
 * parser.  We put them in a rule so that the parser generator will
 * add them to the parse.h output file.
 *
 */
102 103 104
%nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION
          COLUMN AGG_FUNCTION.

105
%type <string> table tablelist id
106
%type <column_list> selcollist column column_and_type column_def table_def
107
%type <column_list> column_assignment update_assign_list constlist
108
%type <query> query from fromtable selectfrom unorderedsel
109
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter
110
%type <expr> expr val column_val const_val
111
%type <column_type> column_type data_type data_type_l data_count
112
%type <integer> number alterop
113

114 115 116 117
/* Reference: http://mates.ms.mff.cuni.cz/oracle/doc/ora815nt/server.815/a67779/operator.htm */
%left TK_OR
%left TK_AND
%left TK_NOT
118
%left TK_EQ TK_NE TK_LT TK_GT TK_LE TK_GE TK_LIKE
119 120
%right TK_NEGATION

121 122
%%

123 124
query:
    onequery
125 126 127 128
    {
        SQL_input* sql = (SQL_input*) info;
        *sql->view = $1;
    }
129 130 131 132
    ;

onequery:
    oneselect
133
  | onecreate
134
  | oneinsert
135
  | oneupdate
136
  | onedelete
137
  | onealter
138 139 140
    ;

oneinsert:
Mike McCormack's avatar
Mike McCormack committed
141
    TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP
142 143
        {
            SQL_input *sql = (SQL_input*) info;
144
            MSIVIEW *insert = NULL;
145

146
            INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE );
147 148 149 150
            if( !insert )
                YYABORT;
            $$ = insert;
        }
151
  | TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMPORARY
152 153
        {
            SQL_input *sql = (SQL_input*) info;
154
            MSIVIEW *insert = NULL;
155

156
            INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE );
157 158 159 160
            if( !insert )
                YYABORT;
            $$ = insert;
        }
161 162 163 164 165 166
    ;

onecreate:
    TK_CREATE TK_TABLE table TK_LP table_def TK_RP
        {
            SQL_input* sql = (SQL_input*) info;
167
            MSIVIEW *create = NULL;
168 169 170 171

            if( !$5 )
                YYABORT;
            CREATE_CreateView( sql->db, &create, $3, $5, FALSE );
172 173
            if( !create )
                YYABORT;
174 175 176 177 178
            $$ = create;
        }
  | TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD
        {
            SQL_input* sql = (SQL_input*) info;
179
            MSIVIEW *create = NULL;
180 181 182 183

            if( !$5 )
                YYABORT;
            CREATE_CreateView( sql->db, &create, $3, $5, TRUE );
184 185
            if( !create )
                YYABORT;
186 187 188 189
            $$ = create;
        }
    ;

190 191 192 193
oneupdate:
    TK_UPDATE table TK_SET update_assign_list TK_WHERE expr
        {
            SQL_input* sql = (SQL_input*) info;
194
            MSIVIEW *update = NULL;
195

196
            UPDATE_CreateView( sql->db, &update, $2, $4, $6 );
197 198
            if( !update )
                YYABORT;
199 200
            $$ = update;
        }
201 202 203 204 205 206 207 208 209 210
  | TK_UPDATE table TK_SET update_assign_list
        {
            SQL_input* sql = (SQL_input*) info;
            MSIVIEW *update = NULL;

            UPDATE_CreateView( sql->db, &update, $2, $4, NULL );
            if( !update )
                YYABORT;
            $$ = update;
        }
211 212
    ;

213 214 215 216
onedelete:
    TK_DELETE from
        {
            SQL_input* sql = (SQL_input*) info;
217
            MSIVIEW *delete = NULL;
218 219

            DELETE_CreateView( sql->db, &delete, $2 );
220 221
            if( !delete )
                YYABORT;
222 223 224 225
            $$ = delete;
        }
    ;

226 227 228 229 230 231
onealter:
    TK_ALTER TK_TABLE table alterop
        {
            SQL_input* sql = (SQL_input*) info;
            MSIVIEW *alter = NULL;

232
            ALTER_CreateView( sql->db, &alter, $3, NULL, $4 );
233 234
            if( !alter )
                YYABORT;
235 236 237 238 239 240 241 242 243 244
            $$ = alter;
        }
  | TK_ALTER TK_TABLE table TK_ADD column_and_type
        {
            SQL_input *sql = (SQL_input *)info;
            MSIVIEW *alter = NULL;

            ALTER_CreateView( sql->db, &alter, $3, $5, 0 );
            if (!alter)
                YYABORT;
245 246
            $$ = alter;
        }
247 248 249 250 251 252 253 254 255 256
  | TK_ALTER TK_TABLE table TK_ADD column_and_type TK_HOLD
        {
            SQL_input *sql = (SQL_input *)info;
            MSIVIEW *alter = NULL;

            ALTER_CreateView( sql->db, &alter, $3, $5, 1 );
            if (!alter)
                YYABORT;
            $$ = alter;
        }
257 258 259 260 261 262 263 264 265 266 267 268 269
    ;

alterop:
    TK_HOLD
        {
            $$ = 1;
        }
  | TK_FREE
        {
            $$ = -1;
        }
  ;

270 271 272 273 274 275 276 277 278 279 280
table_def:
    column_def TK_PRIMARY TK_KEY selcollist
        {
            if( SQL_MarkPrimaryKeys( $1, $4 ) )
                $$ = $1;
            else
                $$ = NULL;
        }
    ;

column_def:
281
    column_def TK_COMMA column_and_type
282
        {
283
            column_info *ci;
284 285 286 287

            for( ci = $1; ci->next; ci = ci->next )
                ;

288
            ci->next = $3;
289
            $$ = $1;
290
        }
291
  | column_and_type
292
        {
293 294 295 296 297 298 299 300
            $$ = $1;
        }
    ;

column_and_type:
    column column_type
        {
            $$ = $1;
301
            $$->type = ($2 | MSITYPE_VALID);
302
            $$->temporary = $2 & MSITYPE_TEMPORARY ? TRUE : FALSE;
303 304 305 306
        }
    ;

column_type:
307 308
    data_type_l
        {
309
            $$ = $1;
310 311 312
        }
  | data_type_l TK_LOCALIZABLE
        {
313
            $$ = $1 | MSITYPE_LOCALIZABLE;
314
        }
315 316
  | data_type_l TK_TEMPORARY
        {
317
            $$ = $1 | MSITYPE_TEMPORARY;
318
        }
319 320 321
    ;

data_type_l:
322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
    data_type
        {
            $$ |= MSITYPE_NULLABLE;
        }
  | data_type TK_NOT TK_NULL
        {
            $$ = $1;
        }
    ;

data_type:
    TK_CHAR
        {
            $$ = MSITYPE_STRING | 1;
        }
  | TK_CHAR TK_LP data_count TK_RP
        {
339
            $$ = MSITYPE_STRING | 0x400 | $3;
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358
        }
  | TK_LONGCHAR
        {
            $$ = 2;
        }
  | TK_SHORT
        {
            $$ = 2;
        }
  | TK_INT
        {
            $$ = 2;
        }
  | TK_LONG
        {
            $$ = 4;
        }
  | TK_OBJECT
        {
359
            $$ = MSITYPE_STRING | MSITYPE_VALID;
360 361 362 363
        }
    ;

data_count:
364
    number
365
        {
366
            if( ( $1 > 255 ) || ( $1 < 0 ) )
367
                YYABORT;
368
            $$ = $1;
369 370 371
        }
    ;

372 373 374
oneselect:
    unorderedsel TK_ORDER TK_BY selcollist
        {
375
            UINT r;
376 377

            if( $4 )
378 379 380 381 382 383 384
            {
                r = $1->ops->sort( $1, $4 );
                if ( r != ERROR_SUCCESS)
                    YYABORT;
            }

            $$ = $1;
385 386 387 388 389
        }
  | unorderedsel
    ;

unorderedsel:
390 391 392 393 394
    TK_SELECT selectfrom
        {
            $$ = $2;
        }
  | TK_SELECT TK_DISTINCT selectfrom
395
        {
396
            SQL_input* sql = (SQL_input*) info;
397
            UINT r;
398 399

            $$ = NULL;
400 401 402 403
            r = DISTINCT_CreateView( sql->db, &$$, $3 );
            if (r != ERROR_SUCCESS)
            {
                $3->ops->delete($3);
404
                YYABORT;
405
            }
406
        }
407 408 409
    ;

selectfrom:
410
    selcollist from
411
        {
412
            SQL_input* sql = (SQL_input*) info;
413
            UINT r;
414

415 416
            $$ = NULL;
            if( $1 )
417 418 419 420 421 422 423 424
            {
                r = SELECT_CreateView( sql->db, &$$, $2, $1 );
                if (r != ERROR_SUCCESS)
                {
                    $2->ops->delete($2);
                    YYABORT;
                }
            }
425 426
            else
                $$ = $2;
427 428 429 430
        }
    ;

selcollist:
431
    column
432
  | column TK_COMMA selcollist
433
        {
434
            $1->next = $3;
435 436 437 438 439 440 441 442
        }
  | TK_STAR
        {
            $$ = NULL;
        }
    ;

from:
443 444
    fromtable
  | fromtable TK_WHERE expr
445
        {
446
            SQL_input* sql = (SQL_input*) info;
447
            UINT r;
448 449

            $$ = NULL;
450
            r = WHERE_CreateView( sql->db, &$$, $1, $3 );
451 452 453
            if( r != ERROR_SUCCESS )
            {
                $1->ops->delete( $1 );
454
                YYABORT;
455
            }
456
        }
457 458 459 460 461
    ;

fromtable:
    TK_FROM table
        {
462
            SQL_input* sql = (SQL_input*) info;
463 464 465
            UINT r;

            $$ = NULL;
466 467
            r = TABLE_CreateView( sql->db, $2, &$$ );
            if( r != ERROR_SUCCESS || !$$ )
468 469
                YYABORT;
        }
470
  | TK_FROM tablelist
471 472 473 474
        {
            SQL_input* sql = (SQL_input*) info;
            UINT r;

475 476
            r = JOIN_CreateView( sql->db, &$$, $2 );
            msi_free( $2 );
477 478 479
            if( r != ERROR_SUCCESS )
                YYABORT;
        }
480 481
    ;

482 483 484 485 486 487 488 489 490 491 492 493 494 495
tablelist:
    table
        {
            $$ = strdupW($1);
        }
  |
    table TK_COMMA tablelist
        {
            $$ = parser_add_table($3, $1);
            if (!$$)
                YYABORT;
        }
    ;

496 497 498 499
expr:
    TK_LP expr TK_RP
        {
            $$ = $2;
500 501
            if( !$$ )
                YYABORT;
502 503 504
        }
  | expr TK_AND expr
        {
505
            $$ = EXPR_complex( info, $1, OP_AND, $3 );
506 507
            if( !$$ )
                YYABORT;
508 509 510
        }
  | expr TK_OR expr
        {
511
            $$ = EXPR_complex( info, $1, OP_OR, $3 );
512 513
            if( !$$ )
                YYABORT;
514 515 516
        }
  | column_val TK_EQ val
        {
517
            $$ = EXPR_complex( info, $1, OP_EQ, $3 );
518 519
            if( !$$ )
                YYABORT;
520 521 522
        }
  | column_val TK_GT val
        {
523
            $$ = EXPR_complex( info, $1, OP_GT, $3 );
524 525
            if( !$$ )
                YYABORT;
526 527 528
        }
  | column_val TK_LT val
        {
529
            $$ = EXPR_complex( info, $1, OP_LT, $3 );
530 531
            if( !$$ )
                YYABORT;
532 533 534
        }
  | column_val TK_LE val
        {
535
            $$ = EXPR_complex( info, $1, OP_LE, $3 );
536 537
            if( !$$ )
                YYABORT;
538 539 540
        }
  | column_val TK_GE val
        {
541
            $$ = EXPR_complex( info, $1, OP_GE, $3 );
542 543
            if( !$$ )
                YYABORT;
544 545 546
        }
  | column_val TK_NE val
        {
547
            $$ = EXPR_complex( info, $1, OP_NE, $3 );
548 549
            if( !$$ )
                YYABORT;
550 551 552
        }
  | column_val TK_IS TK_NULL
        {
553
            $$ = EXPR_unary( info, $1, OP_ISNULL );
554 555
            if( !$$ )
                YYABORT;
556 557 558
        }
  | column_val TK_IS TK_NOT TK_NULL
        {
559
            $$ = EXPR_unary( info, $1, OP_NOTNULL );
560 561
            if( !$$ )
                YYABORT;
562 563 564 565 566
        }
    ;

val:
    column_val
567
  | const_val
568
    ;
569 570 571 572

constlist:
    const_val
        {
573 574
            $$ = parser_alloc_column( info, NULL, NULL );
            if( !$$ )
575
                YYABORT;
576
            $$->val = $1;
577
        }
578
  | const_val TK_COMMA constlist
579
        {
580 581
            $$ = parser_alloc_column( info, NULL, NULL );
            if( !$$ )
582
                YYABORT;
583 584
            $$->val = $1;
            $$->next = $3;
585
        }
586 587 588 589 590 591 592
    ;

update_assign_list:
    column_assignment
  | column_assignment TK_COMMA update_assign_list
        {
            $$ = $1;
593
            $$->next = $3;
594 595 596 597 598 599
        }
    ;

column_assignment:
    column TK_EQ const_val
        {
600 601
            $$ = $1;
            $$->val = $3;
602 603
        }
    ;
604 605

const_val:
606
    number
607
        {
608
            $$ = EXPR_ival( info, $1 );
609 610
            if( !$$ )
                YYABORT;
611
        }
612
  | TK_MINUS number %prec TK_NEGATION
613
        {
614
            $$ = EXPR_ival( info, -$2 );
615 616
            if( !$$ )
                YYABORT;
617 618 619
        }
  | TK_STRING
        {
620
            $$ = EXPR_sval( info, &$1 );
621 622
            if( !$$ )
                YYABORT;
623
        }
Mike McCormack's avatar
Mike McCormack committed
624 625
  | TK_WILDCARD
        {
626
            $$ = EXPR_wildcard( info );
627 628
            if( !$$ )
                YYABORT;
Mike McCormack's avatar
Mike McCormack committed
629
        }
630 631 632
    ;

column_val:
633
    column
634
        {
635
            $$ = EXPR_column( info, $1 );
636 637
            if( !$$ )
                YYABORT;
638 639 640 641
        }
    ;

column:
642
    table TK_DOT id
643
        {
644 645 646
            $$ = parser_alloc_column( info, $1, $3 );
            if( !$$ )
                YYABORT;
647
        }
648
  | id
649
        {
650 651 652
            $$ = parser_alloc_column( info, NULL, $1 );
            if( !$$ )
                YYABORT;
653 654 655 656
        }
    ;

table:
657
    id
658 659 660 661 662
        {
            $$ = $1;
        }
    ;

663
id:
664 665
    TK_ID
        {
666 667 668
            $$ = SQL_getstring( info, &$1 );
            if( !$$ )
                YYABORT;
669 670 671
        }
    ;

672 673 674 675 676 677 678
number:
    TK_INTEGER
        {
            $$ = SQL_getint( info );
        }
    ;

679 680
%%

681 682 683 684 685 686 687 688 689 690 691 692 693
static LPWSTR parser_add_table(LPWSTR list, LPWSTR table)
{
    DWORD size = lstrlenW(list) + lstrlenW(table) + 2;
    static const WCHAR space[] = {' ',0};

    list = msi_realloc(list, size * sizeof(WCHAR));
    if (!list) return NULL;

    lstrcatW(list, space);
    lstrcatW(list, table);
    return list;
}

694 695 696 697 698
static void *parser_alloc( void *info, unsigned int sz )
{
    SQL_input* sql = (SQL_input*) info;
    struct list *mem;

699
    mem = msi_alloc( sizeof (struct list) + sz );
700 701 702 703
    list_add_tail( sql->mem, mem );
    return &mem[1];
}

704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR column )
{
    column_info *col;

    col = parser_alloc( info, sizeof (*col) );
    if( col )
    {
        col->table = table;
        col->column = column;
        col->val = NULL;
        col->type = 0;
        col->next = NULL;
    }

    return col;
}

721
static int sql_lex( void *SQL_lval, SQL_input *sql )
722 723
{
    int token;
724
    struct sql_str * str = SQL_lval;
725 726 727 728 729 730 731

    do
    {
        sql->n += sql->len;
        if( ! sql->command[sql->n] )
            return 0;  /* end of input */

732
        /* TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); */
733 734 735
        sql->len = sqliteGetToken( &sql->command[sql->n], &token );
        if( sql->len==0 )
            break;
736 737
        str->data = &sql->command[sql->n];
        str->len = sql->len;
738 739 740
    }
    while( token == TK_SPACE );

741
    /* TRACE("token : %d (%s)\n", token, debugstr_wn(&sql->command[sql->n], sql->len)); */
742

743 744 745
    return token;
}

746
LPWSTR SQL_getstring( void *info, const struct sql_str *strdata )
747
{
748 749
    LPCWSTR p = strdata->data;
    UINT len = strdata->len;
750 751 752
    LPWSTR str;

    /* if there's quotes, remove them */
753
    if( ( (p[0]=='`') && (p[len-1]=='`') ) ||
754
        ( (p[0]=='\'') && (p[len-1]=='\'') ) )
755 756 757 758
    {
        p++;
        len -= 2;
    }
759 760
    str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
    if( !str )
761
        return str;
762
    memcpy( str, p, len*sizeof(WCHAR) );
763 764 765 766 767
    str[len]=0;

    return str;
}

768
INT SQL_getint( void *info )
769
{
770
    SQL_input* sql = (SQL_input*) info;
771
    LPCWSTR p = &sql->command[sql->n];
772 773 774 775 776 777 778 779 780 781 782
    INT i, r = 0;

    for( i=0; i<sql->len; i++ )
    {
        if( '0' > p[i] || '9' < p[i] )
        {
            ERR("should only be numbers here!\n");
            break;
        }
        r = (p[i]-'0') + r*10;
    }
783

784
    return r;
785 786
}

787
static int sql_error( const char *str )
788 789 790 791
{
    return 0;
}

792
static struct expr * EXPR_wildcard( void *info )
793
{
794
    struct expr *e = parser_alloc( info, sizeof *e );
795 796 797 798 799 800 801
    if( e )
    {
        e->type = EXPR_WILDCARD;
    }
    return e;
}

802
static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )
803
{
804
    struct expr *e = parser_alloc( info, sizeof *e );
805 806 807 808 809 810 811 812 813 814
    if( e )
    {
        e->type = EXPR_COMPLEX;
        e->u.expr.left = l;
        e->u.expr.op = op;
        e->u.expr.right = r;
    }
    return e;
}

815 816 817 818 819 820 821 822 823 824 825 826 827
static struct expr * EXPR_unary( void *info, struct expr *l, UINT op )
{
    struct expr *e = parser_alloc( info, sizeof *e );
    if( e )
    {
        e->type = EXPR_UNARY;
        e->u.expr.left = l;
        e->u.expr.op = op;
        e->u.expr.right = NULL;
    }
    return e;
}

828
static struct expr * EXPR_column( void *info, const column_info *column )
829
{
830
    struct expr *e = parser_alloc( info, sizeof *e );
831 832 833
    if( e )
    {
        e->type = EXPR_COLUMN;
834
        e->u.sval = column->column;
835 836 837 838
    }
    return e;
}

839
static struct expr * EXPR_ival( void *info, int val )
840
{
841
    struct expr *e = parser_alloc( info, sizeof *e );
842 843 844
    if( e )
    {
        e->type = EXPR_IVAL;
845
        e->u.ival = val;
846 847 848 849
    }
    return e;
}

850
static struct expr * EXPR_sval( void *info, const struct sql_str *str )
851
{
852
    struct expr *e = parser_alloc( info, sizeof *e );
853 854 855
    if( e )
    {
        e->type = EXPR_SVAL;
856
        e->u.sval = SQL_getstring( info, str );
857 858 859 860
    }
    return e;
}

861 862
static BOOL SQL_MarkPrimaryKeys( column_info *cols,
                                 column_info *keys )
863
{
864
    column_info *k;
865 866 867 868
    BOOL found = TRUE;

    for( k = keys; k && found; k = k->next )
    {
869
        column_info *c;
870 871 872 873

        found = FALSE;
        for( c = cols; c && !found; c = c->next )
        {
874
             if( lstrcmpW( k->column, c->column ) )
875 876 877 878 879 880 881 882 883
                 continue;
             c->type |= MSITYPE_KEY;
             found = TRUE;
        }
    }

    return found;
}

884 885
UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
                   struct list *mem )
886
{
887
    SQL_input sql;
888 889 890 891 892 893 894 895 896
    int r;

    *phview = NULL;

    sql.db = db;
    sql.command = command;
    sql.n = 0;
    sql.len = 0;
    sql.view = phview;
897
    sql.mem = mem;
898

899
    r = sql_parse(&sql);
900 901 902 903

    TRACE("Parse returned %d\n", r);
    if( r )
    {
904
        *sql.view = NULL;
905 906 907 908 909
        return ERROR_BAD_QUERY_SYNTAX;
    }

    return ERROR_SUCCESS;
}