Implement MsiModifyView (MSIMODIFY_INSERT_TEMPORARY).
This commit is contained in:
parent
1bac61f8e5
commit
e8d1a167df
|
@ -60,10 +60,11 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
{
|
||||
MSICREATEVIEW *cv = (MSICREATEVIEW*)view;
|
||||
column_info *col;
|
||||
UINT r, nField, row, table_val, column_val;
|
||||
UINT r, nField;
|
||||
static const WCHAR szTables[] = { '_','T','a','b','l','e','s',0 };
|
||||
static const WCHAR szColumns[] = { '_','C','o','l','u','m','n','s',0 };
|
||||
MSIVIEW *tv = NULL;
|
||||
MSIRECORD *rec;
|
||||
|
||||
TRACE("%p Table %s (%s)\n", cv, debugstr_w(cv->name),
|
||||
cv->bIsTemp?"temporary":"permanent");
|
||||
|
@ -72,12 +73,6 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
if( TABLE_Exists(cv->db, cv->name ) )
|
||||
return ERROR_BAD_QUERY_SYNTAX;
|
||||
|
||||
/* add the name to the _Tables table */
|
||||
table_val = msi_addstringW( cv->db->strings, 0, cv->name, -1, 1 );
|
||||
TRACE("New string %s -> %d\n", debugstr_w( cv->name ), table_val );
|
||||
if( table_val < 0 )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
r = TABLE_CreateView( cv->db, szTables, &tv );
|
||||
TRACE("CreateView returned %x\n", r);
|
||||
if( r )
|
||||
|
@ -86,20 +81,26 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
r = tv->ops->execute( tv, 0 );
|
||||
TRACE("tv execute returned %x\n", r);
|
||||
if( r )
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
row = -1;
|
||||
r = tv->ops->insert_row( tv, &row );
|
||||
rec = MSI_CreateRecord( 1 );
|
||||
if( !rec )
|
||||
goto err;
|
||||
|
||||
r = MSI_RecordSetStringW( rec, 1, cv->name );
|
||||
if( r )
|
||||
goto err;
|
||||
|
||||
r = tv->ops->insert_row( tv, rec );
|
||||
TRACE("insert_row returned %x\n", r);
|
||||
if( r )
|
||||
goto err;
|
||||
|
||||
r = tv->ops->set_int( tv, row, 1, table_val );
|
||||
if( r )
|
||||
goto err;
|
||||
tv->ops->delete( tv );
|
||||
tv = NULL;
|
||||
|
||||
msiobj_release( &rec->hdr );
|
||||
|
||||
/* add each column to the _Columns table */
|
||||
r = TABLE_CreateView( cv->db, szColumns, &tv );
|
||||
if( r )
|
||||
|
@ -108,7 +109,15 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
r = tv->ops->execute( tv, 0 );
|
||||
TRACE("tv execute returned %x\n", r);
|
||||
if( r )
|
||||
return r;
|
||||
goto err;
|
||||
|
||||
rec = MSI_CreateRecord( 4 );
|
||||
if( !rec )
|
||||
goto err;
|
||||
|
||||
r = MSI_RecordSetStringW( rec, 1, cv->name );
|
||||
if( r )
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* need to set the table, column number, col name and type
|
||||
|
@ -117,36 +126,21 @@ static UINT CREATE_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
nField = 1;
|
||||
for( col = cv->col_info; col; col = col->next )
|
||||
{
|
||||
row = -1;
|
||||
r = tv->ops->insert_row( tv, &row );
|
||||
r = MSI_RecordSetInteger( rec, 2, nField );
|
||||
if( r )
|
||||
goto err;
|
||||
|
||||
column_val = msi_addstringW( cv->db->strings, 0, col->column, -1, 1 );
|
||||
TRACE("New string %s -> %d\n", debugstr_w( col->column ), column_val );
|
||||
if( column_val < 0 )
|
||||
break;
|
||||
|
||||
/* add the string again here so we increase the reference count */
|
||||
table_val = msi_addstringW( cv->db->strings, 0, cv->name, -1, 1 );
|
||||
if( table_val < 0 )
|
||||
break;
|
||||
|
||||
r = tv->ops->set_int( tv, row, 1, table_val );
|
||||
r = MSI_RecordSetStringW( rec, 3, col->column );
|
||||
if( r )
|
||||
break;
|
||||
goto err;
|
||||
|
||||
r = tv->ops->set_int( tv, row, 2, 0x8000|nField );
|
||||
r = MSI_RecordSetInteger( rec, 4, col->type );
|
||||
if( r )
|
||||
break;
|
||||
goto err;
|
||||
|
||||
r = tv->ops->set_int( tv, row, 3, column_val );
|
||||
r = tv->ops->insert_row( tv, rec );
|
||||
if( r )
|
||||
break;
|
||||
|
||||
r = tv->ops->set_int( tv, row, 4, 0x8000|col->type );
|
||||
if( r )
|
||||
break;
|
||||
goto err;
|
||||
|
||||
nField++;
|
||||
}
|
||||
|
|
|
@ -82,11 +82,11 @@ static UINT DELETE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT va
|
|||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
static UINT DELETE_insert_row( struct tagMSIVIEW *view, UINT *num )
|
||||
static UINT DELETE_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||
{
|
||||
MSIDELETEVIEW *dv = (MSIDELETEVIEW*)view;
|
||||
|
||||
TRACE("%p %p\n", dv, num );
|
||||
TRACE("%p %p\n", dv, record );
|
||||
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
|
|
@ -109,7 +109,7 @@ err:
|
|||
static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||
{
|
||||
MSIINSERTVIEW *iv = (MSIINSERTVIEW*)view;
|
||||
UINT n, type, val, r, row, col_count = 0;
|
||||
UINT r, col_count = 0;
|
||||
MSIVIEW *sv;
|
||||
MSIRECORD *values = NULL;
|
||||
|
||||
|
@ -136,38 +136,13 @@ static UINT INSERT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
if( !values )
|
||||
goto err;
|
||||
|
||||
row = -1;
|
||||
r = sv->ops->insert_row( sv, &row );
|
||||
TRACE("insert_row returned %x\n", r);
|
||||
if( r )
|
||||
goto err;
|
||||
|
||||
for( n = 1; n <= col_count; n++ )
|
||||
{
|
||||
r = sv->ops->get_column_info( sv, n, NULL, &type );
|
||||
if( r )
|
||||
break;
|
||||
|
||||
if( type & MSITYPE_STRING )
|
||||
{
|
||||
const WCHAR *str = MSI_RecordGetString( values, n );
|
||||
val = msi_addstringW( iv->db->strings, 0, str, -1, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
val = MSI_RecordGetInteger( values, n );
|
||||
val |= 0x8000;
|
||||
}
|
||||
r = sv->ops->set_int( sv, row, n, val );
|
||||
if( r )
|
||||
break;
|
||||
}
|
||||
r = sv->ops->insert_row( sv, values );
|
||||
|
||||
err:
|
||||
if( values )
|
||||
msiobj_release( &values->hdr );
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -129,10 +129,9 @@ typedef struct tagMSIVIEWOPS
|
|||
UINT (*set_int)( struct tagMSIVIEW *, UINT row, UINT col, UINT val );
|
||||
|
||||
/*
|
||||
* Inserts a new, blank row into the database
|
||||
* *row receives the number of the new row
|
||||
* Inserts a new row into the database from the records contents
|
||||
*/
|
||||
UINT (*insert_row)( struct tagMSIVIEW *, UINT *row );
|
||||
UINT (*insert_row)( struct tagMSIVIEW *, MSIRECORD * );
|
||||
|
||||
/*
|
||||
* execute - loads the underlying data into memory so it can be read
|
||||
|
|
|
@ -99,16 +99,16 @@ static UINT SELECT_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT va
|
|||
return sv->table->ops->set_int( sv->table, row, col, val );
|
||||
}
|
||||
|
||||
static UINT SELECT_insert_row( struct tagMSIVIEW *view, UINT *num )
|
||||
static UINT SELECT_insert_row( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||
{
|
||||
MSISELECTVIEW *sv = (MSISELECTVIEW*)view;
|
||||
|
||||
TRACE("%p %p\n", sv, num );
|
||||
TRACE("%p %p\n", sv, record );
|
||||
|
||||
if( !sv->table )
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
|
||||
return sv->table->ops->insert_row( sv->table, num );
|
||||
return sv->table->ops->insert_row( sv->table, record );
|
||||
}
|
||||
|
||||
static UINT SELECT_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
||||
|
|
150
dlls/msi/table.c
150
dlls/msi/table.c
|
@ -1192,7 +1192,7 @@ static UINT TABLE_set_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT val
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT TABLE_insert_row( struct tagMSIVIEW *view, UINT *num )
|
||||
static UINT table_create_new_row( struct tagMSIVIEW *view, UINT *num )
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
USHORT **p, *row;
|
||||
|
@ -1301,11 +1301,155 @@ static UINT TABLE_get_column_info( struct tagMSIVIEW *view,
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT table_find_in_column( MSITABLEVIEW *tv, UINT col, UINT val, UINT *row )
|
||||
{
|
||||
UINT i, r, x;
|
||||
|
||||
for( i=0; i<tv->table->row_count; i++ )
|
||||
{
|
||||
r = TABLE_fetch_int( (struct tagMSIVIEW*) tv, i, col, &x );
|
||||
if ( r != ERROR_SUCCESS )
|
||||
{
|
||||
ERR("TABLE_fetch_int shouldn't fail here\n");
|
||||
break;
|
||||
}
|
||||
if ( x == val )
|
||||
{
|
||||
*row = i;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
return ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
|
||||
static UINT table_validate_new( MSITABLEVIEW *tv, MSIRECORD *rec )
|
||||
{
|
||||
LPCWSTR str;
|
||||
UINT i, val, r, row;
|
||||
|
||||
/* FIXME: set the MsiViewGetError value */
|
||||
|
||||
for( i = 0; i<tv->num_cols; i++ )
|
||||
{
|
||||
/* check for duplicate keys */
|
||||
if( !( tv->columns[i].type & MSITYPE_KEY ) )
|
||||
continue;
|
||||
|
||||
TRACE("column %d (%s.%s)is a key\n", i,
|
||||
debugstr_w(tv->columns[i].tablename),
|
||||
debugstr_w(tv->columns[i].colname) );
|
||||
|
||||
val = 0;
|
||||
if( tv->columns[i].type & MSITYPE_STRING )
|
||||
{
|
||||
/* keys can't be null */
|
||||
str = MSI_RecordGetString( rec, i+1 );
|
||||
if( !str )
|
||||
return ERROR_INVALID_DATA;
|
||||
|
||||
/* if the string doesn't exist in the string table yet, it's OK */
|
||||
r = msi_string2idW( tv->db->strings, str, &val );
|
||||
if( ERROR_SUCCESS != r )
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
val = MSI_RecordGetInteger( rec, i+1 );
|
||||
val ^= 0x8000;
|
||||
}
|
||||
|
||||
/* if we find the same value in the table, it's a duplicate */
|
||||
row = 0;
|
||||
r = table_find_in_column( tv, i+1, val, &row );
|
||||
if( ERROR_SUCCESS == r )
|
||||
{
|
||||
TRACE("found in row %d\n", row );
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT TABLE_insert_row( struct tagMSIVIEW *view, MSIRECORD *rec )
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
UINT n, type, val, r, row, col_count = 0;
|
||||
|
||||
r = TABLE_get_dimensions( view, NULL, &col_count );
|
||||
if( r )
|
||||
return r;
|
||||
|
||||
row = -1;
|
||||
r = table_create_new_row( view, &row );
|
||||
TRACE("insert_row returned %08x\n", r);
|
||||
if( r )
|
||||
return r;
|
||||
|
||||
for( n = 1; n <= col_count; n++ )
|
||||
{
|
||||
r = TABLE_get_column_info( view, n, NULL, &type );
|
||||
if( r )
|
||||
break;
|
||||
|
||||
if( type & MSITYPE_STRING )
|
||||
{
|
||||
const WCHAR *str = MSI_RecordGetString( rec, n );
|
||||
val = msi_addstringW( tv->db->strings, 0, str, -1, 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
val = MSI_RecordGetInteger( rec, n );
|
||||
val ^= 0x8000;
|
||||
}
|
||||
r = TABLE_set_int( view, row, n, val );
|
||||
if( r )
|
||||
break;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT TABLE_modify( struct tagMSIVIEW *view, MSIMODIFY eModifyMode,
|
||||
MSIRECORD *rec)
|
||||
{
|
||||
FIXME("%p %d %p\n", view, eModifyMode, rec );
|
||||
return ERROR_CALL_NOT_IMPLEMENTED;
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
UINT r;
|
||||
|
||||
TRACE("%p %d %p\n", view, eModifyMode, rec );
|
||||
|
||||
switch (eModifyMode)
|
||||
{
|
||||
case MSIMODIFY_VALIDATE_NEW:
|
||||
r = table_validate_new( tv, rec );
|
||||
break;
|
||||
|
||||
case MSIMODIFY_INSERT_TEMPORARY:
|
||||
r = table_validate_new( tv, rec );
|
||||
if (r != ERROR_SUCCESS)
|
||||
break;
|
||||
r = TABLE_insert_row( view, rec );
|
||||
break;
|
||||
|
||||
case MSIMODIFY_REFRESH:
|
||||
case MSIMODIFY_INSERT:
|
||||
case MSIMODIFY_UPDATE:
|
||||
case MSIMODIFY_ASSIGN:
|
||||
case MSIMODIFY_REPLACE:
|
||||
case MSIMODIFY_MERGE:
|
||||
case MSIMODIFY_DELETE:
|
||||
case MSIMODIFY_VALIDATE:
|
||||
case MSIMODIFY_VALIDATE_FIELD:
|
||||
case MSIMODIFY_VALIDATE_DELETE:
|
||||
FIXME("%p %d %p - mode not implemented\n", view, eModifyMode, rec );
|
||||
r = ERROR_CALL_NOT_IMPLEMENTED;
|
||||
break;
|
||||
|
||||
default:
|
||||
r = ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT TABLE_delete( struct tagMSIVIEW *view )
|
||||
|
|
Loading…
Reference in New Issue