Commit 62c544cf authored by James Hawkins's avatar James Hawkins Committed by Alexandre Julliard

msi: Implement the DROP TABLE sql command.

parent 68525652
......@@ -19,6 +19,7 @@ C_SRCS = \
delete.c \
dialog.c \
distinct.c \
drop.c \
events.c \
files.c \
font.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 )
......
......@@ -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;
......
......@@ -191,7 +191,8 @@ static const MSIVIEWOPS delete_ops =
NULL,
NULL,
NULL,
NULL
NULL,
NULL,
};
UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
......
......@@ -296,6 +296,7 @@ static const MSIVIEWOPS distinct_ops =
NULL,
NULL,
DISTINCT_sort,
NULL,
};
UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
......
/*
* 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 have 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 <stdarg.h>
#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;
}
......@@ -239,6 +239,7 @@ static const MSIVIEWOPS insert_ops =
NULL,
NULL,
NULL,
NULL,
};
static UINT count_column_info( const column_info *ci )
......
......@@ -306,6 +306,7 @@ static const MSIVIEWOPS join_ops =
NULL,
NULL,
JOIN_sort,
NULL,
};
UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR tables )
......
......@@ -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
......
......@@ -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 );
......
......@@ -363,6 +363,7 @@ static const MSIVIEWOPS select_ops =
NULL,
NULL,
SELECT_sort,
NULL,
};
static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name )
......
......@@ -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 <str> TK_ID
%token TK_ILLEGAL TK_INSERT TK_INT
......@@ -106,7 +106,7 @@ static struct expr * EXPR_wildcard( void *info );
%type <column_list> selcollist column column_and_type column_def table_def
%type <column_list> column_assignment update_assign_list constlist
%type <query> query from fromtable selectfrom unorderedsel
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter onedrop
%type <expr> expr val column_val const_val
%type <column_type> column_type data_type data_type_l data_count
%type <integer> 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
{
......
......@@ -474,6 +474,7 @@ static const MSIVIEWOPS storages_ops =
NULL,
NULL,
NULL,
NULL,
};
static INT add_storages_to_table(MSISTORAGESVIEW *sv)
......
......@@ -438,6 +438,7 @@ static const MSIVIEWOPS streams_ops =
NULL,
NULL,
NULL,
NULL,
};
static INT add_streams_to_table(MSISTREAMSVIEW *sv)
......
......@@ -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
......@@ -1073,21 +1073,13 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
count = table->row_count;
for( i=0; i<count; i++ )
if( table->data[ i ][ 0 ] == table_id )
break;
if (i!=count)
return TRUE;
count = table->nonpersistent_row_count;
for( i=0; i<count; i++ )
if( table->nonpersistent_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 FALSE;
}
......@@ -2058,6 +2050,52 @@ 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;
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;
list_remove(&tv->table->entry);
free_table(tv->table);
TABLE_delete(view);
done:
msiobj_release(&rec->hdr);
tables->ops->delete(tables);
return r;
}
static const MSIVIEWOPS table_ops =
{
TABLE_fetch_int,
......@@ -2078,6 +2116,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 )
......
......@@ -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();
}
......@@ -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 },
......
......@@ -222,6 +222,7 @@ static const MSIVIEWOPS update_ops =
NULL,
NULL,
NULL,
NULL,
};
UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment