From 19ed3d64b942176912e27b29a91838f2ba99b5aa Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Thu, 2 Oct 2008 14:22:54 -0500 Subject: [PATCH] msi: Implement the DROP TABLE sql command. To: wine-patches --- dlls/msi/Makefile.in | 1 + dlls/msi/alter.c | 1 + dlls/msi/create.c | 8 +++- dlls/msi/delete.c | 3 +- dlls/msi/distinct.c | 1 + dlls/msi/drop.c | 125 ++++++++++++++++++++++++++++++++++++++++++++++++++ dlls/msi/insert.c | 1 + dlls/msi/join.c | 1 + dlls/msi/msipriv.h | 5 ++ dlls/msi/query.h | 2 + dlls/msi/select.c | 1 + dlls/msi/sql.y | 18 ++++++- dlls/msi/storages.c | 1 + dlls/msi/streams.c | 1 + dlls/msi/table.c | 77 ++++++++++++++++++++++++++---- dlls/msi/tests/db.c | 89 +++++++++++++++++++++++++++++++++++ dlls/msi/tokenize.c | 2 + dlls/msi/update.c | 1 + dlls/msi/where.c | 1 + 19 files changed, 324 insertions(+), 15 deletions(-) create mode 100644 dlls/msi/drop.c diff --git a/dlls/msi/Makefile.in b/dlls/msi/Makefile.in index 8cbd8a4..a3ae579 100644 --- a/dlls/msi/Makefile.in +++ b/dlls/msi/Makefile.in @@ -19,6 +19,7 @@ C_SRCS = \ delete.c \ dialog.c \ distinct.c \ + drop.c \ events.c \ files.c \ font.c \ diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c index 892ad35..3252f6a 100644 --- a/dlls/msi/alter.c +++ b/dlls/msi/alter.c @@ -242,6 +242,7 @@ static const MSIVIEWOPS alter_ops = NULL, NULL, NULL, + NULL, }; UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, column_info *colinfo, int hold ) diff --git a/dlls/msi/create.c b/dlls/msi/create.c index ed8713c..9a5c97b 100644 --- a/dlls/msi/create.c +++ b/dlls/msi/create.c @@ -137,6 +137,7 @@ static const MSIVIEWOPS create_ops = NULL, NULL, NULL, + NULL, }; static UINT check_columns( column_info *col_info ) @@ -157,7 +158,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table, { MSICREATEVIEW *cv = NULL; UINT r; - const column_info *col; + column_info *col; BOOL temp = TRUE; TRACE("%p\n", cv ); @@ -171,11 +172,16 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table, return ERROR_FUNCTION_FAILED; for( col = col_info; col; col = col->next ) + { + if (!col->table) + col->table = strdupW(table); + if( !col->temporary ) { temp = FALSE; break; } + } /* fill the structure */ cv->view.ops = &create_ops; diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c index 8d37324..3db2783 100644 --- a/dlls/msi/delete.c +++ b/dlls/msi/delete.c @@ -191,7 +191,8 @@ static const MSIVIEWOPS delete_ops = NULL, NULL, NULL, - NULL + NULL, + NULL, }; UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c index 6a29c5a..6c21b88 100644 --- a/dlls/msi/distinct.c +++ b/dlls/msi/distinct.c @@ -296,6 +296,7 @@ static const MSIVIEWOPS distinct_ops = NULL, NULL, DISTINCT_sort, + NULL, }; UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) diff --git a/dlls/msi/drop.c b/dlls/msi/drop.c new file mode 100644 index 0000000..e810d0a --- /dev/null +++ b/dlls/msi/drop.c @@ -0,0 +1,125 @@ +/* + * Implementation of the Microsoft Installer (msi.dll) + * + * Copyright 2008 James Hawkins + * + * 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 hdve received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "wine/debug.h" +#include "msi.h" +#include "msiquery.h" +#include "objbase.h" +#include "objidl.h" +#include "msipriv.h" + +#include "query.h" + +WINE_DEFAULT_DEBUG_CHANNEL(msidb); + +typedef struct tagMSIDROPVIEW +{ + MSIVIEW view; + MSIDATABASE *db; + MSIVIEW *table; + column_info *colinfo; + INT hold; +} MSIDROPVIEW; + +static UINT DROP_execute(struct tagMSIVIEW *view, MSIRECORD *record) +{ + MSIDROPVIEW *dv = (MSIDROPVIEW*)view; + UINT r; + + TRACE("%p %p\n", dv, record); + + if( !dv->table ) + return ERROR_FUNCTION_FAILED; + + r = dv->table->ops->execute(dv->table, record); + if (r != ERROR_SUCCESS) + return r; + + return dv->table->ops->drop(dv->table); +} + +static UINT DROP_close(struct tagMSIVIEW *view) +{ + MSIDROPVIEW *dv = (MSIDROPVIEW*)view; + + TRACE("%p\n", dv); + + return ERROR_SUCCESS; +} + +static UINT DROP_get_dimensions(struct tagMSIVIEW *view, UINT *rows, UINT *cols) +{ + MSIDROPVIEW *dv = (MSIDROPVIEW*)view; + + TRACE("%p %p %p\n", dv, rows, cols); + + return ERROR_FUNCTION_FAILED; +} + +static const MSIVIEWOPS drop_ops = +{ + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + DROP_execute, + DROP_close, + DROP_get_dimensions, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, +}; + +UINT DROP_CreateView(MSIDATABASE *db, MSIVIEW **view, LPCWSTR name) +{ + MSIDROPVIEW *dv; + UINT r; + + TRACE("%p %s\n", view, debugstr_w(name)); + + dv = msi_alloc_zero(sizeof *dv); + if(!dv) + return ERROR_FUNCTION_FAILED; + + r = TABLE_CreateView(db, name, &dv->table); + if (r != ERROR_SUCCESS || !dv->table) + return r; + + dv->view.ops = &drop_ops; + dv->db = db; + + *view = (MSIVIEW *)dv; + + return ERROR_SUCCESS; +} diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c index 55ac234..0907126 100644 --- a/dlls/msi/insert.c +++ b/dlls/msi/insert.c @@ -239,6 +239,7 @@ static const MSIVIEWOPS insert_ops = NULL, NULL, NULL, + NULL, }; static UINT count_column_info( const column_info *ci ) diff --git a/dlls/msi/join.c b/dlls/msi/join.c index 756db6f..34de3b1 100644 --- a/dlls/msi/join.c +++ b/dlls/msi/join.c @@ -306,6 +306,7 @@ static const MSIVIEWOPS join_ops = NULL, NULL, JOIN_sort, + NULL, }; UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables ) diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index 96656c6..2991e7d 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -274,6 +274,11 @@ typedef struct tagMSIVIEWOPS * sort - orders the table by columns */ UINT (*sort)( struct tagMSIVIEW *view, column_info *columns ); + + /* + * drop - drops the table from the database + */ + UINT (*drop)( struct tagMSIVIEW *view ); } MSIVIEWOPS; struct tagMSIVIEW diff --git a/dlls/msi/query.h b/dlls/msi/query.h index 53dcf63..25bb500 100644 --- a/dlls/msi/query.h +++ b/dlls/msi/query.h @@ -117,6 +117,8 @@ UINT STREAMS_CreateView( MSIDATABASE *db, MSIVIEW **view ); UINT STORAGES_CreateView( MSIDATABASE *db, MSIVIEW **view ); +UINT DROP_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name ); + int sqliteGetToken(const WCHAR *z, int *tokenType); MSIRECORD *msi_query_merge_record( UINT fields, const column_info *vl, MSIRECORD *rec ); diff --git a/dlls/msi/select.c b/dlls/msi/select.c index 070bbfa..30fabce 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -363,6 +363,7 @@ static const MSIVIEWOPS select_ops = NULL, NULL, SELECT_sort, + NULL, }; static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name ) diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y index e610383..7deae21 100644 --- a/dlls/msi/sql.y +++ b/dlls/msi/sql.y @@ -81,7 +81,7 @@ static struct expr * EXPR_wildcard( void *info ); int integer; } -%token TK_ALTER TK_AND TK_BY TK_CHAR TK_COMMA TK_CREATE TK_DELETE +%token TK_ALTER TK_AND TK_BY TK_CHAR TK_COMMA TK_CREATE TK_DELETE TK_DROP %token TK_DISTINCT TK_DOT TK_EQ TK_FREE TK_FROM TK_GE TK_GT TK_HOLD TK_ADD %token TK_ID %token TK_ILLEGAL TK_INSERT TK_INT @@ -106,7 +106,7 @@ static struct expr * EXPR_wildcard( void *info ); %type selcollist column column_and_type column_def table_def %type column_assignment update_assign_list constlist %type query from fromtable selectfrom unorderedsel -%type oneupdate onedelete oneselect onequery onecreate oneinsert onealter +%type oneupdate onedelete oneselect onequery onecreate oneinsert onealter onedrop %type expr val column_val const_val %type column_type data_type data_type_l data_count %type number alterop @@ -135,6 +135,7 @@ onequery: | oneupdate | onedelete | onealter + | onedrop ; oneinsert: @@ -267,6 +268,19 @@ alterop: } ; +onedrop: + TK_DROP TK_TABLE table + { + SQL_input* sql = (SQL_input*) info; + UINT r; + + $$ = NULL; + r = DROP_CreateView( sql->db, &$$, $3 ); + if( r != ERROR_SUCCESS || !$$ ) + YYABORT; + } + ; + table_def: column_def TK_PRIMARY TK_KEY selcollist { diff --git a/dlls/msi/storages.c b/dlls/msi/storages.c index 4fb3ba0..2e21cb8 100644 --- a/dlls/msi/storages.c +++ b/dlls/msi/storages.c @@ -474,6 +474,7 @@ static const MSIVIEWOPS storages_ops = NULL, NULL, NULL, + NULL, }; static INT add_storages_to_table(MSISTORAGESVIEW *sv) diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index e3846ad..e263105 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -438,6 +438,7 @@ static const MSIVIEWOPS streams_ops = NULL, NULL, NULL, + NULL, }; static INT add_streams_to_table(MSISTREAMSVIEW *sv) diff --git a/dlls/msi/table.c b/dlls/msi/table.c index 49b5cb6..e435e51 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -109,7 +109,7 @@ static const MSICOLUMNINFO _Columns_cols[4] = { }; static const MSICOLUMNINFO _Tables_cols[1] = { - { szTables, 1, szName, MSITYPE_VALID | MSITYPE_STRING | 64, 0, 0, NULL }, + { szTables, 1, szName, MSITYPE_VALID | MSITYPE_STRING | MSITYPE_KEY | 64, 0, 0, NULL }, }; #define MAX_STREAM_NAME 0x1f @@ -567,9 +567,14 @@ static MSITABLE *find_cached_table( MSIDATABASE *db, LPCWSTR name ) { MSITABLE *t; + ERR("find_cached_table: %s\n", debugstr_w(name)); + LIST_FOR_EACH_ENTRY( t, &db->tables, MSITABLE, entry ) + { + ERR("%p %s\n", t, debugstr_w(t->name)); if( !lstrcmpW( name, t->name ) ) return t; + } return NULL; } @@ -1073,20 +1078,12 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name ) count = table->row_count; for( i=0; idata[ i ][ 0 ] == table_id ) - break; - - if (i!=count) - return TRUE; + return TRUE; count = table->nonpersistent_row_count; for( i=0; inonpersistent_data[ i ][ 0 ] == table_id ) - break; - - if (i!=count) - return TRUE; - - TRACE("Searched %d tables, but %d was not found\n", count, table_id ); + return TRUE; return FALSE; } @@ -2058,6 +2055,63 @@ static UINT TABLE_sort(struct tagMSIVIEW *view, column_info *columns) return ERROR_SUCCESS; } +static UINT TABLE_drop(struct tagMSIVIEW *view) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW*)view; + MSIVIEW *tables = NULL; + MSIRECORD *rec = NULL; + UINT i, r, row; + MSITABLE *table; + + TRACE("dropping table %s\n", debugstr_w(tv->name)); + + for (i = 0; i < tv->table->col_count; i++) + { + r = TABLE_remove_column(view, tv->table->colinfo[i].tablename, + tv->table->colinfo[i].number); + if (r != ERROR_SUCCESS) + return r; + } + + rec = MSI_CreateRecord(1); + if (!rec) + return ERROR_OUTOFMEMORY; + + MSI_RecordSetStringW(rec, 1, tv->name); + + r = TABLE_CreateView(tv->db, szTables, &tables); + if (r != ERROR_SUCCESS) + return r; + + r = msi_table_find_row((MSITABLEVIEW *)tables, rec, &row); + if (r != ERROR_SUCCESS) + goto done; + + r = TABLE_delete_row(tables, row); + if (r != ERROR_SUCCESS) + goto done; + + ERR("TABLES BEFORE\n"); + + LIST_FOR_EACH_ENTRY(table, &tv->db->tables, MSITABLE, entry) + ERR("%p %s\n", table, debugstr_w(table->name)); + + list_remove(&tv->table->entry); + free_table(tv->table); + TABLE_delete(view); + + ERR("TABLES AFTER\n"); + + LIST_FOR_EACH_ENTRY(table, &tv->db->tables, MSITABLE, entry) + ERR("%p %s\n", table, debugstr_w(table->name)); + +done: + msiobj_release(&rec->hdr); + tables->ops->delete(tables); + + return r; +} + static const MSIVIEWOPS table_ops = { TABLE_fetch_int, @@ -2078,6 +2132,7 @@ static const MSIVIEWOPS table_ops = TABLE_add_column, TABLE_remove_column, TABLE_sort, + TABLE_drop, }; UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view ) diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 78a6ca2..c0a821a 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -6313,6 +6313,94 @@ static void test_dbtopackage(void) DeleteFileA(msifile); } +static void test_droptable(void) +{ + MSIHANDLE hdb, hview, hrec; + LPCSTR query; + UINT r; + + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "SELECT * FROM `One`"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + + query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + MsiCloseHandle(hrec); + + query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + MsiCloseHandle(hrec); + + query = "DROP `One`"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "DROP TABLE"; + r = run_query(hdb, 0, query); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "DROP TABLE `One`"; + hview = 0; + r = MsiDatabaseOpenViewA(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_FUNCTION_FAILED, + "Expected ERROR_FUNCTION_FAILED, got %d\n", r); + + MsiViewClose(hview); + MsiCloseHandle(hview); + + query = "SELECT * FROM `IDontExist`"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "SELECT * FROM `One`"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "DROP TABLE One"; + r = run_query(hdb, 0, query); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r); + + query = "SELECT * FROM `One`"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_BAD_QUERY_SYNTAX, + "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r); + + query = "SELECT * FROM `_Tables` WHERE `Name` = 'One'"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + + query = "SELECT * FROM `_Columns` WHERE `Table` = 'One'"; + r = do_query(hdb, query, &hrec); + ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r); + + MsiCloseHandle(hdb); + DeleteFileA(msifile); +} + START_TEST(db) { test_msidatabase(); @@ -6352,4 +6440,5 @@ START_TEST(db) test_where_viewmodify(); test_storages_table(); test_dbtopackage(); + test_droptable(); } diff --git a/dlls/msi/tokenize.c b/dlls/msi/tokenize.c index 92a1067..aec6f27 100644 --- a/dlls/msi/tokenize.c +++ b/dlls/msi/tokenize.c @@ -47,6 +47,7 @@ static const WCHAR CHARACTER_W[] = { 'C','H','A','R','A','C','T','E','R',0 }; static const WCHAR CREATE_W[] = { 'C','R','E','A','T','E',0 }; static const WCHAR DELETE_W[] = { 'D','E','L','E','T','E',0 }; static const WCHAR DISTINCT_W[] = { 'D','I','S','T','I','N','C','T',0 }; +static const WCHAR DROP_W[] = { 'D','R','O','P',0 }; static const WCHAR FREE_W[] = { 'F','R','E','E',0 }; static const WCHAR FROM_W[] = { 'F','R','O','M',0 }; static const WCHAR HOLD_W[] = { 'H','O','L','D',0 }; @@ -89,6 +90,7 @@ static const Keyword aKeywordTable[] = { { CREATE_W, TK_CREATE }, { DELETE_W, TK_DELETE }, { DISTINCT_W, TK_DISTINCT }, + { DROP_W, TK_DROP }, { FREE_W, TK_FREE }, { FROM_W, TK_FROM }, { HOLD_W, TK_HOLD }, diff --git a/dlls/msi/update.c b/dlls/msi/update.c index 44d30c6..d0c466b 100644 --- a/dlls/msi/update.c +++ b/dlls/msi/update.c @@ -222,6 +222,7 @@ static const MSIVIEWOPS update_ops = NULL, NULL, NULL, + NULL, }; UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table, diff --git a/dlls/msi/where.c b/dlls/msi/where.c index 8883496..28f115e 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -585,6 +585,7 @@ static const MSIVIEWOPS where_ops = NULL, NULL, WHERE_sort, + NULL, }; static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond, -- 1.5.4.3