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)
|
if (r != ERROR_SUCCESS)
|
||||||
return r;
|
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);
|
tv->ops->delete(tv);
|
||||||
|
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
|
|
|
@ -41,6 +41,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(msidb);
|
||||||
typedef struct tagMSIINSERTVIEW
|
typedef struct tagMSIINSERTVIEW
|
||||||
{
|
{
|
||||||
MSIVIEW view;
|
MSIVIEW view;
|
||||||
|
MSIVIEW *table;
|
||||||
MSIDATABASE *db;
|
MSIDATABASE *db;
|
||||||
BOOL bIsTemp;
|
BOOL bIsTemp;
|
||||||
MSIVIEW *sv;
|
MSIVIEW *sv;
|
||||||
|
@ -102,10 +103,121 @@ err:
|
||||||
return NULL;
|
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 )
|
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
{
|
{
|
||||||
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
|
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
|
||||||
UINT r, col_count = 0;
|
UINT r, row = -1, col_count = 0;
|
||||||
MSIVIEW *sv;
|
MSIVIEW *sv;
|
||||||
MSIRECORD *values = NULL;
|
MSIRECORD *values = NULL;
|
||||||
|
|
||||||
|
@ -116,7 +228,7 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
return ERROR_FUNCTION_FAILED;
|
return ERROR_FUNCTION_FAILED;
|
||||||
|
|
||||||
r = sv->ops->execute( sv, 0 );
|
r = sv->ops->execute( sv, 0 );
|
||||||
TRACE("tv execute returned %x\n", r);
|
TRACE("sv execute returned %x\n", r);
|
||||||
if( r )
|
if( r )
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -132,7 +244,15 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||||
if( !values )
|
if( !values )
|
||||||
goto err;
|
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:
|
err:
|
||||||
if( values )
|
if( values )
|
||||||
|
@ -282,6 +402,7 @@ UINT INSERT_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
|
||||||
/* fill the structure */
|
/* fill the structure */
|
||||||
iv->view.ops = &insert_ops;
|
iv->view.ops = &insert_ops;
|
||||||
msiobj_addref( &db->hdr );
|
msiobj_addref( &db->hdr );
|
||||||
|
iv->table = tv;
|
||||||
iv->db = db;
|
iv->db = db;
|
||||||
iv->vals = values;
|
iv->vals = values;
|
||||||
iv->bIsTemp = temp;
|
iv->bIsTemp = temp;
|
||||||
|
|
|
@ -199,7 +199,7 @@ typedef struct tagMSIVIEWOPS
|
||||||
/*
|
/*
|
||||||
* Inserts a new row into the database from the records contents
|
* 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
|
* 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;
|
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;
|
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
|
||||||
UINT i, table_cols, r;
|
UINT i, table_cols, r;
|
||||||
|
@ -161,7 +161,7 @@ static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record, BOOL
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
r = sv->table->ops->insert_row( sv->table, outrec, temporary );
|
r = sv->table->ops->insert_row( sv->table, outrec, row, temporary );
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
msiobj_release( &outrec->hdr );
|
msiobj_release( &outrec->hdr );
|
||||||
|
|
|
@ -243,14 +243,19 @@ done:
|
||||||
return r;
|
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;
|
MSISTORAGESVIEW *sv = (MSISTORAGESVIEW *)view;
|
||||||
|
|
||||||
if (!storages_set_table_size(sv, ++sv->num_rows))
|
if (!storages_set_table_size(sv, ++sv->num_rows))
|
||||||
return ERROR_FUNCTION_FAILED;
|
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)
|
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)
|
if (r == ERROR_SUCCESS)
|
||||||
return storages_modify_update(view, rec);
|
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)
|
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;
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_INSERT:
|
case MSIMODIFY_INSERT:
|
||||||
r = STORAGES_insert_row(view, rec, FALSE);
|
r = STORAGES_insert_row(view, rec, -1, FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_UPDATE:
|
case MSIMODIFY_UPDATE:
|
||||||
|
|
|
@ -209,14 +209,19 @@ done:
|
||||||
return r;
|
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;
|
MSISTREAMSVIEW *sv = (MSISTREAMSVIEW *)view;
|
||||||
|
|
||||||
if (!streams_set_table_size(sv, ++sv->num_rows))
|
if (!streams_set_table_size(sv, ++sv->num_rows))
|
||||||
return ERROR_FUNCTION_FAILED;
|
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)
|
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)
|
if (r == ERROR_SUCCESS)
|
||||||
return streams_modify_update(view, rec);
|
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)
|
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;
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_INSERT:
|
case MSIMODIFY_INSERT:
|
||||||
r = STREAMS_insert_row(view, rec, FALSE);
|
r = STREAMS_insert_row(view, rec, -1, FALSE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_UPDATE:
|
case MSIMODIFY_UPDATE:
|
||||||
|
|
|
@ -683,7 +683,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
||||||
if( r )
|
if( r )
|
||||||
goto err;
|
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);
|
TRACE("insert_row returned %x\n", r);
|
||||||
if( r )
|
if( r )
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -733,7 +733,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
||||||
if( r )
|
if( r )
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
r = tv->ops->insert_row( tv, rec, FALSE );
|
r = tv->ops->insert_row( tv, rec, -1, FALSE );
|
||||||
if( r )
|
if( r )
|
||||||
goto err;
|
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;
|
row_count = &tv->table->nonpersistent_row_count;
|
||||||
data_ptr = &tv->table->nonpersistent_data;
|
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
|
else
|
||||||
{
|
{
|
||||||
row_count = &tv->table->row_count;
|
row_count = &tv->table->row_count;
|
||||||
data_ptr = &tv->table->data;
|
data_ptr = &tv->table->data;
|
||||||
*num = tv->table->row_count;
|
if (*num == -1)
|
||||||
|
*num = tv->table->row_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
sz = (*row_count + 1) * sizeof (BYTE*);
|
sz = (*row_count + 1) * sizeof (BYTE*);
|
||||||
|
@ -1497,10 +1499,11 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
|
||||||
return ERROR_SUCCESS;
|
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;
|
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" );
|
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 )
|
if( r != ERROR_SUCCESS )
|
||||||
return r;
|
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 );
|
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 );
|
r = table_validate_new( tv, rec );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
break;
|
break;
|
||||||
r = TABLE_insert_row( view, rec, FALSE );
|
r = TABLE_insert_row( view, rec, -1, FALSE );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_INSERT_TEMPORARY:
|
case MSIMODIFY_INSERT_TEMPORARY:
|
||||||
r = table_validate_new( tv, rec );
|
r = table_validate_new( tv, rec );
|
||||||
if (r != ERROR_SUCCESS)
|
if (r != ERROR_SUCCESS)
|
||||||
break;
|
break;
|
||||||
r = TABLE_insert_row( view, rec, TRUE );
|
r = TABLE_insert_row( view, rec, -1, TRUE );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSIMODIFY_REFRESH:
|
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_RecordSetStringW(rec, 3, column);
|
||||||
MSI_RecordSetInteger(rec, 4, type);
|
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)
|
if (r != ERROR_SUCCESS)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -2354,7 +2378,10 @@ static UINT* msi_record_to_row( const MSITABLEVIEW *tv, MSIRECORD *rec )
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
data[i] = MSI_RecordGetInteger( rec, i+1 );
|
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;
|
data[i] += 0x8000;
|
||||||
else
|
else
|
||||||
data[i] += 0x80000000;
|
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)
|
if (r != ERROR_SUCCESS)
|
||||||
ERR("insert row failed\n");
|
ERR("insert row failed\n");
|
||||||
|
|
||||||
|
|
|
@ -6927,6 +6927,115 @@ static void test_dbmerge(void)
|
||||||
DeleteFileA("binary.dat");
|
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)
|
START_TEST(db)
|
||||||
{
|
{
|
||||||
test_msidatabase();
|
test_msidatabase();
|
||||||
|
@ -6968,4 +7077,5 @@ START_TEST(db)
|
||||||
test_dbtopackage();
|
test_dbtopackage();
|
||||||
test_droptable();
|
test_droptable();
|
||||||
test_dbmerge();
|
test_dbmerge();
|
||||||
|
test_insertorder();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue