diff --git a/dlls/msi/query.h b/dlls/msi/query.h index 8f8a2441f5e..ca34b4c5d38 100644 --- a/dlls/msi/query.h +++ b/dlls/msi/query.h @@ -131,7 +131,7 @@ UINT STORAGES_CreateView( MSIDATABASE *db, MSIVIEW **view ) DECLSPEC_HIDDEN; UINT DROP_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name ) DECLSPEC_HIDDEN; -int sqliteGetToken(const WCHAR *z, int *tokenType) DECLSPEC_HIDDEN; +int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip) DECLSPEC_HIDDEN; MSIRECORD *msi_query_merge_record( UINT fields, const column_info *vl, MSIRECORD *rec ) DECLSPEC_HIDDEN; diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y index 548e14290ce..ead7743171d 100644 --- a/dlls/msi/sql.y +++ b/dlls/msi/sql.y @@ -797,7 +797,7 @@ static column_info *parser_alloc_column( void *info, LPCWSTR table, LPCWSTR colu static int sql_lex( void *SQL_lval, SQL_input *sql ) { - int token; + int token, skip; struct sql_str * str = SQL_lval; do @@ -807,11 +807,12 @@ static int sql_lex( void *SQL_lval, SQL_input *sql ) return 0; /* end of input */ /* TRACE("string : %s\n", debugstr_w(&sql->command[sql->n])); */ - sql->len = sqliteGetToken( &sql->command[sql->n], &token ); + sql->len = sqliteGetToken( &sql->command[sql->n], &token, &skip ); if( sql->len==0 ) break; str->data = &sql->command[sql->n]; str->len = sql->len; + sql->n += skip; } while( token == TK_SPACE ); diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 6ecd642a7fa..d33eb0c857e 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -727,6 +727,36 @@ static void test_msibadqueries(void) r = try_query( hdb, "select * from 'c'"); ok(r == ERROR_BAD_QUERY_SYNTAX, "query failed\n"); + r = try_query( hdb, "select `c`.`b` from `c` order by `c`.`order`"); + ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); + + r = try_query( hdb, "select `c`.b` from `c`"); + ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); + + r = try_query( hdb, "select `c`.`b from `c`"); + ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); + + r = try_query( hdb, "select `c`.b from `c`"); + ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); + + r = try_query( hdb, "select `c.`b` from `c`"); + ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); + + r = try_query( hdb, "select c`.`b` from `c`"); + ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); + + r = try_query( hdb, "select c.`b` from `c`"); + ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); + + r = try_query( hdb, "select `c`.`b` from c`"); + ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); + + r = try_query( hdb, "select `c`.`b` from `c"); + ok( r == ERROR_BAD_QUERY_SYNTAX, "query failed: %u\n", r ); + + r = try_query( hdb, "select `c`.`b` from c"); + ok( r == ERROR_SUCCESS, "query failed: %u\n", r ); + r = try_query( hdb, "CREATE TABLE `\5a` (`b` CHAR NOT NULL PRIMARY KEY `b`)" ); ok( r == ERROR_SUCCESS , "query failed: %u\n", r ); diff --git a/dlls/msi/tokenize.c b/dlls/msi/tokenize.c index 64e14b87aee..c43288848ac 100644 --- a/dlls/msi/tokenize.c +++ b/dlls/msi/tokenize.c @@ -190,8 +190,10 @@ static const char isIdChar[] = { ** -1 if the token is (or might be) incomplete. Store the token ** type in *tokenType before returning. */ -int sqliteGetToken(const WCHAR *z, int *tokenType){ +int sqliteGetToken(const WCHAR *z, int *tokenType, int *skip){ int i; + + *skip = 0; switch( *z ){ case ' ': case '\t': case '\n': case '\f': for(i=1; isspace(z[i]) && z[i] != '\r'; i++){} @@ -280,6 +282,7 @@ int sqliteGetToken(const WCHAR *z, int *tokenType){ } for(i=1; isIdChar[z[i]]; i++){} *tokenType = sqliteKeywordCode(z, i); + if( *tokenType == TK_ID && z[i] == '`' ) *skip = 1; return i; } *tokenType = TK_ILLEGAL;