Track memory allocations in the SQL parser.
This commit is contained in:
parent
7f99aa834f
commit
0093007b32
|
@ -201,20 +201,10 @@ static UINT CREATE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
|||
static UINT CREATE_delete( struct tagMSIVIEW *view )
|
||||
{
|
||||
MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
|
||||
create_col_info *col;
|
||||
|
||||
TRACE("%p\n", cv );
|
||||
|
||||
col = cv->col_info;
|
||||
while( col )
|
||||
{
|
||||
create_col_info *t = col;
|
||||
col = col->next;
|
||||
HeapFree( GetProcessHeap(), 0, t->colname );
|
||||
HeapFree( GetProcessHeap(), 0, t );
|
||||
}
|
||||
msiobj_release( &cv->db->hdr );
|
||||
HeapFree( GetProcessHeap(), 0, cv->name );
|
||||
HeapFree( GetProcessHeap(), 0, cv );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -250,7 +240,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
|
|||
cv->view.ops = &create_ops;
|
||||
msiobj_addref( &db->hdr );
|
||||
cv->db = db;
|
||||
cv->name = table; /* FIXME: strdupW it? */
|
||||
cv->name = table;
|
||||
cv->col_info = col_info;
|
||||
cv->bIsTemp = temp;
|
||||
*view = (MSIVIEW*) cv;
|
||||
|
|
|
@ -233,7 +233,6 @@ static UINT INSERT_delete( struct tagMSIVIEW *view )
|
|||
sv = iv->sv;
|
||||
if( sv )
|
||||
sv->ops->delete( sv );
|
||||
delete_value_list( iv->vals );
|
||||
msiobj_release( &iv->db->hdr );
|
||||
HeapFree( GetProcessHeap(), 0, iv );
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "objbase.h"
|
||||
#include "objidl.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
#define MSI_DATASIZEMASK 0x00ff
|
||||
#define MSITYPE_VALID 0x0100
|
||||
|
@ -77,6 +78,7 @@ typedef struct tagMSIQUERY
|
|||
MSIVIEW *view;
|
||||
UINT row;
|
||||
MSIDATABASE *db;
|
||||
struct list mem;
|
||||
} MSIQUERY;
|
||||
|
||||
/* maybe we can use a Variant instead of doing it ourselves? */
|
||||
|
|
|
@ -41,10 +41,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
|||
void MSI_CloseView( MSIOBJECTHDR *arg )
|
||||
{
|
||||
MSIQUERY *query = (MSIQUERY*) arg;
|
||||
struct list *ptr, *t;
|
||||
|
||||
if( query->view && query->view->ops->delete )
|
||||
query->view->ops->delete( query->view );
|
||||
msiobj_release( &query->db->hdr );
|
||||
|
||||
LIST_FOR_EACH_SAFE( ptr, t, &query->mem )
|
||||
{
|
||||
HeapFree( GetProcessHeap(), 0, ptr );
|
||||
}
|
||||
}
|
||||
|
||||
UINT VIEW_find_column( MSIVIEW *table, LPCWSTR name, UINT *n )
|
||||
|
@ -120,8 +126,9 @@ UINT MSI_DatabaseOpenViewW(MSIDATABASE *db,
|
|||
query->row = 0;
|
||||
query->db = db;
|
||||
query->view = NULL;
|
||||
list_init( &query->mem );
|
||||
|
||||
r = MSI_ParseSQL( db, szQuery, &query->view );
|
||||
r = MSI_ParseSQL( db, szQuery, &query->view, &query->mem );
|
||||
if( r == ERROR_SUCCESS )
|
||||
{
|
||||
msiobj_addref( &query->hdr );
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include "msi.h"
|
||||
#include "msiquery.h"
|
||||
#include "msipriv.h"
|
||||
#include "wine/list.h"
|
||||
|
||||
|
||||
#define OP_EQ 1
|
||||
|
@ -105,7 +106,8 @@ typedef struct _column_assignment
|
|||
} column_assignment;
|
||||
|
||||
|
||||
UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phView);
|
||||
UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
|
||||
struct list *mem );
|
||||
|
||||
UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view );
|
||||
|
||||
|
@ -131,10 +133,6 @@ UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **, LPWSTR table,
|
|||
|
||||
UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table );
|
||||
|
||||
void delete_expr( struct expr *e );
|
||||
void delete_string_list( string_list *sl );
|
||||
void delete_value_list( value_list *vl );
|
||||
|
||||
int sqliteGetToken(const WCHAR *z, int *tokenType);
|
||||
|
||||
#endif /* __WINE_MSI_QUERY_H */
|
||||
|
|
175
dlls/msi/sql.y
175
dlls/msi/sql.y
|
@ -30,6 +30,7 @@
|
|||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "query.h"
|
||||
#include "wine/list.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/unicode.h"
|
||||
|
||||
|
@ -46,20 +47,22 @@ typedef struct tag_SQL_input
|
|||
LPCWSTR command;
|
||||
DWORD n, len;
|
||||
MSIVIEW **view; /* view structure for the resulting query */
|
||||
struct list *mem;
|
||||
} SQL_input;
|
||||
|
||||
static LPWSTR SQL_getstring( struct sql_str *str );
|
||||
static INT SQL_getint( SQL_input *sql );
|
||||
static int SQL_lex( void *SQL_lval, SQL_input *info);
|
||||
static LPWSTR SQL_getstring( void *info, struct sql_str *str );
|
||||
static INT SQL_getint( void *info );
|
||||
static int SQL_lex( void *SQL_lval, SQL_input *info );
|
||||
|
||||
static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
|
||||
string_list *keys);
|
||||
static void *parser_alloc( void *info, unsigned int sz );
|
||||
|
||||
static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r );
|
||||
static struct expr * EXPR_column( LPWSTR );
|
||||
static struct expr * EXPR_ival( struct sql_str *, int sign);
|
||||
static struct expr * EXPR_sval( struct sql_str *);
|
||||
static struct expr * EXPR_wildcard();
|
||||
static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, string_list *keys);
|
||||
|
||||
static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r );
|
||||
static struct expr * EXPR_column( void *info, LPWSTR column );
|
||||
static struct expr * EXPR_ival( void *info, struct sql_str *, int sign );
|
||||
static struct expr * EXPR_sval( void *info, struct sql_str * );
|
||||
static struct expr * EXPR_wildcard( void *info );
|
||||
|
||||
%}
|
||||
|
||||
|
@ -435,70 +438,72 @@ expr:
|
|||
TK_LP expr TK_RP
|
||||
{
|
||||
$$ = $2;
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_EQ column_val
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_EQ, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_EQ, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| expr TK_AND expr
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_AND, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_AND, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| expr TK_OR expr
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_OR, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_OR, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_EQ val
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_EQ, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_EQ, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_GT val
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_GT, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_GT, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_LT val
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_LT, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_LT, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_LE val
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_LE, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_LE, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_GE val
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_GE, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_GE, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_NE val
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_NE, $3 );
|
||||
$$ = EXPR_complex( info, $1, OP_NE, $3 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_IS TK_NULL
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_ISNULL, NULL );
|
||||
$$ = EXPR_complex( info, $1, OP_ISNULL, NULL );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
| column_val TK_IS TK_NOT TK_NULL
|
||||
{
|
||||
$$ = EXPR_complex( $1, OP_NOTNULL, NULL );
|
||||
$$ = EXPR_complex( info, $1, OP_NOTNULL, NULL );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
|
@ -514,24 +519,22 @@ constlist:
|
|||
{
|
||||
value_list *vals;
|
||||
|
||||
vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );
|
||||
if( vals )
|
||||
{
|
||||
vals->val = $1;
|
||||
vals->next = NULL;
|
||||
}
|
||||
vals = parser_alloc( info, sizeof *vals );
|
||||
if( !vals )
|
||||
YYABORT;
|
||||
vals->val = $1;
|
||||
vals->next = NULL;
|
||||
$$ = vals;
|
||||
}
|
||||
| const_val TK_COMMA constlist
|
||||
{
|
||||
value_list *vals;
|
||||
|
||||
vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals );
|
||||
if( vals )
|
||||
{
|
||||
vals->val = $1;
|
||||
vals->next = $3;
|
||||
}
|
||||
vals = parser_alloc( info, sizeof *vals );
|
||||
if( !vals )
|
||||
YYABORT;
|
||||
vals->val = $1;
|
||||
vals->next = $3;
|
||||
$$ = vals;
|
||||
}
|
||||
;
|
||||
|
@ -565,26 +568,26 @@ column_assignment:
|
|||
const_val:
|
||||
TK_INTEGER
|
||||
{
|
||||
$$ = EXPR_ival( &$1, 1 );
|
||||
$$ = EXPR_ival( info, &$1, 1 );
|
||||
}
|
||||
| TK_MINUS TK_INTEGER
|
||||
{
|
||||
$$ = EXPR_ival( &$2, -1 );
|
||||
$$ = EXPR_ival( info, &$2, -1 );
|
||||
}
|
||||
| TK_STRING
|
||||
{
|
||||
$$ = EXPR_sval( &$1 );
|
||||
$$ = EXPR_sval( info, &$1 );
|
||||
}
|
||||
| TK_WILDCARD
|
||||
{
|
||||
$$ = EXPR_wildcard();
|
||||
$$ = EXPR_wildcard( info );
|
||||
}
|
||||
;
|
||||
|
||||
column_val:
|
||||
column
|
||||
{
|
||||
$$ = EXPR_column( $1 );
|
||||
$$ = EXPR_column( info, $1 );
|
||||
}
|
||||
;
|
||||
|
||||
|
@ -609,13 +612,25 @@ table:
|
|||
id:
|
||||
TK_ID
|
||||
{
|
||||
$$ = SQL_getstring( &$1 );
|
||||
$$ = SQL_getstring( info, &$1 );
|
||||
if( !$$ )
|
||||
YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
int SQL_lex( void *SQL_lval, SQL_input *sql)
|
||||
static void *parser_alloc( void *info, unsigned int sz )
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
struct list *mem;
|
||||
|
||||
mem = HeapAlloc( GetProcessHeap(), 0, sizeof (struct list) + sz );
|
||||
list_add_tail( sql->mem, mem );
|
||||
return &mem[1];
|
||||
}
|
||||
|
||||
int SQL_lex( void *SQL_lval, SQL_input *sql )
|
||||
{
|
||||
int token;
|
||||
struct sql_str * str = SQL_lval;
|
||||
|
@ -640,7 +655,7 @@ int SQL_lex( void *SQL_lval, SQL_input *sql)
|
|||
return token;
|
||||
}
|
||||
|
||||
LPWSTR SQL_getstring( struct sql_str *strdata)
|
||||
LPWSTR SQL_getstring( void *info, struct sql_str *strdata )
|
||||
{
|
||||
LPCWSTR p = strdata->data;
|
||||
UINT len = strdata->len;
|
||||
|
@ -653,30 +668,31 @@ LPWSTR SQL_getstring( struct sql_str *strdata)
|
|||
p++;
|
||||
len -= 2;
|
||||
}
|
||||
str = HeapAlloc( GetProcessHeap(), 0, (len + 1)*sizeof(WCHAR));
|
||||
if(!str )
|
||||
str = parser_alloc( info, (len + 1)*sizeof(WCHAR) );
|
||||
if( !str )
|
||||
return str;
|
||||
memcpy(str, p, len*sizeof(WCHAR) );
|
||||
memcpy( str, p, len*sizeof(WCHAR) );
|
||||
str[len]=0;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
INT SQL_getint( SQL_input *sql )
|
||||
INT SQL_getint( void *info )
|
||||
{
|
||||
SQL_input* sql = (SQL_input*) info;
|
||||
LPCWSTR p = &sql->command[sql->n];
|
||||
|
||||
return atoiW( p );
|
||||
}
|
||||
|
||||
int SQL_error(const char *str)
|
||||
int SQL_error( const char *str )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct expr * EXPR_wildcard()
|
||||
static struct expr * EXPR_wildcard( void *info )
|
||||
{
|
||||
struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
|
||||
struct expr *e = parser_alloc( info, sizeof *e );
|
||||
if( e )
|
||||
{
|
||||
e->type = EXPR_WILDCARD;
|
||||
|
@ -684,9 +700,9 @@ static struct expr * EXPR_wildcard()
|
|||
return e;
|
||||
}
|
||||
|
||||
static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r )
|
||||
static struct expr * EXPR_complex( void *info, struct expr *l, UINT op, struct expr *r )
|
||||
{
|
||||
struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
|
||||
struct expr *e = parser_alloc( info, sizeof *e );
|
||||
if( e )
|
||||
{
|
||||
e->type = EXPR_COMPLEX;
|
||||
|
@ -697,20 +713,20 @@ static struct expr * EXPR_complex( struct expr *l, UINT op, struct expr *r )
|
|||
return e;
|
||||
}
|
||||
|
||||
static struct expr * EXPR_column( LPWSTR str )
|
||||
static struct expr * EXPR_column( void *info, LPWSTR column )
|
||||
{
|
||||
struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
|
||||
struct expr *e = parser_alloc( info, sizeof *e );
|
||||
if( e )
|
||||
{
|
||||
e->type = EXPR_COLUMN;
|
||||
e->u.sval = str;
|
||||
e->u.sval = column;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
static struct expr * EXPR_ival( struct sql_str *str , int sign)
|
||||
static struct expr * EXPR_ival( void *info, struct sql_str *str, int sign )
|
||||
{
|
||||
struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
|
||||
struct expr *e = parser_alloc( info, sizeof *e );
|
||||
if( e )
|
||||
{
|
||||
e->type = EXPR_IVAL;
|
||||
|
@ -719,55 +735,18 @@ static struct expr * EXPR_ival( struct sql_str *str , int sign)
|
|||
return e;
|
||||
}
|
||||
|
||||
static struct expr * EXPR_sval( struct sql_str *str )
|
||||
static struct expr * EXPR_sval( void *info, struct sql_str *str )
|
||||
{
|
||||
struct expr *e = HeapAlloc( GetProcessHeap(), 0, sizeof *e );
|
||||
struct expr *e = parser_alloc( info, sizeof *e );
|
||||
if( e )
|
||||
{
|
||||
e->type = EXPR_SVAL;
|
||||
e->u.sval = SQL_getstring( str );
|
||||
e->u.sval = SQL_getstring( info, str );
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
void delete_expr( struct expr *e )
|
||||
{
|
||||
if( !e )
|
||||
return;
|
||||
if( e->type == EXPR_COMPLEX )
|
||||
{
|
||||
delete_expr( e->u.expr.left );
|
||||
delete_expr( e->u.expr.right );
|
||||
}
|
||||
else if( e->type == EXPR_SVAL )
|
||||
HeapFree( GetProcessHeap(), 0, e->u.sval );
|
||||
HeapFree( GetProcessHeap(), 0, e );
|
||||
}
|
||||
|
||||
void delete_string_list( string_list *sl )
|
||||
{
|
||||
while( sl )
|
||||
{
|
||||
string_list *t = sl->next;
|
||||
HeapFree( GetProcessHeap(), 0, sl->string );
|
||||
HeapFree( GetProcessHeap(), 0, sl );
|
||||
sl = t;
|
||||
}
|
||||
}
|
||||
|
||||
void delete_value_list( value_list *vl )
|
||||
{
|
||||
while( vl )
|
||||
{
|
||||
value_list *t = vl->next;
|
||||
delete_expr( vl->val );
|
||||
HeapFree( GetProcessHeap(), 0, vl );
|
||||
vl = t;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
|
||||
string_list *keys )
|
||||
static BOOL SQL_MarkPrimaryKeys( create_col_info *cols, string_list *keys)
|
||||
{
|
||||
string_list *k;
|
||||
BOOL found = TRUE;
|
||||
|
@ -789,7 +768,8 @@ static BOOL SQL_MarkPrimaryKeys( create_col_info *cols,
|
|||
return found;
|
||||
}
|
||||
|
||||
UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview )
|
||||
UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview,
|
||||
struct list *mem )
|
||||
{
|
||||
SQL_input sql;
|
||||
int r;
|
||||
|
@ -801,6 +781,7 @@ UINT MSI_ParseSQL( MSIDATABASE *db, LPCWSTR command, MSIVIEW **phview )
|
|||
sql.n = 0;
|
||||
sql.len = 0;
|
||||
sql.view = phview;
|
||||
sql.mem = mem;
|
||||
|
||||
r = SQL_parse(&sql);
|
||||
|
||||
|
|
|
@ -171,7 +171,6 @@ static UINT UPDATE_delete( struct tagMSIVIEW *view )
|
|||
wv = uv->wv;
|
||||
if( wv )
|
||||
wv->ops->delete( wv );
|
||||
delete_value_list( uv->vals );
|
||||
msiobj_release( &uv->db->hdr );
|
||||
HeapFree( GetProcessHeap(), 0, uv );
|
||||
|
||||
|
|
|
@ -334,9 +334,6 @@ static UINT WHERE_delete( struct tagMSIVIEW *view )
|
|||
wv->reorder = NULL;
|
||||
wv->row_count = 0;
|
||||
|
||||
if( wv->cond )
|
||||
delete_expr( wv->cond );
|
||||
|
||||
msiobj_release( &wv->db->hdr );
|
||||
HeapFree( GetProcessHeap(), 0, wv );
|
||||
|
||||
|
|
Loading…
Reference in New Issue