msi: Correctly order transposed column values in the INSERT query.
This commit is contained in:
parent
4063a32f80
commit
b3c9875cf7
|
@ -1349,7 +1349,7 @@ static UINT merge_table(MSIDATABASE *db, MERGETABLE *table)
|
|||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = tv->ops->insert_row(tv, row->data, FALSE);
|
||||
r = tv->ops->insert_row(tv, row->data, -1, FALSE);
|
||||
tv->ops->delete(tv);
|
||||
|
||||
if (r != ERROR_SUCCESS)
|
||||
|
|
|
@ -41,6 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
|
|||
typedef struct tagMSIINSERTVIEW
|
||||
{
|
||||
MSIVIEW view;
|
||||
MSIVIEW *table;
|
||||
MSIDATABASE *db;
|
||||
BOOL bIsTemp;
|
||||
MSIVIEW *sv;
|
||||
|
@ -102,10 +103,121 @@ err:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/* checks to see if the column order specified in the INSERT query
|
||||
* matches the column order of the table
|
||||
*/
|
||||
static BOOL msi_columns_in_order(MSIINSERTVIEW *iv, UINT col_count)
|
||||
{
|
||||
LPWSTR a, b = NULL;
|
||||
UINT i;
|
||||
int res;
|
||||
|
||||
for (i = 1; i <= col_count; i++)
|
||||
{
|
||||
iv->sv->ops->get_column_info(iv->sv, i, &a, NULL);
|
||||
iv->table->ops->get_column_info(iv->table, i, &b, NULL);
|
||||
|
||||
res = lstrcmpW(a, b);
|
||||
msi_free(a);
|
||||
msi_free(b);
|
||||
|
||||
if (res != 0)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* rearranges the data in the record to be inserted based on column order,
|
||||
* and pads the record for any missing columns in the INSERT query
|
||||
*/
|
||||
static UINT msi_arrange_record(MSIINSERTVIEW *iv, MSIRECORD **values)
|
||||
{
|
||||
MSIRECORD *padded;
|
||||
UINT col_count, val_count;
|
||||
UINT r, i, colidx;
|
||||
LPWSTR a, b = NULL;
|
||||
int res;
|
||||
|
||||
r = iv->table->ops->get_dimensions(iv->table, NULL, &col_count);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
val_count = MSI_RecordGetFieldCount(*values);
|
||||
|
||||
/* check to see if the columns are arranged already
|
||||
* to avoid unnecessary copying
|
||||
*/
|
||||
if (col_count == val_count && msi_columns_in_order(iv, col_count))
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
padded = MSI_CreateRecord(col_count);
|
||||
if (!padded)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
for (colidx = 1; colidx <= val_count; colidx++)
|
||||
{
|
||||
r = iv->sv->ops->get_column_info(iv->sv, colidx, &a, NULL);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto err;
|
||||
|
||||
for (i = 1; i <= col_count; i++)
|
||||
{
|
||||
r = iv->table->ops->get_column_info(iv->table, i, &b, NULL);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto err;
|
||||
|
||||
res = lstrcmpW(a, b);
|
||||
msi_free(b);
|
||||
|
||||
if (res == 0)
|
||||
{
|
||||
MSI_RecordCopyField(*values, colidx, padded, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
msi_free(a);
|
||||
}
|
||||
|
||||
msiobj_release(&(*values)->hdr);
|
||||
*values = padded;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
err:
|
||||
msiobj_release(&padded->hdr);
|
||||
return r;
|
||||
}
|
||||
|
||||
static BOOL row_has_null_primary_keys(MSIINSERTVIEW *iv, MSIRECORD *row)
|
||||
{
|
||||
UINT r, i, col_count, type;
|
||||
|
||||
r = iv->table->ops->get_dimensions( iv->table, NULL, &col_count );
|
||||
if (r != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
for (i = 1; i <= col_count; i++)
|
||||
{
|
||||
r = iv->table->ops->get_column_info(iv->table, i, NULL, &type);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
if (!(type & MSITYPE_KEY))
|
||||
continue;
|
||||
|
||||
if (MSI_RecordIsNull(row, i))
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||
{
|
||||
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
|
||||
UINT r, col_count = 0;
|
||||
UINT r, row = -1, col_count = 0;
|
||||
MSIVIEW *sv;
|
||||
MSIRECORD *values = NULL;
|
||||
|
||||
|
@ -116,7 +228,7 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = sv->ops->execute( sv, 0 );
|
||||
TRACE("tv execute returned %x\n", r);
|
||||
TRACE("sv execute returned %x\n", r);
|
||||
if( r )
|
||||
return r;
|
||||
|
||||
|
@ -132,7 +244,15 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
if( !values )
|
||||
goto err;
|
||||
|
||||
r = sv->ops->insert_row( sv, values, iv->bIsTemp );
|
||||
r = msi_arrange_record( iv, &values );
|
||||
if( r != ERROR_SUCCESS )
|
||||
goto err;
|
||||
|
||||
/* rows with NULL primary keys are inserted at the beginning of the table */
|
||||
if( row_has_null_primary_keys( iv, values ) )
|
||||
row = 0;
|
||||
|
||||
r = iv->table->ops->insert_row( iv->table, values, row, iv->bIsTemp );
|
||||
|
||||
err:
|
||||
if( values )
|
||||
|
@ -282,6 +402,7 @@ UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
|
|||
/* fill the structure */
|
||||
iv->view.ops = &insert_ops;
|
||||
msiobj_addref( &db->hdr );
|
||||
iv->table = tv;
|
||||
iv->db = db;
|
||||
iv->vals = values;
|
||||
iv->bIsTemp = temp;
|
||||
|
|
|
@ -199,7 +199,7 @@ typedef struct tagMSIVIEWOPS
|
|||
/*
|
||||
* Inserts a new row into the database from the records contents
|
||||
*/
|
||||
UINT (*insert_row)( struct tagMSIVIEW *view, MSIRECORD *record, BOOL temporary );
|
||||
UINT (*insert_row)( struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary );
|
||||
|
||||
/*
|
||||
* Deletes a row from the database
|
||||
|
|
|
@ -136,7 +136,7 @@ static UINT SELECT_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, U
|
|||
return r;
|
||||
}
|
||||
|
||||
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, BOOL temporary )
|
||||
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, UINT row, BOOL temporary )
|
||||
{
|
||||
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
|
||||
UINT i, table_cols, r;
|
||||
|
@ -161,7 +161,7 @@ static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, BOOL
|
|||
goto fail;
|
||||
}
|
||||
|
||||
r = sv->table->ops->insert_row( sv->table, outrec, temporary );
|
||||
r = sv->table->ops->insert_row( sv->table, outrec, row, temporary );
|
||||
|
||||
fail:
|
||||
msiobj_release( &outrec->hdr );
|
||||
|
|
|
@ -243,14 +243,19 @@ done:
|
|||
return r;
|
||||
}
|
||||
|
||||
static UINT STORAGES_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary)
|
||||
static UINT STORAGES_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
|
||||
{
|
||||
MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
|
||||
|
||||
if (!storages_set_table_size(sv, ++sv->num_rows))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
return STORAGES_set_row(view, sv->num_rows - 1, rec, 0);
|
||||
if (row == -1)
|
||||
row = sv->num_rows - 1;
|
||||
|
||||
/* FIXME have to readjust rows */
|
||||
|
||||
return STORAGES_set_row(view, row, rec, 0);
|
||||
}
|
||||
|
||||
static UINT STORAGES_delete_row(struct tagMSIVIEW *view, UINT row)
|
||||
|
@ -361,7 +366,7 @@ static UINT storages_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
|
|||
if (r == ERROR_SUCCESS)
|
||||
return storages_modify_update(view, rec);
|
||||
|
||||
return STORAGES_insert_row(view, rec, FALSE);
|
||||
return STORAGES_insert_row(view, rec, -1, FALSE);
|
||||
}
|
||||
|
||||
static UINT STORAGES_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
|
||||
|
@ -377,7 +382,7 @@ static UINT STORAGES_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIR
|
|||
break;
|
||||
|
||||
case MSIMODIFY_INSERT:
|
||||
r = STORAGES_insert_row(view, rec, FALSE);
|
||||
r = STORAGES_insert_row(view, rec, -1, FALSE);
|
||||
break;
|
||||
|
||||
case MSIMODIFY_UPDATE:
|
||||
|
|
|
@ -209,14 +209,19 @@ done:
|
|||
return r;
|
||||
}
|
||||
|
||||
static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary)
|
||||
static UINT STREAMS_insert_row(struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary)
|
||||
{
|
||||
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
|
||||
|
||||
if (!streams_set_table_size(sv, ++sv->num_rows))
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
return STREAMS_set_row(view, sv->num_rows - 1, rec, 0);
|
||||
if (row == -1)
|
||||
row = sv->num_rows - 1;
|
||||
|
||||
/* FIXME have to readjust rows */
|
||||
|
||||
return STREAMS_set_row(view, row, rec, 0);
|
||||
}
|
||||
|
||||
static UINT STREAMS_delete_row(struct tagMSIVIEW *view, UINT row)
|
||||
|
@ -327,7 +332,7 @@ static UINT streams_modify_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
|
|||
if (r == ERROR_SUCCESS)
|
||||
return streams_modify_update(view, rec);
|
||||
|
||||
return STREAMS_insert_row(view, rec, FALSE);
|
||||
return STREAMS_insert_row(view, rec, -1, FALSE);
|
||||
}
|
||||
|
||||
static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRECORD *rec, UINT row)
|
||||
|
@ -343,7 +348,7 @@ static UINT STREAMS_modify(struct tagMSIVIEW *view, MSIMODIFY eModifyMode, MSIRE
|
|||
break;
|
||||
|
||||
case MSIMODIFY_INSERT:
|
||||
r = STREAMS_insert_row(view, rec, FALSE);
|
||||
r = STREAMS_insert_row(view, rec, -1, FALSE);
|
||||
break;
|
||||
|
||||
case MSIMODIFY_UPDATE:
|
||||
|
|
|
@ -683,7 +683,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
|||
if( r )
|
||||
goto err;
|
||||
|
||||
r = tv->ops->insert_row( tv, rec, persistent == MSICONDITION_FALSE );
|
||||
r = tv->ops->insert_row( tv, rec, -1, persistent == MSICONDITION_FALSE );
|
||||
TRACE("insert_row returned %x\n", r);
|
||||
if( r )
|
||||
goto err;
|
||||
|
@ -733,7 +733,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
|||
if( r )
|
||||
goto err;
|
||||
|
||||
r = tv->ops->insert_row( tv, rec, FALSE );
|
||||
r = tv->ops->insert_row( tv, rec, -1, FALSE );
|
||||
if( r )
|
||||
goto err;
|
||||
|
||||
|
@ -1372,13 +1372,15 @@ static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num, BOOL tempo
|
|||
{
|
||||
row_count = &tv->table->nonpersistent_row_count;
|
||||
data_ptr = &tv->table->nonpersistent_data;
|
||||
*num = tv->table->row_count + tv->table->nonpersistent_row_count;
|
||||
if (*num == -1)
|
||||
*num = tv->table->row_count + tv->table->nonpersistent_row_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
row_count = &tv->table->row_count;
|
||||
data_ptr = &tv->table->data;
|
||||
*num = tv->table->row_count;
|
||||
if (*num == -1)
|
||||
*num = tv->table->row_count;
|
||||
}
|
||||
|
||||
sz = (*row_count + 1) * sizeof (BYTE*);
|
||||
|
@ -1497,10 +1499,11 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temporary )
|
||||
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary )
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
UINT r, row = -1;
|
||||
UINT i, r, idx, size;
|
||||
BYTE **data;
|
||||
|
||||
TRACE("%p %p %s\n", tv, rec, temporary ? "TRUE" : "FALSE" );
|
||||
|
||||
|
@ -1514,6 +1517,27 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, BOOL temp
|
|||
if( r != ERROR_SUCCESS )
|
||||
return r;
|
||||
|
||||
idx = row;
|
||||
if( temporary )
|
||||
{
|
||||
data = tv->table->nonpersistent_data;
|
||||
size = tv->table->nonpersistent_row_count;
|
||||
idx -= tv->table->row_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = tv->table->data;
|
||||
size = tv->table->row_count;
|
||||
}
|
||||
|
||||
/* shift the rows to make room for the new row */
|
||||
if( idx != size - 1 )
|
||||
{
|
||||
for (i = 1; i < size - idx; i++)
|
||||
memmove(&(data[size - i][0]),
|
||||
&(data[size - i - 1][0]), tv->row_size);
|
||||
}
|
||||
|
||||
return TABLE_set_row( view, row, rec, (1<<tv->num_cols) - 1 );
|
||||
}
|
||||
|
||||
|
@ -1641,14 +1665,14 @@ static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
|||
r = table_validate_new( tv, rec );
|
||||
if (r != ERROR_SUCCESS)
|
||||
break;
|
||||
r = TABLE_insert_row( view, rec, FALSE );
|
||||
r = TABLE_insert_row( view, rec, -1, FALSE );
|
||||
break;
|
||||
|
||||
case MSIMODIFY_INSERT_TEMPORARY:
|
||||
r = table_validate_new( tv, rec );
|
||||
if (r != ERROR_SUCCESS)
|
||||
break;
|
||||
r = TABLE_insert_row( view, rec, TRUE );
|
||||
r = TABLE_insert_row( view, rec, -1, TRUE );
|
||||
break;
|
||||
|
||||
case MSIMODIFY_REFRESH:
|
||||
|
@ -1880,7 +1904,7 @@ static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number
|
|||
MSI_RecordSetStringW(rec, 3, column);
|
||||
MSI_RecordSetInteger(rec, 4, type);
|
||||
|
||||
r = TABLE_insert_row(&tv->view, rec, FALSE);
|
||||
r = TABLE_insert_row(&tv->view, rec, -1, FALSE);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
|
@ -2354,7 +2378,10 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
|
|||
else
|
||||
{
|
||||
data[i] = MSI_RecordGetInteger( rec, i+1 );
|
||||
if ((tv->columns[i].type&0xff) == 2)
|
||||
|
||||
if (data[i] == MSI_NULL_INTEGER)
|
||||
data[i] = 0;
|
||||
else if ((tv->columns[i].type&0xff) == 2)
|
||||
data[i] += 0x8000;
|
||||
else
|
||||
data[i] += 0x80000000;
|
||||
|
@ -2548,7 +2575,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
|
|||
}
|
||||
}
|
||||
|
||||
r = TABLE_insert_row( &tv->view, rec, FALSE );
|
||||
r = TABLE_insert_row( &tv->view, rec, -1, FALSE );
|
||||
if (r != ERROR_SUCCESS)
|
||||
ERR("insert row failed\n");
|
||||
|
||||
|
|
|
@ -6927,6 +6927,115 @@ static void test_dbmerge(void)
|
|||
DeleteFileA("binary.dat");
|
||||
}
|
||||
|
||||
UINT ordervals[6][3] =
|
||||
{
|
||||
{ MSI_NULL_INTEGER, 12, 13 },
|
||||
{ 1, 2, 3 },
|
||||
{ 6, 4, 5 },
|
||||
{ 8, 9, 7 },
|
||||
{ 10, 11, MSI_NULL_INTEGER },
|
||||
{ 14, MSI_NULL_INTEGER, 15 }
|
||||
};
|
||||
|
||||
static void test_insertorder(void)
|
||||
{
|
||||
MSIHANDLE hdb, view, rec;
|
||||
LPCSTR query;
|
||||
UINT r;
|
||||
int i;
|
||||
|
||||
hdb = create_db();
|
||||
ok(hdb, "failed to create db\n");
|
||||
|
||||
query = "CREATE TABLE `T` ( `A` SHORT, `B` SHORT, `C` SHORT PRIMARY KEY `A`)";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` ( `B`, `C`, `A` ) VALUES ( 4, 5, 6 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` ( `C`, `A`, `B` ) VALUES ( 7, 8, 9 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` ( `A`, `B` ) VALUES ( 10, 11 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` ( `B`, `C` ) VALUES ( 12, 13 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
/* fails because the primary key already
|
||||
* has an MSI_NULL_INTEGER value set above
|
||||
*/
|
||||
query = "INSERT INTO `T` ( `C` ) VALUES ( 14 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_FUNCTION_FAILED,
|
||||
"Expected ERROR_FUNCTION_FAILED, got %d\n", r);
|
||||
|
||||
/* replicate the error where primary key is set twice */
|
||||
query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 1, 14 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_FUNCTION_FAILED,
|
||||
"Expected ERROR_FUNCTION_FAILED, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` ( `A`, `C` ) VALUES ( 14, 15 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` VALUES ( 16 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_BAD_QUERY_SYNTAX,
|
||||
"Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` VALUES ( 17, 18 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_BAD_QUERY_SYNTAX,
|
||||
"Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `T` VALUES ( 19, 20, 21 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
ok(r == ERROR_BAD_QUERY_SYNTAX,
|
||||
"Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
|
||||
|
||||
query = "SELECT * FROM `T`";
|
||||
r = MsiDatabaseOpenView(hdb, query, &view);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
r = MsiViewExecute(view, 0);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
r = MsiViewFetch(view, &rec);
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
r = MsiRecordGetInteger(rec, 1);
|
||||
ok(r == ordervals[i][0], "Expected %d, got %d\n", ordervals[i][0], r);
|
||||
|
||||
r = MsiRecordGetInteger(rec, 2);
|
||||
ok(r == ordervals[i][1], "Expected %d, got %d\n", ordervals[i][1], r);
|
||||
|
||||
r = MsiRecordGetInteger(rec, 3);
|
||||
ok(r == ordervals[i][2], "Expected %d, got %d\n", ordervals[i][2], r);
|
||||
|
||||
MsiCloseHandle(rec);
|
||||
}
|
||||
|
||||
r = MsiViewFetch(view, &rec);
|
||||
ok(r == ERROR_NO_MORE_ITEMS, "Expected ERROR_NO_MORE_ITEMS, got %d\n", r);
|
||||
|
||||
MsiViewClose(view);
|
||||
MsiCloseHandle(view);
|
||||
MsiCloseHandle(hdb);
|
||||
DeleteFileA(msifile);
|
||||
}
|
||||
|
||||
START_TEST(db)
|
||||
{
|
||||
test_msidatabase();
|
||||
|
@ -6968,4 +7077,5 @@ START_TEST(db)
|
|||
test_dbtopackage();
|
||||
test_droptable();
|
||||
test_dbmerge();
|
||||
test_insertorder();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue