Sync to Wine-20050524:
[reactos.git] / reactos / lib / msi / sql.y
index 5bd2c7d..7a0edd9 100644 (file)
@@ -30,6 +30,7 @@
 #include "windef.h"\r
 #include "winbase.h"\r
 #include "query.h"\r
+#include "wine/list.h"\r
 #include "wine/debug.h"\r
 #include "wine/unicode.h"\r
 \r
@@ -46,25 +47,22 @@ typedef struct tag_SQL_input
     LPCWSTR command;\r
     DWORD n, len;\r
     MSIVIEW **view;  /* view structure for the resulting query */\r
+    struct list *mem;\r
 } SQL_input;\r
 \r
-static LPWSTR SQL_getstring( struct sql_str *str );\r
-static INT SQL_getint( SQL_input *sql );\r
-static int SQL_lex( void *SQL_lval, SQL_input *info);\r
+static LPWSTR SQL_getstring( void *info, struct sql_str *str );\r
+static INT SQL_getint( void *info );\r
+static int SQL_lex( void *SQL_lval, SQL_input *info );\r
 \r
-static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, \r
-                               string_list *columns );\r
-static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, \r
-                             string_list *columns );\r
+static void *parser_alloc( void *info, unsigned int sz );\r
 \r
-static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,\r
-                                 string_list *keys);\r
+static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, string_list *keys);\r
 \r
-static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r );\r
-static struct expr * EXPR_column( LPWSTR );\r
-static struct expr * EXPR_ival( struct sql_str *, int sign);\r
-static struct expr * EXPR_sval( struct sql_str *);\r
-static struct expr * EXPR_wildcard();\r
+static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );\r
+static struct expr * EXPR_column( void *info, LPWSTR column );\r
+static struct expr * EXPR_ival( void *info, struct sql_str *, int sign );\r
+static struct expr * EXPR_sval( void *info, struct sql_str * );\r
+static struct expr * EXPR_wildcard( void *info );\r
 \r
 %}\r
 \r
@@ -127,10 +125,10 @@ static struct expr * EXPR_wildcard();
 %nonassoc END_OF_FILE ILLEGAL SPACE UNCLOSED_STRING COMMENT FUNCTION\r
           COLUMN AGG_FUNCTION.\r
 \r
-%type <string> column table string_or_id\r
+%type <string> column table id\r
 %type <column_list> selcollist\r
-%type <query> from unorderedsel oneselect onequery onecreate oneinsert\r
-%type <query> oneupdate onedelete\r
+%type <query> query from fromtable unorderedsel selectfrom\r
+%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert\r
 %type <expr> expr val column_val const_val\r
 %type <column_type> column_type data_type data_type_l data_count\r
 %type <column_info> column_def table_def\r
@@ -139,51 +137,44 @@ static struct expr * EXPR_wildcard();
 \r
 %%\r
 \r
-onequery:\r
-    oneselect\r
+query:\r
+    onequery\r
     {\r
         SQL_input* sql = (SQL_input*) info;\r
         *sql->view = $1;\r
     }\r
+    ;\r
+\r
+onequery:\r
+    oneselect\r
   | onecreate\r
-    {\r
-        SQL_input* sql = (SQL_input*) info;\r
-        *sql->view = $1;\r
-    }\r
   | oneinsert\r
-    {\r
-        SQL_input* sql = (SQL_input*) info;\r
-        *sql->view = $1;\r
-    }\r
   | oneupdate\r
-    {\r
-        SQL_input* sql = (SQL_input*) info;\r
-        *sql->view = $1;\r
-    }\r
   | onedelete\r
-    {\r
-        SQL_input* sql = (SQL_input*) info;\r
-        *sql->view = $1;\r
-    }\r
     ;\r
 \r
 oneinsert:\r
     TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP\r
-    {\r
-        SQL_input *sql = (SQL_input*) info;\r
-        MSIVIEW *insert = NULL; \r
+        {\r
+            SQL_input *sql = (SQL_input*) info;\r
+            MSIVIEW *insert = NULL; \r
+            UINT r;\r
 \r
-        INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE ); \r
-        $$ = insert;\r
-    }\r
+            r = INSERT_CreateView( sql->db, &insert, $3, $5, $9, FALSE ); \r
+            if( !insert )\r
+                YYABORT;\r
+            $$ = insert;\r
+        }\r
   | TK_INSERT TK_INTO table TK_LP selcollist TK_RP TK_VALUES TK_LP constlist TK_RP TK_TEMP\r
