msi: Update tables using records, not integer by integer.

This commit is contained in:
Mike McCormack 2006-10-26 17:09:47 +09:00 committed by Alexandre Julliard
parent 9b95c27c9c
commit 15bfb30fc3
6 changed files with 122 additions and 98 deletions

View File

@ -76,7 +76,8 @@ static UINT DELETE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IS
static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{ {
MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view; MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
UINT r, i, j, rows = 0, cols = 0; UINT r, i, rows = 0, cols = 0;
MSIRECORD *empty;
TRACE("%p %p\n", dv, record); TRACE("%p %p\n", dv, record);
@ -91,12 +92,17 @@ static UINT DELETE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
return r; return r;
TRACE("blanking %d rows\n", rows); TRACE("blanking %d rows\n", rows);
empty = MSI_CreateRecord( cols );
if (!empty)
return ERROR_FUNCTION_FAILED;
/* blank out all the rows that match */ /* blank out all the rows that match */
for( i=0; i<rows; i++ ) for ( i=0; i<rows; i++ )
for( j=1; j<=cols; j++ ) dv->table->ops->set_row( dv->table, i, empty, (1<<cols)-1 );
dv->table->ops->set_int( dv->table, i, j, 0 );
msiobj_release( &empty->hdr );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }

View File

@ -133,11 +133,11 @@ typedef struct tagMSIVIEWOPS
UINT (*fetch_stream)( struct tagMSIVIEW *, UINT row, UINT col, IStream **stm ); UINT (*fetch_stream)( struct tagMSIVIEW *, UINT row, UINT col, IStream **stm );
/* /*
* get_int - sets one integer at {row,col} in the table * set_row - sets values in a row as specified by mask
* *
* Similar semantics to fetch_int * Similar semantics to fetch_int
*/ */
UINT (*set_int)( struct tagMSIVIEW *, UINT row, UINT col, UINT val ); UINT (*set_row)( struct tagMSIVIEW *, UINT row, MSIRECORD *rec, UINT mask );
/* /*
* Inserts a new row into the database from the records contents * Inserts a new row into the database from the records contents

View File

@ -82,21 +82,46 @@ static UINT SELECT_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IS
return sv->table->ops->fetch_stream( sv->table, row, col, stm ); return sv->table->ops->fetch_stream( sv->table, row, col, stm );
} }
static UINT SELECT_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val ) static UINT SELECT_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
{ {
MSISELECTVIEW *sv = (MSISELECTVIEW*)view; MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
UINT i, expanded_mask = 0, r = ERROR_SUCCESS, col_count = 0;
MSIRECORD *expanded;
TRACE("%p %d %d %04x\n", sv, row, col, val ); TRACE("%p %d %p %08x\n", sv, row, rec, mask );
if( !sv->table ) if ( !sv->table )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
if( (col==0) || (col>sv->num_cols) ) /* test if any of the mask bits are invalid */
return ERROR_FUNCTION_FAILED; if ( mask >= (1<<sv->num_cols) )
return ERROR_INVALID_PARAMETER;
col = sv->cols[ col - 1 ]; /* find the number of columns in the table below */
r = sv->table->ops->get_dimensions( sv->table, NULL, &col_count );
if( r )
return r;
return sv->table->ops->set_int( sv->table, row, col, val ); /* expand the record to the right size for the underlying table */
expanded = MSI_CreateRecord( col_count );
if ( !expanded )
return ERROR_FUNCTION_FAILED;
/* move the right fields across */
for ( i=0; i<sv->num_cols; i++ )
{
r = MSI_RecordCopyField( rec, i+1, expanded, sv->cols[ i ] );
if (r != ERROR_SUCCESS)
break;
expanded_mask |= (1<<(sv->cols[i]-1));
}
/* set the row in the underlying table */
if (r == ERROR_SUCCESS)
r = sv->table->ops->set_row( sv->table, row, expanded, expanded_mask );
msiobj_release( &expanded->hdr );
return r;
} }
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record ) static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
@ -240,7 +265,7 @@ static const MSIVIEWOPS select_ops =
{ {
SELECT_fetch_int, SELECT_fetch_int,
SELECT_fetch_stream, SELECT_fetch_stream,
SELECT_set_int, SELECT_set_row,
SELECT_insert_row, SELECT_insert_row,
SELECT_execute, SELECT_execute,
SELECT_close, SELECT_close,

View File

@ -1101,7 +1101,7 @@ static UINT TABLE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *
{ {
case 4: case 4:
offset = tv->columns[col-1].offset/2; offset = tv->columns[col-1].offset/2;
*val = tv->table->data[row][offset] + *val = tv->table->data[row][offset] +
(tv->table->data[row][offset + 1] << 16); (tv->table->data[row][offset + 1] << 16);
break; break;
case 2: case 2:
@ -1186,9 +1186,8 @@ static UINT TABLE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
return r; return r;
} }
static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val ) static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val )
{ {
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT offset, n; UINT offset, n;
if( !tv->table ) if( !tv->table )
@ -1223,6 +1222,61 @@ static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT TABLE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT i, val, r = ERROR_SUCCESS;
if ( !tv->table )
return ERROR_INVALID_PARAMETER;
/* test if any of the mask bits are invalid */
if ( mask >= (1<<tv->num_cols) )
return ERROR_INVALID_PARAMETER;
for ( i = 0; i < tv->num_cols; i++ )
{
/* only update the fields specified in the mask */
if ( !(mask&(1<<i)) )
continue;
/* FIXME: should we allow updating keys? */
val = 0;
if ( !MSI_RecordIsNull( rec, i + 1 ) )
{
if ( MSITYPE_IS_BINARY(tv->columns[ i ].type) )
{
val = 1; /* refers to the first key column */
}
else if ( tv->columns[i].type & MSITYPE_STRING )
{
LPCWSTR sval = MSI_RecordGetString( rec, i + 1 );
val = msi_addstringW( tv->db->strings, 0, sval, -1, 1 );
}
else if ( 2 == bytes_per_column( &tv->columns[ i ] ) )
{
val = 0x8000 + MSI_RecordGetInteger( rec, i + 1 );
if ( val & 0xffff0000 )
{
ERR("field %u value %d out of range\n", i+1, val - 0x8000 );
return ERROR_FUNCTION_FAILED;
}
}
else
{
INT ival = MSI_RecordGetInteger( rec, i + 1 );
val = ival ^ 0x80000000;
}
}
r = TABLE_set_int( tv, row, i+1, val );
if ( r != ERROR_SUCCESS )
break;
}
return r;
}
static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num ) static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num )
{ {
MSITABLEVIEW *tv = (MSITABLEVIEW*)view; MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
@ -1365,43 +1419,6 @@ static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT msi_table_modify_row( MSITABLEVIEW *tv, MSIRECORD *rec,
UINT row, UINT mask )
{
UINT i, val, r = ERROR_SUCCESS;
TRACE("%p %p %u %08x\n", tv, rec, row, mask );
for( i = 0; i < tv->num_cols; i++ )
{
/* set keys or values specified in the mask */
if( (~tv->columns[i].type & MSITYPE_KEY) && (~mask & (1<<i)) )
continue;
if (MSI_RecordIsNull( rec, i+1))
val = 0;
else if( (tv->columns[i].type & MSITYPE_STRING) &&
! MSITYPE_IS_BINARY(tv->columns[i].type) )
{
const WCHAR *str = MSI_RecordGetString( rec, i+1 );
val = msi_addstringW( tv->db->strings, 0, str, -1, 1 );
}
else
{
val = MSI_RecordGetInteger( rec, i+1 );
if ( 2 == bytes_per_column( &tv->columns[i] ) )
val ^= 0x8000;
else
val ^= 0x80000000;
}
r = TABLE_set_int( &tv->view, row, i+1, val );
if( r )
break;
}
return r;
}
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec ) static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
{ {
MSITABLEVIEW *tv = (MSITABLEVIEW*)view; MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
@ -1419,7 +1436,7 @@ static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
if( r != ERROR_SUCCESS ) if( r != ERROR_SUCCESS )
return r; return r;
return msi_table_modify_row( tv, rec, row, ~0 ); return TABLE_set_row( view, row, rec, (1<<tv->num_cols) - 1 );
} }
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode, static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
@ -1588,7 +1605,7 @@ static const MSIVIEWOPS table_ops =
{ {
TABLE_fetch_int, TABLE_fetch_int,
TABLE_fetch_stream, TABLE_fetch_stream,
TABLE_set_int, TABLE_set_row,
TABLE_insert_row, TABLE_insert_row,
TABLE_execute, TABLE_execute,
TABLE_close, TABLE_close,
@ -1874,8 +1891,9 @@ static UINT msi_table_find_row( MSITABLEVIEW *tv, MSIRECORD *rec, UINT *row )
static UINT msi_delete_row( MSITABLEVIEW *tv, UINT row ) static UINT msi_delete_row( MSITABLEVIEW *tv, UINT row )
{ {
UINT i; UINT i;
for( i=1; i<=tv->num_cols; i++ ) for( i=1; i<=tv->num_cols; i++ )
tv->view.ops->set_int( &tv->view, row, i, 0 ); TABLE_set_int( tv, row, i, 0 );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
@ -1997,7 +2015,7 @@ static UINT msi_table_load_transform( MSIDATABASE *db, IStorage *stg,
else if ( mask ) else if ( mask )
{ {
TRACE("modifying row [%d]:\n", row); TRACE("modifying row [%d]:\n", row);
msi_table_modify_row( tv, rec, row, mask ); TABLE_set_row( &tv->view, row, rec, mask );
} }
else else
{ {

View File

@ -58,7 +58,7 @@ static UINT UPDATE_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT
static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record ) static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{ {
MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view; MSIUPDATEVIEW *uv = (MSIUPDATEVIEW*)view;
UINT n, type, val, r, row, col_count = 0, row_count = 0; UINT i, r, col_count = 0, row_count = 0;
MSIRECORD *values = NULL; MSIRECORD *values = NULL;
MSIVIEW *wv; MSIVIEW *wv;
@ -75,47 +75,22 @@ static UINT UPDATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
r = wv->ops->get_dimensions( wv, &row_count, &col_count ); r = wv->ops->get_dimensions( wv, &row_count, &col_count );
if( r ) if( r )
goto err; return r;
values = msi_query_merge_record( col_count, uv->vals, record ); values = msi_query_merge_record( col_count, uv->vals, record );
if (!values) if (!values)
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
for( row = 0; row < row_count; row++ ) for ( i=0; i<row_count; i++ )
{ {
for( n = 1; n <= col_count; n++ ) r = wv->ops->set_row( wv, i, values, (1 << col_count) - 1 );
{ if (r != ERROR_SUCCESS)
r = wv->ops->get_column_info( wv, n, NULL, &type ); break;
if( r )
break;
if( MSI_RecordIsNull( values, n ))
val = 0;
else if( type & MSITYPE_STRING )
{
const WCHAR *str = MSI_RecordGetString( values, n );
val = msi_addstringW( uv->db->strings, 0, str, -1, 1 );
}
else if ((type & 0xff) == 2)
{
val = MSI_RecordGetInteger( values, n );
val ^= 0x8000;
}
else
{
val = MSI_RecordGetInteger( values, n );
val ^= 0x80000000;
}
r = wv->ops->set_int( wv, row, n, val );
if( r )
break;
}
} }
msiobj_release( &values->hdr ); msiobj_release( &values->hdr );
err: return r;
return ERROR_SUCCESS;
} }

View File

@ -82,21 +82,21 @@ static UINT WHERE_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, ISt
return wv->table->ops->fetch_stream( wv->table, row, col, stm ); return wv->table->ops->fetch_stream( wv->table, row, col, stm );
} }
static UINT WHERE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val ) static UINT WHERE_set_row( struct tagMSIVIEW *view, UINT row, MSIRECORD *rec, UINT mask )
{ {
MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view; MSIWHEREVIEW *wv = (MSIWHEREVIEW*)view;
TRACE("%p %d %d %04x\n", wv, row, col, val ); TRACE("%p %d %p %08x\n", wv, row, rec, mask );
if( !wv->table ) if( !wv->table )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
if( row > wv->row_count ) if( row > wv->row_count )
return ERROR_NO_MORE_ITEMS; return ERROR_NO_MORE_ITEMS;
row = wv->reorder[ row ]; row = wv->reorder[ row ];
return wv->table->ops->set_int( wv->table, row, col, val ); return wv->table->ops->set_row( wv->table, row, rec, mask );
} }
static INT INT_evaluate( INT lval, UINT op, INT rval ) static INT INT_evaluate( INT lval, UINT op, INT rval )
@ -420,7 +420,7 @@ static const MSIVIEWOPS where_ops =
{ {
WHERE_fetch_int, WHERE_fetch_int,
WHERE_fetch_stream, WHERE_fetch_stream,
WHERE_set_int, WHERE_set_row,
NULL, NULL,
WHERE_execute, WHERE_execute,
WHERE_close, WHERE_close,