msi: Ref count temporary columns and release them when necessary.
This commit is contained in:
parent
0fd733bf90
commit
ccef56f2cc
|
@ -127,7 +127,7 @@ static UINT alter_add_column(MSIALTERVIEW *av)
|
|||
|
||||
r = columns->ops->add_column(columns, av->colinfo->table,
|
||||
colnum, av->colinfo->column,
|
||||
av->colinfo->type);
|
||||
av->colinfo->type, (av->hold == 1));
|
||||
|
||||
msiobj_release(&columns->hdr);
|
||||
return r;
|
||||
|
@ -143,7 +143,8 @@ static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record )
|
|||
av->table->ops->add_ref(av->table);
|
||||
else if (av->hold == -1)
|
||||
av->table->ops->release(av->table);
|
||||
else
|
||||
|
||||
if (av->colinfo)
|
||||
return alter_add_column(av);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
@ -223,6 +224,7 @@ static const MSIVIEWOPS alter_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, column_info *colinfo, int hold )
|
||||
|
@ -230,7 +232,7 @@ UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, column_inf
|
|||
MSIALTERVIEW *av;
|
||||
UINT r;
|
||||
|
||||
TRACE("%p %s %d\n", view, debugstr_w(name), hold );
|
||||
TRACE("%p %p %s %d\n", view, colinfo, debugstr_w(name), hold );
|
||||
|
||||
av = msi_alloc_zero( sizeof *av );
|
||||
if( !av )
|
||||
|
|
|
@ -133,6 +133,7 @@ static const MSIVIEWOPS create_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static UINT check_columns( column_info *col_info )
|
||||
|
|
|
@ -196,6 +196,7 @@ static const MSIVIEWOPS delete_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
|
||||
|
|
|
@ -285,6 +285,7 @@ static const MSIVIEWOPS distinct_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
|
||||
|
|
|
@ -236,6 +236,7 @@ static const MSIVIEWOPS insert_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static UINT count_column_info( const column_info *ci )
|
||||
|
|
|
@ -256,6 +256,7 @@ static const MSIVIEWOPS join_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view,
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#define MSITYPE_STRING 0x0800
|
||||
#define MSITYPE_NULLABLE 0x1000
|
||||
#define MSITYPE_KEY 0x2000
|
||||
#define MSITYPE_TEMPORARY 0x4000
|
||||
|
||||
/* Word Count masks */
|
||||
#define MSIWORDCOUNT_SHORTFILENAMES 0x0001
|
||||
|
@ -235,7 +236,12 @@ typedef struct tagMSIVIEWOPS
|
|||
/*
|
||||
* add_column - adds a column to the table
|
||||
*/
|
||||
UINT (*add_column)( struct tagMSIVIEW *view, LPCWSTR table, UINT number, LPCWSTR column, UINT type );
|
||||
UINT (*add_column)( struct tagMSIVIEW *view, LPCWSTR table, UINT number, LPCWSTR column, UINT type, BOOL hold );
|
||||
|
||||
/*
|
||||
* remove_column - removes the column represented by table name and column number from the table
|
||||
*/
|
||||
UINT (*remove_column)( struct tagMSIVIEW *view, LPCWSTR table, UINT number );
|
||||
} MSIVIEWOPS;
|
||||
|
||||
struct tagMSIVIEW
|
||||
|
|
|
@ -285,6 +285,7 @@ static const MSIVIEWOPS order_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static UINT ORDER_AddColumn( MSIORDERVIEW *ov, LPCWSTR name )
|
||||
|
|
|
@ -278,6 +278,7 @@ static const MSIVIEWOPS select_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name )
|
||||
|
|
|
@ -40,8 +40,6 @@ static int sql_error(const char *str);
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(msi);
|
||||
|
||||
#define MSITYPE_TEMPORARY 0x8000
|
||||
|
||||
typedef struct tag_SQL_input
|
||||
{
|
||||
MSIDATABASE *db;
|
||||
|
@ -246,6 +244,16 @@ onealter:
|
|||
YYABORT;
|
||||
$$ = alter;
|
||||
}
|
||||
| TK_ALTER TK_TABLE table TK_ADD column_and_type TK_HOLD
|
||||
{
|
||||
SQL_input *sql = (SQL_input *)info;
|
||||
MSIVIEW *alter = NULL;
|
||||
|
||||
ALTER_CreateView( sql->db, &alter, $3, $5, 1 );
|
||||
if (!alter)
|
||||
YYABORT;
|
||||
$$ = alter;
|
||||
}
|
||||
;
|
||||
|
||||
alterop:
|
||||
|
@ -290,7 +298,7 @@ column_and_type:
|
|||
column column_type
|
||||
{
|
||||
$$ = $1;
|
||||
$$->type = ($2 | MSITYPE_VALID) & ~MSITYPE_TEMPORARY;
|
||||
$$->type = ($2 | MSITYPE_VALID);
|
||||
$$->temporary = $2 & MSITYPE_TEMPORARY ? TRUE : FALSE;
|
||||
}
|
||||
;
|
||||
|
|
|
@ -340,6 +340,7 @@ static const MSIVIEWOPS streams_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
|
||||
|
|
|
@ -58,6 +58,7 @@ typedef struct tagMSICOLUMNINFO
|
|||
LPCWSTR colname;
|
||||
UINT type;
|
||||
UINT offset;
|
||||
INT ref_count;
|
||||
MSICOLUMNHASHENTRY **hash_table;
|
||||
} MSICOLUMNINFO;
|
||||
|
||||
|
@ -660,6 +661,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
|
|||
table->colinfo[ i ].colname = strdupW( col->column );
|
||||
table->colinfo[ i ].type = col->type;
|
||||
table->colinfo[ i ].offset = 0;
|
||||
table->colinfo[ i ].ref_count = 0;
|
||||
table->colinfo[ i ].hash_table = NULL;
|
||||
}
|
||||
table_calc_column_offsets( table->colinfo, table->col_count);
|
||||
|
@ -1015,6 +1017,7 @@ static UINT get_tablecolumns( MSIDATABASE *db,
|
|||
colinfo[ col - 1 ].colname = msi_makestring( db, id );
|
||||
colinfo[ col - 1 ].type = read_table_int(table->data, i, _Columns_cols[3].offset, sizeof(USHORT)) - (1<<15);
|
||||
colinfo[ col - 1 ].offset = 0;
|
||||
colinfo[ col - 1 ].ref_count = 0;
|
||||
colinfo[ col - 1 ].hash_table = NULL;
|
||||
}
|
||||
n++;
|
||||
|
@ -1667,19 +1670,77 @@ static UINT TABLE_find_matching_rows( struct tagMSIVIEW *view, UINT col,
|
|||
static UINT TABLE_add_ref(struct tagMSIVIEW *view)
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
int i;
|
||||
|
||||
TRACE("%p %d\n", view, tv->table->ref_count);
|
||||
|
||||
for (i = 0; i < tv->table->col_count; i++)
|
||||
{
|
||||
if (tv->table->colinfo[i].type & MSITYPE_TEMPORARY)
|
||||
InterlockedIncrement(&tv->table->colinfo[i].ref_count);
|
||||
}
|
||||
|
||||
return InterlockedIncrement(&tv->table->ref_count);
|
||||
}
|
||||
|
||||
static UINT TABLE_remove_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number)
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
MSIRECORD *rec;
|
||||
MSIVIEW *columns = NULL;
|
||||
UINT row, r;
|
||||
|
||||
rec = MSI_CreateRecord(2);
|
||||
if (!rec)
|
||||
return ERROR_OUTOFMEMORY;
|
||||
|
||||
MSI_RecordSetStringW(rec, 1, table);
|
||||
MSI_RecordSetInteger(rec, 2, number);
|
||||
|
||||
r = TABLE_CreateView(tv->db, szColumns, &columns);
|
||||
if (r != ERROR_SUCCESS)
|
||||
return r;
|
||||
|
||||
r = msi_table_find_row((MSITABLEVIEW *)columns, rec, &row);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
r = TABLE_delete_row(columns, row);
|
||||
if (r != ERROR_SUCCESS)
|
||||
goto done;
|
||||
|
||||
msi_update_table_columns(tv->db, table);
|
||||
|
||||
done:
|
||||
msiobj_release(&rec->hdr);
|
||||
if (columns) msiobj_release(&columns->hdr);
|
||||
return r;
|
||||
}
|
||||
|
||||
static UINT TABLE_release(struct tagMSIVIEW *view)
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
INT ref = tv->table->ref_count;
|
||||
int i;
|
||||
UINT r;
|
||||
|
||||
TRACE("%p %d\n", view, ref);
|
||||
|
||||
for (i = 0; i < tv->table->col_count; i++)
|
||||
{
|
||||
if (tv->table->colinfo[i].type & MSITYPE_TEMPORARY)
|
||||
{
|
||||
ref = InterlockedDecrement(&tv->table->colinfo[i].ref_count);
|
||||
if (ref == 0)
|
||||
{
|
||||
r = TABLE_remove_column(view, tv->table->colinfo[i].tablename,
|
||||
tv->table->colinfo[i].number);
|
||||
if (r != ERROR_SUCCESS)
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ref = InterlockedDecrement(&tv->table->ref_count);
|
||||
if (ref == 0)
|
||||
{
|
||||
|
@ -1694,11 +1755,13 @@ static UINT TABLE_release(struct tagMSIVIEW *view)
|
|||
return ref;
|
||||
}
|
||||
|
||||
static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number, LPCWSTR column, UINT type)
|
||||
static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number,
|
||||
LPCWSTR column, UINT type, BOOL hold)
|
||||
{
|
||||
MSITABLEVIEW *tv = (MSITABLEVIEW*)view;
|
||||
MSITABLE *msitable;
|
||||
MSIRECORD *rec;
|
||||
UINT r;
|
||||
UINT r, i;
|
||||
|
||||
rec = MSI_CreateRecord(4);
|
||||
if (!rec)
|
||||
|
@ -1715,6 +1778,19 @@ static UINT TABLE_add_column(struct tagMSIVIEW *view, LPCWSTR table, UINT number
|
|||
|
||||
msi_update_table_columns(tv->db, table);
|
||||
|
||||
if (!hold)
|
||||
goto done;
|
||||
|
||||
msitable = find_cached_table(tv->db, table);
|
||||
for (i = 0; i < msitable->col_count; i++)
|
||||
{
|
||||
if (!lstrcmpW(msitable->colinfo[i].colname, column))
|
||||
{
|
||||
InterlockedIncrement(&msitable->colinfo[i].ref_count);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
msiobj_release(&rec->hdr);
|
||||
return r;
|
||||
|
@ -1737,6 +1813,7 @@ static const MSIVIEWOPS table_ops =
|
|||
TABLE_add_ref,
|
||||
TABLE_release,
|
||||
TABLE_add_column,
|
||||
TABLE_remove_column,
|
||||
};
|
||||
|
||||
UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
|
||||
|
|
|
@ -3010,25 +3010,16 @@ static void test_alter(void)
|
|||
/* column D is removed */
|
||||
query = "SELECT * FROM `U` WHERE `D` = 8";
|
||||
r = run_query(hdb, 0, query);
|
||||
todo_wine
|
||||
{
|
||||
ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
|
||||
}
|
||||
ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
|
||||
|
||||
query = "INSERT INTO `U` ( `A`, `B`, `C`, `D` ) VALUES ( 9, 10, 11, 12 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
todo_wine
|
||||
{
|
||||
ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
|
||||
}
|
||||
ok(r == ERROR_BAD_QUERY_SYNTAX, "Expected ERROR_BAD_QUERY_SYNTAX, got %d\n", r);
|
||||
|
||||
/* add the column again */
|
||||
query = "ALTER TABLE `U` ADD `E` INTEGER TEMPORARY HOLD";
|
||||
r = run_query(hdb, 0, query);
|
||||
todo_wine
|
||||
{
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
}
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
/* up the ref count */
|
||||
query = "ALTER TABLE `U` HOLD";
|
||||
|
@ -3037,17 +3028,11 @@ static void test_alter(void)
|
|||
|
||||
query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 13, 14, 15, 16 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
todo_wine
|
||||
{
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
}
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "SELECT * FROM `U` WHERE `E` = 16";
|
||||
r = run_query(hdb, 0, query);
|
||||
todo_wine
|
||||
{
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
}
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
/* drop the ref count */
|
||||
query = "ALTER TABLE `U` FREE";
|
||||
|
@ -3056,17 +3041,11 @@ static void test_alter(void)
|
|||
|
||||
query = "INSERT INTO `U` ( `A`, `B`, `C`, `E` ) VALUES ( 17, 18, 19, 20 )";
|
||||
r = run_query(hdb, 0, query);
|
||||
todo_wine
|
||||
{
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
}
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
query = "SELECT * FROM `U` WHERE `E` = 20";
|
||||
r = run_query(hdb, 0, query);
|
||||
todo_wine
|
||||
{
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
}
|
||||
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %d\n", r);
|
||||
|
||||
/* drop the ref count */
|
||||
query = "ALTER TABLE `U` FREE";
|
||||
|
|
|
@ -188,6 +188,7 @@ static const MSIVIEWOPS update_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
|
||||
|
|
|
@ -450,6 +450,7 @@ static const MSIVIEWOPS where_ops =
|
|||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond,
|
||||
|
|
Loading…
Reference in New Issue