-    {\r
-        SQL_input *sql = (SQL_input*) info;\r
-        MSIVIEW *insert = NULL; \r
+        {\r
+            SQL_input *sql = (SQL_input*) info;\r
+            MSIVIEW *insert = NULL; \r
 \r
-        INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE ); \r
-        $$ = insert;\r
-    }\r
+            INSERT_CreateView( sql->db, &insert, $3, $5, $9, TRUE ); \r
+            if( !insert )\r
+                YYABORT;\r
+            $$ = insert;\r
+        }\r
     ;\r
 \r
 onecreate:\r
@@ -195,6 +186,8 @@ onecreate:
             if( !$5 )\r
                 YYABORT;\r
             CREATE_CreateView( sql->db, &create, $3, $5, FALSE );\r
+            if( !create )\r
+                YYABORT;\r
             $$ = create;\r
         }\r
   | TK_CREATE TK_TABLE table TK_LP table_def TK_RP TK_HOLD\r
@@ -205,6 +198,8 @@ onecreate:
             if( !$5 )\r
                 YYABORT;\r
             CREATE_CreateView( sql->db, &create, $3, $5, TRUE );\r
+            if( !create )\r
+                YYABORT;\r
             $$ = create;\r
         }\r
     ;\r
@@ -216,6 +211,8 @@ oneupdate:
             MSIVIEW *update = NULL; \r
 \r
             UPDATE_CreateView( sql->db, &update, $2, &$4, $6 );\r
+            if( !update )\r
+                YYABORT;\r
             $$ = update;\r
         }\r
     ;\r
@@ -227,6 +224,8 @@ onedelete:
             MSIVIEW *delete = NULL; \r
 \r
             DELETE_CreateView( sql->db, &delete, $2 );\r
+            if( !delete )\r
+                YYABORT;\r
             $$ = delete;\r
         }\r
     ;\r
