From 5007de8b051c2421953af0f4500db285461679ed Mon Sep 17 00:00:00 2001 From: Mike McCormack Date: Thu, 20 Jan 2005 20:39:15 +0000 Subject: [PATCH] Fix and test inserting records. --- dlls/msi/insert.c | 71 +++++++++++++++++++++++++++++++++++++++----- dlls/msi/sql.y | 9 +++--- dlls/msi/tests/db.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 151 insertions(+), 14 deletions(-) diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c index d00a4d7b886..df5c1d88d3f 100644 --- a/dlls/msi/insert.c +++ b/dlls/msi/insert.c @@ -44,7 +44,7 @@ typedef struct tagMSIINSERTVIEW MSIDATABASE *db; BOOL bIsTemp; MSIVIEW *sv; - value_list *vals; /* looks like these may be ignored... */ + value_list *vals; } MSIINSERTVIEW; static UINT INSERT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) @@ -56,11 +56,62 @@ static UINT INSERT_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT return ERROR_FUNCTION_FAILED; } +/* + * INSERT_merge_record + * + * Merge a value_list and a record to create a second record. + * Replace wildcard entries in the valuelist with values from the record + */ +static MSIRECORD *INSERT_merge_record( UINT fields, value_list *vl, MSIRECORD *rec ) +{ + MSIRECORD *merged; + DWORD wildcard_count = 1, i; + const WCHAR *str; + + merged = MSI_CreateRecord( fields ); + for( i=1; i <= fields; i++ ) + { + if( !vl ) + { + TRACE("Not enough elements in the list to insert\n"); + goto err; + } + switch( vl->val->type ) + { + case EXPR_SVAL: + TRACE("field %ld -> %s\n", i, debugstr_w(vl->val->u.sval)); + MSI_RecordSetStringW( merged, i, vl->val->u.sval ); + break; + case EXPR_IVAL: + MSI_RecordSetInteger( merged, i, vl->val->u.ival ); + break; + case EXPR_WILDCARD: + if( !rec ) + goto err; + if( MSI_RecordIsNull( rec, wildcard_count ) ) + goto err; + str = MSI_RecordGetString( rec, wildcard_count ); + MSI_RecordSetStringW( merged, i, str ); + wildcard_count++; + break; + default: + ERR("Unknown expression type %d\n", vl->val->type); + } + vl = vl->next; + } + + return merged; +err: + msiobj_release( &merged->hdr ); + return NULL; +} + static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view; UINT n, type, val, r, row, col_count = 0; MSIVIEW *sv; + MSIRECORD *values = NULL; TRACE("%p %p\n", iv, record ); @@ -77,12 +128,13 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record ) if( r ) goto err; - n = MSI_RecordGetFieldCount( record ); - if( n != col_count ) - { - ERR("Number of fields do not match\n"); + /* + * Merge the wildcard values into the list of values provided + * in the query, and create a record containing both. + */ + values = INSERT_merge_record( col_count, iv->vals, record ); + if( !values ) goto err; - } row = -1; r = sv->ops->insert_row( sv, &row ); @@ -98,12 +150,12 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record ) if( type & MSITYPE_STRING ) { - const WCHAR *str = MSI_RecordGetString( record, n ); + const WCHAR *str = MSI_RecordGetString( values, n ); val = msi_addstringW( iv->db->strings, 0, str, -1, 1 ); } else { - val = MSI_RecordGetInteger( record, n ); + val = MSI_RecordGetInteger( values, n ); val |= 0x8000; } r = sv->ops->set_int( sv, row, n, val ); @@ -112,6 +164,9 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record ) } err: + if( values ) + msiobj_release( &values->hdr ); + return ERROR_SUCCESS; } diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y index 592e6bc2d61..f8bcfb719d3 100644 --- a/dlls/msi/sql.y +++ b/dlls/msi/sql.y @@ -499,18 +499,17 @@ constlist: } $$ = vals; } - | constlist TK_COMMA const_val + | const_val TK_COMMA constlist { value_list *vals; vals = HeapAlloc( GetProcessHeap(), 0, sizeof *vals ); if( vals ) { - vals->val = $3; - vals->next = NULL; + vals->val = $1; + vals->next = $3; } - $1->next = vals; - $$ = $1; + $$ = vals; } ; diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 09f553e3490..83b58ef149c 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -24,7 +24,7 @@ #include "wine/test.h" -START_TEST(db) +static void test_msidatabase(void) { MSIHANDLE hdb = 0; CHAR szName[] = "C:\\mytest.msi"; @@ -42,3 +42,86 @@ START_TEST(db) res = MsiCloseHandle( hdb ); ok( res == ERROR_SUCCESS , "Failed to close database" ); } + +void test_msiinsert(void) +{ + const char *msifile = "winetest.msi"; + MSIHANDLE hdb = 0, hview = 0, hrec = 0; + UINT r; + char *query, buf[80]; + DWORD sz; + + DeleteFile(msifile); + + /* just MsiOpenDatabase should not create a file */ + r = MsiOpenDatabase(msifile, MSIDBOPEN_CREATE, &hdb); + ok(r == ERROR_SUCCESS, "MsiOpenDatabase failed\n"); + + /* create a table */ + query = "CREATE TABLE `phone` ( " + "`id` INT, `name` CHAR(32), `number` CHAR(32) " + "PRIMARY KEY `id`)"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + /* insert a value into it */ + query = "INSERT INTO `phone` ( `id`, `name`, `number` )" + "VALUES('1', 'Abe', '8675309')"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + query = "SELECT * FROM `phone`"; + r = MsiDatabaseOpenView(hdb, query, &hview); + ok(r == ERROR_SUCCESS, "MsiDatabaseOpenView failed\n"); + r = MsiViewExecute(hview, 0); + ok(r == ERROR_SUCCESS, "MsiViewExecute failed\n"); + r = MsiViewFetch(hview, &hrec); + ok(r == ERROR_SUCCESS, "MsiViewFetch failed\n"); + + /* check the record contains what we put in it */ + r = MsiRecordGetFieldCount(hrec); + ok(r == 3, "record count wrong\n"); + + r = MsiRecordGetInteger(hrec, 1); + ok(r == 1, "field 1 contents wrong\n"); + sz = sizeof buf; + r = MsiRecordGetString(hrec, 2, buf, &sz); + ok(r == ERROR_SUCCESS, "field 2 content fetch failed\n"); + ok(!strcmp(buf,"Abe"), "field 2 content incorrect\n"); + sz = sizeof buf; + r = MsiRecordGetString(hrec, 3, buf, &sz); + ok(r == ERROR_SUCCESS, "field 3 content fetch failed\n"); + ok(!strcmp(buf,"8675309"), "field 3 content incorrect\n"); + + r = MsiViewClose(hview); + ok(r == ERROR_SUCCESS, "MsiViewClose failed\n"); + r = MsiCloseHandle(hview); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + r = MsiDatabaseCommit(hdb); + ok(r == ERROR_SUCCESS, "MsiDatabaseCommit failed\n"); + + r = MsiCloseHandle(hdb); + ok(r == ERROR_SUCCESS, "MsiCloseHandle failed\n"); + + r = DeleteFile(msifile); + ok(r == TRUE, "file didn't exist after commit\n"); +} + +START_TEST(db) +{ + test_msidatabase(); + test_msiinsert(); +} -- 2.11.4.GIT