struct tagMSITABLE
{
BYTE **data;
+ BOOL *data_persistent;
UINT row_count;
- BYTE **nonpersistent_data;
- UINT nonpersistent_row_count;
struct list entry;
MSICOLUMNINFO *colinfo;
UINT col_count;
static UINT get_tablecolumns( MSIDATABASE *db,
LPCWSTR szTableName, MSICOLUMNINFO *colinfo, UINT *sz);
static void msi_free_colinfo( MSICOLUMNINFO *colinfo, UINT count );
+static UINT table_find_insert_idx (MSIVIEW *view, LPCWSTR name, INT *pidx);
static inline UINT bytes_per_column( MSIDATABASE *db, const MSICOLUMNINFO *col )
{
if( MSITYPE_IS_BINARY(col->type) )
return 2;
+
if( col->type & MSITYPE_STRING )
return db->bytes_per_strref;
- if( (col->type & 0xff) > 4 )
+
+ if( (col->type & 0xff) <= 2)
+ return 2;
+
+ if( (col->type & 0xff) != 4 )
ERR("Invalid column size!\n");
- return col->type & 0xff;
+
+ return 4;
}
static int utf2mime(int x)
for( i=0; i<table->row_count; i++ )
msi_free( table->data[i] );
msi_free( table->data );
- for( i=0; i<table->nonpersistent_row_count; i++ )
- msi_free( table->nonpersistent_data[i] );
- msi_free( table->nonpersistent_data );
+ msi_free( table->data_persistent );
msi_free_colinfo( table->colinfo, table->col_count );
msi_free( table->colinfo );
msi_free( table );
t->data = msi_alloc_zero( t->row_count * sizeof (USHORT*) );
if( !t->data )
goto err;
+ t->data_persistent = msi_alloc_zero( t->row_count * sizeof(BOOL));
+ if ( !t->data_persistent )
+ goto err;
/* transpose all the data */
TRACE("Transposing data from %d rows\n", t->row_count );
t->data[i] = msi_alloc( row_size );
if( !t->data[i] )
goto err;
+ t->data_persistent[i] = TRUE;
for( j=0; j<t->col_count; j++ )
{
column_info *col;
MSITABLE *table;
UINT i;
+ INT idx;
/* only add tables that don't exist already */
if( TABLE_Exists(db, name ) )
table->ref_count = 1;
table->row_count = 0;
table->data = NULL;
- table->nonpersistent_row_count = 0;
- table->nonpersistent_data = NULL;
+ table->data_persistent = NULL;
table->colinfo = NULL;
table->col_count = 0;
table->persistent = persistent;
if( r )
goto err;
- r = tv->ops->insert_row( tv, rec, -1, persistent == MSICONDITION_FALSE );
+ r = table_find_insert_idx (tv, name, &idx);
+ if (r != ERROR_SUCCESS)
+ idx = -1;
+
+ r = tv->ops->insert_row( tv, rec, idx, persistent == MSICONDITION_FALSE );
TRACE("insert_row returned %x\n", r);
if( r )
goto err;
if( r )
goto err;
- r = tv->ops->insert_row( tv, rec, -1, FALSE );
+ r = table_find_insert_idx (tv, name, &idx);
+ if (r != ERROR_SUCCESS)
+ idx = -1;
+
+ r = tv->ops->insert_row( tv, rec, idx, FALSE );
if( r )
goto err;
table->row_count = 0;
table->data = NULL;
- table->nonpersistent_row_count = 0;
- table->nonpersistent_data = NULL;
+ table->data_persistent = NULL;
table->colinfo = NULL;
table->col_count = 0;
table->persistent = MSICONDITION_TRUE;
goto err;
}
+ rawsize = 0;
p = rawdata;
for( i=0; i<t->col_count; i++ )
{
{
UINT offset = t->colinfo[i].offset;
+ if (!t->data_persistent[j]) continue;
+ if (i == 0)
+ rawsize += row_size;
+
*p++ = t->data[j][offset];
*p++ = t->data[j][offset + 1];
if( 4 == bytes_per_column( db, &t->colinfo[i] ) )
if( table->data[ i ][ 0 ] == table_id )
return TRUE;
- count = table->nonpersistent_row_count;
- for( i=0; i<count; i++ )
- if( table->nonpersistent_data[ i ][ 0 ] == table_id )
- return TRUE;
-
return FALSE;
}
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT offset, n;
- BYTE **data;
if( !tv->table )
return ERROR_INVALID_PARAMETER;
return ERROR_INVALID_PARAMETER;
/* how many rows are there ? */
- if( row >= tv->table->row_count + tv->table->nonpersistent_row_count )
+ if( row >= tv->table->row_count )
return ERROR_NO_MORE_ITEMS;
if( tv->columns[col-1].offset >= tv->row_size )
if (tv->order)
row = tv->order->reorder[row];
- if (row >= tv->table->row_count)
- {
- row -= tv->table->row_count;
- data = tv->table->nonpersistent_data;
- }
- else
- data = tv->table->data;
-
n = bytes_per_column( tv->db, &tv->columns[col-1] );
if (n != 2 && n != 3 && n != 4)
{
}
offset = tv->columns[col-1].offset;
- *val = read_table_int(data, row, offset, n);
+ *val = read_table_int(tv->table->data, row, offset, n);
/* TRACE("Data [%d][%d] = %d\n", row, col, *val ); */
static UINT TABLE_set_int( MSITABLEVIEW *tv, UINT row, UINT col, UINT val )
{
UINT offset, n, i;
- BYTE **data;
if( !tv->table )
return ERROR_INVALID_PARAMETER;
if( (col==0) || (col>tv->num_cols) )
return ERROR_INVALID_PARAMETER;
- if( row >= tv->table->row_count + tv->table->nonpersistent_row_count )
+ if( row >= tv->table->row_count )
return ERROR_INVALID_PARAMETER;
if( tv->columns[col-1].offset >= tv->row_size )
msi_free( tv->columns[col-1].hash_table );
tv->columns[col-1].hash_table = NULL;
- if (row >= tv->table->row_count)
- {
- row -= tv->table->row_count;
- data = tv->table->nonpersistent_data;
- }
- else
- data = tv->table->data;
-
n = bytes_per_column( tv->db, &tv->columns[col-1] );
if ( n != 2 && n != 3 && n != 4 )
{
offset = tv->columns[col-1].offset;
for ( i = 0; i < n; i++ )
- data[row][offset + i] = (val >> i * 8) & 0xff;
+ tv->table->data[row][offset + i] = (val >> i * 8) & 0xff;
return ERROR_SUCCESS;
}
if ( !(mask&(1<<i)) )
continue;
- /* if row >= tv->table->row_count then it is a non-persistent row */
persistent = (tv->table->persistent != MSICONDITION_FALSE) &&
- (row < tv->table->row_count);
+ (tv->table->data_persistent[row]);
/* FIXME: should we allow updating keys? */
val = 0;
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
BYTE **p, *row;
+ BOOL *b;
UINT sz;
BYTE ***data_ptr;
+ BOOL **data_persist_ptr;
UINT *row_count;
TRACE("%p %s\n", view, temporary ? "TRUE" : "FALSE");
if( !row )
return ERROR_NOT_ENOUGH_MEMORY;
- if( temporary )
- {
- row_count = &tv->table->nonpersistent_row_count;
- data_ptr = &tv->table->nonpersistent_data;
- 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;
- if (*num == -1)
- *num = tv->table->row_count;
- }
+ row_count = &tv->table->row_count;
+ data_ptr = &tv->table->data;
+ data_persist_ptr = &tv->table->data_persistent;
+ if (*num == -1)
+ *num = tv->table->row_count;
sz = (*row_count + 1) * sizeof (BYTE*);
if( *data_ptr )
return ERROR_NOT_ENOUGH_MEMORY;
}
+ sz = (*row_count + 1) * sizeof (BOOL);
+ if( *data_persist_ptr )
+ b = msi_realloc( *data_persist_ptr, sz );
+ else
+ b = msi_alloc( sz );
+ if( !b )
+ {
+ msi_free( row );
+ msi_free( p );
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+
*data_ptr = p;
(*data_ptr)[*row_count] = row;
+
+ *data_persist_ptr = b;
+ (*data_persist_ptr)[*row_count] = !temporary;
+
(*row_count)++;
return ERROR_SUCCESS;
{
if( !tv->table )
return ERROR_INVALID_PARAMETER;
- *rows = tv->table->row_count + tv->table->nonpersistent_row_count;
+ *rows = tv->table->row_count;
}
return ERROR_SUCCESS;
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec, UINT row, BOOL temporary )
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
- UINT i, r, idx, size;
- BYTE **data;
+ UINT i, r;
TRACE("%p %p %s\n", tv, rec, temporary ? "TRUE" : "FALSE" );
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 = tv->table->row_count - 1; i > row; i--)
{
- for (i = 1; i < size - idx; i++)
- memmove(&(data[size - i][0]),
- &(data[size - i - 1][0]), tv->row_size);
+ memmove(&(tv->table->data[i][0]),
+ &(tv->table->data[i - 1][0]), tv->row_size);
+ tv->table->data_persistent[i] = tv->table->data_persistent[i - 1];
}
+ /* Re-set the persistence flag */
+ tv->table->data_persistent[row] = !temporary;
return TABLE_set_row( view, row, rec, (1<<tv->num_cols) - 1 );
}
{
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
UINT r, num_rows, num_cols, i;
- BYTE **data;
TRACE("%p %d\n", tv, row);
if ( row >= num_rows )
return ERROR_FUNCTION_FAILED;
- if ( row < tv->table->row_count )
- {
- num_rows = tv->table->row_count;
- tv->table->row_count--;
- data = tv->table->data;
- }
- else
- {
- num_rows = tv->table->nonpersistent_row_count;
- row -= tv->table->row_count;
- tv->table->nonpersistent_row_count--;
- data = tv->table->nonpersistent_data;
- }
+ num_rows = tv->table->row_count;
+ tv->table->row_count--;
/* reset the hash tables */
for (i = 0; i < tv->num_cols; i++)
return ERROR_SUCCESS;
for (i = row + 1; i < num_rows; i++)
- memcpy(data[i - 1], data[i], tv->row_size);
+ {
+ memcpy(tv->table->data[i - 1], tv->table->data[i], tv->row_size);
+ tv->table->data_persistent[i - 1] = tv->table->data_persistent[i];
+ }
return ERROR_SUCCESS;
}
return TABLE_set_row(view, new_row, rec, (1 << tv->num_cols) - 1);
}
+static UINT msi_table_assign(struct tagMSIVIEW *view, MSIRECORD *rec)
+{
+ MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
+ UINT r, row;
+
+ if (!tv->table)
+ return ERROR_INVALID_PARAMETER;
+
+ r = msi_table_find_row(tv, rec, &row);
+ if (r == ERROR_SUCCESS)
+ return TABLE_set_row(view, row, rec, (1 << tv->num_cols) - 1);
+ else
+ return TABLE_insert_row( view, rec, -1, FALSE );
+}
+
static UINT modify_delete_row( struct tagMSIVIEW *view, MSIRECORD *rec )
{
MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
break;
case MSIMODIFY_ASSIGN:
+ r = msi_table_assign( view, rec );
+ break;
+
case MSIMODIFY_REPLACE:
case MSIMODIFY_MERGE:
case MSIMODIFY_VALIDATE:
if( !tv->columns[col-1].hash_table )
{
UINT i;
- UINT num_rows = tv->table->row_count + tv->table->nonpersistent_row_count;
+ UINT num_rows = tv->table->row_count;
MSICOLUMNHASHENTRY **hash_table;
MSICOLUMNHASHENTRY *new_entry;
data = msi_record_to_row( tv, rec );
if( !data )
return r;
- for( i = 0; i < tv->table->row_count + tv->table->nonpersistent_row_count; i++ )
+ for( i = 0; i < tv->table->row_count; i++ )
{
r = msi_row_matches( tv, i, data );
if( r == ERROR_SUCCESS )
r = TABLE_insert_row( &tv->view, rec, -1, FALSE );
if (r != ERROR_SUCCESS)
- ERR("insert row failed\n");
+ WARN("insert row failed\n");
if ( number != MSI_NULL_INTEGER && !lstrcmpW(name, szColumns) )
msi_update_table_columns( db, table );
r = msi_table_find_row( tv, rec, &row );
if (r != ERROR_SUCCESS)
- ERR("no matching row to transform\n");
+ WARN("no matching row to transform\n");
else if ( mask )
{
TRACE("modifying row [%d]:\n", row);
msi_free( t );
}
}
+
+static UINT table_find_insert_idx (MSIVIEW *view, LPCWSTR name, INT *pidx)
+{
+ UINT r, name_id, row_id;
+ INT idx;
+ MSITABLEVIEW *tv = (MSITABLEVIEW *)view;
+
+ TRACE ("%p %s\n", view, debugstr_w(name));
+
+ r = msi_string2idW(tv->db->strings, name, &name_id);
+ if (r != ERROR_SUCCESS)
+ {
+ *pidx = -1;
+ return r;
+ }
+
+ for( idx = 0; idx < tv->table->row_count; idx++ )
+ {
+ r = TABLE_fetch_int( &tv->view, idx, 1, &row_id );
+ if (row_id > name_id)
+ break;
+ }
+
+ *pidx = idx;
+ return ERROR_SUCCESS;
+}