@@ -342,45 +341,46 @@ oneselect:
         {\r
             SQL_input* sql = (SQL_input*) info;\r
 \r
-            if( !$1 )\r
-                YYABORT;\r
+            $$ = NULL;\r
             if( $4 )\r
-                $$ = do_order_by( sql->db, $1, $4 );\r
+                ORDER_CreateView( sql->db, &$$, $1, $4 );\r
             else\r
                 $$ = $1;\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | unorderedsel\r
     ;\r
 \r
 unorderedsel:\r
-    TK_SELECT selcollist from \r
+    TK_SELECT selectfrom\r
+        {\r
+            $$ = $2;\r
+        }\r
+  | TK_SELECT TK_DISTINCT selectfrom\r
         {\r
             SQL_input* sql = (SQL_input*) info;\r
-            if( !$3 )\r
+\r
+            $$ = NULL;\r
+            DISTINCT_CreateView( sql->db, &$$, $3 );\r
+            if( !$$ )\r
                 YYABORT;\r
-            if( $2 )\r
-            {\r
-                $$ = do_one_select( sql->db, $3, $2 );\r
-                if( !$$ )\r
-                    YYABORT;\r
-            }\r
-            else\r
-                $$ = $3;\r
         }\r
-  | TK_SELECT TK_DISTINCT selcollist from \r
+    ;\r
+\r
+selectfrom:\r
+    selcollist from \r
         {\r
             SQL_input* sql = (SQL_input*) info;\r
-            MSIVIEW *view = $4;\r
 \r
-            if( !view )\r
+            $$ = NULL;\r
+            if( $1 )\r
+                SELECT_CreateView( sql->db, &$$, $2, $1 );\r
+            else\r
+                $$ = $2;\r
+\r
+            if( !$$ )\r
                 YYABORT;\r
-            if( $3 )\r
-            {\r
-                view = do_one_select( sql->db, view, $3 );\r
-                if( !view )\r
-                    YYABORT;\r
-            }\r
-            DISTINCT_CreateView( sql->db, & $$, view );\r
         }\r
     ;\r
 \r
@@ -418,32 +418,29 @@ selcollist:
     ;\r
 \r
 from:\r
-    TK_FROM table\r
+    fromtable\r
+  | fromtable TK_WHERE expr\r
         { \r
             SQL_input* sql = (SQL_input*) info;\r
             UINT r;\r
 \r
             $$ = NULL;\r
-            TRACE("From table: %s\n",debugstr_w($2));\r
-            r = TABLE_CreateView( sql->db, $2, & $$ );\r
-            if( r != ERROR_SUCCESS )\r
+            r = WHERE_CreateView( sql->db, &$$, $1, $3 );\r
+            if( r != ERROR_SUCCESS || !$$ )\r
                 YYABORT;\r
         }\r
-  | TK_FROM table TK_WHERE expr\r
-        { \r
+    ;\r
+\r
+fromtable:\r
+    TK_FROM table\r
+        {\r
             SQL_input* sql = (SQL_input*) info;\r
-            MSIVIEW *view = NULL;\r
             UINT r;\r
 \r
             $$ = NULL;\r
-            TRACE("From table: %s\n",debugstr_w($2));\r
-            r = TABLE_CreateView( sql->db, $2, &view );\r
-            if( r != ERROR_SUCCESS )\r
-                YYABORT;\r
-            r = WHERE_CreateView( sql->db, &view, view, $4 );\r
-            if( r != ERROR_SUCCESS )\r
+            r = TABLE_CreateView( sql->db, $2, &$$ );\r
+            if( r != ERROR_SUCCESS || !$$ )\r
                 YYABORT;\r
-            $$ = view;\r
         }\r
     ;\r
 \r
@@ -451,50 +448,74 @@ expr:
     TK_LP expr TK_RP\r
         {\r
             $$ = $2;\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_EQ column_val\r
         {\r
-            $$ = EXPR_complex( $1, OP_EQ, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_EQ, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | expr TK_AND expr\r
         {\r
-            $$ = EXPR_complex( $1, OP_AND, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_AND, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | expr TK_OR expr\r
         {\r
-            $$ = EXPR_complex( $1, OP_OR, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_OR, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_EQ val\r
         {\r
-            $$ = EXPR_complex( $1, OP_EQ, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_EQ, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_GT val\r
         {\r
-            $$ = EXPR_complex( $1, OP_GT, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_GT, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_LT val\r
         {\r
-            $$ = EXPR_complex( $1, OP_LT, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_LT, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_LE val\r
         {\r
-            $$ = EXPR_complex( $1, OP_LE, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_LE, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_GE val\r
         {\r
-            $$ = EXPR_complex( $1, OP_GE, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_GE, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_NE val\r
         {\r
-            $$ = EXPR_complex( $1, OP_NE, $3 );\r
+            $$ = EXPR_complex( info, $1, OP_NE, $3 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_IS TK_NULL\r
         {\r
-            $$ = EXPR_complex( $1, OP_ISNULL, NULL );\r
+            $$ = EXPR_complex( info, $1, OP_ISNULL, NULL );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | column_val TK_IS TK_NOT TK_NULL\r
         {\r
-            $$ = EXPR_complex( $1, OP_NOTNULL, NULL );\r
+            $$ = EXPR_complex( info, $1, OP_NOTNULL, NULL );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
     ;\r
 \r
@@ -508,24 +529,22 @@ constlist:
         {\r
             value_list *vals;\r
 \r
-            vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );\r
-            if( vals )\r
-            {\r
-                vals->val = $1;\r
-                vals->next = NULL;\r
-            }\r
+            vals = parser_alloc( info, sizeof *vals );\r
+            if( !vals )\r
+                YYABORT;\r
+            vals->val = $1;\r
+            vals->next = NULL;\r
             $$ = vals;\r
         }\r
   | const_val TK_COMMA constlist\r
         {\r
             value_list *vals;\r
 \r
-            vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );\r
-            if( vals )\r
-            {\r
-                vals->val = $1;\r
-                vals->next = $3;\r
-            }\r
+            vals = parser_alloc( info, sizeof *vals );\r
+            if( !vals )\r
+                YYABORT;\r
+            vals->val = $1;\r
+            vals->next = $3;\r
             $$ = vals;\r
         }\r
     ;\r
@@ -559,61 +578,79 @@ column_assignment:
 const_val:\r
     TK_INTEGER\r
         {\r
-            $$ = EXPR_ival( &$1, 1 );\r
+            $$ = EXPR_ival( info, &$1, 1 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | TK_MINUS  TK_INTEGER\r
         {\r
-            $$ = EXPR_ival( &$2, -1 );\r
+            $$ = EXPR_ival( info, &$2, -1 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | TK_STRING\r
         {\r
-            $$ = EXPR_sval( &$1 );\r
+            $$ = EXPR_sval( info, &$1 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
   | TK_WILDCARD\r
         {\r
-            $$ = EXPR_wildcard();\r
+            $$ = EXPR_wildcard( info );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
     ;\r
 \r
 column_val:\r
     column \r
         {\r
-            $$ = EXPR_column( $1 );\r
+            $$ = EXPR_column( info, $1 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
     ;\r
 \r
 column:\r
-    table TK_DOT string_or_id\r
+    table TK_DOT id\r
         {\r
             $$ = $3;  /* FIXME */\r
         }\r
-  | string_or_id\r
+  | id\r
         {\r
             $$ = $1;\r
         }\r
     ;\r
 \r
 table:\r
-    string_or_id\r
+    id\r
         {\r
             $$ = $1;\r
         }\r
     ;\r
 \r
-string_or_id:\r
+id:\r
     TK_ID\r
         {\r
-            $$ = SQL_getstring( &$1 );\r
-        }\r
-  | TK_STRING\r
-        {\r
-            $$ = SQL_getstring( &$1 );\r
+            $$ = SQL_getstring( info, &$1 );\r
+            if( !$$ )\r
+                YYABORT;\r
         }\r
     ;\r
 \r
 %%\r
 \r
-int SQL_lex( void *SQL_lval, SQL_input *sql)\r
+static void *parser_alloc( void *info, unsigned int sz )\r
+{\r
+    SQL_input* sql = (SQL_input*) info;\r
+    struct list *mem;\r
+\r
+    mem = HeapAlloc( GetProcessHeap(), 0, sizeof (struct list) + sz );\r
+    list_add_tail( sql->mem, mem );\r
+    return &mem[1];\r
+}\r
+\r
+int SQL_lex( void *SQL_lval, SQL_input *sql )\r
 {\r
     int token;\r
     struct sql_str * str = SQL_lval;\r
@@ -638,7 +675,7 @@ int SQL_lex( void *SQL_lval, SQL_input *sql)
     return token;\r
 }\r
 \r
-LPWSTR SQL_getstring( struct sql_str *strdata)\r
+LPWSTR SQL_getstring( void *info, struct sql_str *strdata )\r
 {\r
     LPCWSTR p = strdata->data;\r
     UINT len = strdata->len;\r
@@ -651,61 +688,31 @@ LPWSTR SQL_getstring( struct sql_str *strdata)
         p++;\r
         len -= 2;\r
     }\r
-    str = HeapAlloc( GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));\r
-    if(!str )\r
+    str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );\r
+    if( !str )\r
         return str;\r
-    memcpy(str, p, len*sizeof(WCHAR) );\r
+    memcpy( str, p, len*sizeof(WCHAR) );\r
     str[len]=0;\r
 \r
     return str;\r
 }\r
 \r
-INT SQL_getint( SQL_input *sql )\r
+INT SQL_getint( void *info )\r
 {\r
+    SQL_input* sql = (SQL_input*) info;\r
     LPCWSTR p = &sql->command[sql->n];\r
 \r
     return atoiW( p );\r
 }\r
 \r
-int SQL_error(const char *str)\r
+int SQL_error( const char *str )\r
 {\r
     return 0;\r
 }\r
 \r
-static MSIVIEW *do_one_select( MSIDATABASE *db, MSIVIEW *in, \r
-                               string_list *columns )\r
-{\r
-    MSIVIEW *view = NULL;\r
-\r
-    SELECT_CreateView( db, &view, in, columns );\r
-    delete_string_list( columns );\r
-    if( !view )\r
-        ERR("Error creating select query\n");\r
-    return view;\r
-}\r
-\r
-static MSIVIEW *do_order_by( MSIDATABASE *db, MSIVIEW *in, \r
-                             string_list *columns )\r
+static struct expr * EXPR_wildcard( void *info )\r
 {\r
-    MSIVIEW *view = NULL;\r
-\r
-    ORDER_CreateView( db, &view, in );\r
-    if( view )\r
-    {\r
-        string_list *x = columns;\r
-\r
-        for( x = columns; x ; x = x->next )\r
-            ORDER_AddColumn( view, x->string );\r
-    }\r
-    else\r
-        ERR("Error creating select query\n");\r
-    delete_string_list( columns );\r
-    return view;\r
-}\r
-\r
-static struct expr * EXPR_wildcard()\r
-{\r
-    struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
+    struct expr *e = parser_alloc( info, sizeof *e );\r
     if( e )\r
     {\r
         e->type = EXPR_WILDCARD;\r
@@ -713,9 +720,9 @@ static struct expr * EXPR_wildcard()
     return e;\r
 }\r
 \r
-static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r )\r
+static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )\r
 {\r
-    struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
+    struct expr *e = parser_alloc( info, sizeof *e );\r
     if( e )\r
     {\r
         e->type = EXPR_COMPLEX;\r
@@ -726,20 +733,20 @@ static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r )
     return e;\r
 }\r
 \r
-static struct expr * EXPR_column( LPWSTR str )\r
+static struct expr * EXPR_column( void *info, LPWSTR column )\r
 {\r
-    struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
+    struct expr *e = parser_alloc( info, sizeof *e );\r
     if( e )\r
     {\r
         e->type = EXPR_COLUMN;\r
-        e->u.sval = str;\r
+        e->u.sval = column;\r
     }\r
     return e;\r
 }\r
 \r
-static struct expr * EXPR_ival( struct sql_str *str , int sign)\r
+static struct expr * EXPR_ival( void *info, struct sql_str *str, int sign )\r
 {\r
-    struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
+    struct expr *e = parser_alloc( info, sizeof *e );\r
     if( e )\r
     {\r
         e->type = EXPR_IVAL;\r
@@ -748,57 +755,18 @@ static struct expr * EXPR_ival( struct sql_str *str , int sign)
     return e;\r
 }\r
 \r
-static struct expr * EXPR_sval( struct sql_str *str )\r
+static struct expr * EXPR_sval( void *info, struct sql_str *str )\r
 {\r
-    struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );\r
+    struct expr *e = parser_alloc( info, sizeof *e );\r
     if( e )\r
     {\r
         e->type = EXPR_SVAL;\r
-        e->u.sval = SQL_getstring( str );\r
+        e->u.sval = SQL_getstring( info, str );\r
     }\r
     return e;\r
 }\r
 \r
-void delete_expr( struct expr *e )\r
-{\r
-    if( !e )\r
-        return;\r
-    if( e->type == EXPR_COMPLEX )\r
-    {\r
-        delete_expr( e->u.expr.left );\r
-        delete_expr( e->u.expr.right );\r
-    }\r
-    else if( e->type == EXPR_UTF8 )\r
-        HeapFree( GetProcessHeap(), 0, e->u.utf8 );\r
-    else if( e->type == EXPR_SVAL )\r
-        HeapFree( GetProcessHeap(), 0, e->u.sval );\r
-    HeapFree( GetProcessHeap(), 0, e );\r
-}\r
-\r
-void delete_string_list( string_list *sl )\r
-{\r
-    while( sl )\r
-    {\r
-        string_list *t = sl->next;\r
-        HeapFree( GetProcessHeap(), 0, sl->string );\r
-        HeapFree( GetProcessHeap(), 0, sl );\r
-        sl = t;\r
-    }\r
-}\r
-\r
-void delete_value_list( value_list *vl )\r
-{\r
-    while( vl )\r
-    {\r
-        value_list *t = vl->next;\r
-        delete_expr( vl->val );\r
-        HeapFree( GetProcessHeap(), 0, vl );\r
-        vl = t;\r
-    }\r
-}\r
-\r
-static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,\r
-                                 string_list *keys )\r
+static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, string_list *keys)\r
 {\r
     string_list *k;\r
     BOOL found = TRUE;\r
@@ -820,7 +788,8 @@ static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
     return found;\r
 }\r
 \r
-UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview )\r
+UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,\r
+                   struct list *mem )\r
 {\r
     SQL_input sql;\r
     int r;\r
@@ -832,6 +801,7 @@ UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview )
     sql.n = 0;\r
     sql.len = 0;\r
     sql.view = phview;\r
+    sql.mem = mem;\r
 \r
     r = SQL_parse(&sql);\r
 \r