msi 2: Ref count temporary columns and release them when necessary
James Hawkins
truiken at gmail.com
Fri Jul 20 20:41:16 CDT 2007
Hi,
I forgot to mention that the previous patch (msi 1) fixes bug 8895.
http://bugs.winehq.org/show_bug.cgi?id=8895
Changelog:
* Ref count temporary columns and release them when necessary.
dlls/msi/alter.c | 8 +++--
dlls/msi/create.c | 1 +
dlls/msi/delete.c | 1 +
dlls/msi/distinct.c | 1 +
dlls/msi/insert.c | 1 +
dlls/msi/join.c | 1 +
dlls/msi/msipriv.h | 8 ++++-
dlls/msi/order.c | 1 +
dlls/msi/select.c | 1 +
dlls/msi/sql.y | 14 +++++++--
dlls/msi/streams.c | 1 +
dlls/msi/table.c | 81 ++++++++++++++++++++++++++++++++++++++++++++++++++-
dlls/msi/tests/db.c | 35 ++++------------------
dlls/msi/update.c | 1 +
dlls/msi/where.c | 1 +
15 files changed, 119 insertions(+), 37 deletions(-)
--
James Hawkins
-------------- next part --------------
diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c
index 3e8ffbd..734aaba 100644
--- a/dlls/msi/alter.c
+++ b/dlls/msi/alter.c
@@ -127,7 +127,7 @@ static UINT alter_add_column(MSIALTERVIE
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 tagMSI
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,
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 )
diff --git a/dlls/msi/create.c b/dlls/msi/create.c
index f632ef6..8f33ec3 100644
--- a/dlls/msi/create.c
+++ b/dlls/msi/create.c
@@ -133,6 +133,7 @@ static const MSIVIEWOPS create_ops =
NULL,
NULL,
NULL,
+ NULL,
};
static UINT check_columns( column_info *col_info )
diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c
index 81d8a45..7e00484 100644
--- a/dlls/msi/delete.c
+++ b/dlls/msi/delete.c
@@ -196,6 +196,7 @@ static const MSIVIEWOPS delete_ops =
NULL,
NULL,
NULL,
+ NULL,
};
UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c
index 9d8b790..0da3c2e 100644
--- a/dlls/msi/distinct.c
+++ b/dlls/msi/distinct.c
@@ -285,6 +285,7 @@ static const MSIVIEWOPS distinct_ops =
NULL,
NULL,
NULL,
+ NULL,
};
UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c
index e7f3ce1..d122624 100644
--- a/dlls/msi/insert.c
+++ b/dlls/msi/insert.c
@@ -236,6 +236,7 @@ static const MSIVIEWOPS insert_ops =
NULL,
NULL,
NULL,
+ NULL,
};
static UINT count_column_info( const column_info *ci )
diff --git a/dlls/msi/join.c b/dlls/msi/join.c
index 492d0d8..fa31ad3 100644
--- a/dlls/msi/join.c
+++ b/dlls/msi/join.c
@@ -256,6 +256,7 @@ static const MSIVIEWOPS join_ops =
NULL,
NULL,
NULL,
+ NULL,
};
UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view,
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 0dceb75..0036414 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -39,6 +39,7 @@ #define MSITYPE_LOCALIZABLE 0x200
#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
diff --git a/dlls/msi/order.c b/dlls/msi/order.c
index a2a3984..c745be5 100644
--- a/dlls/msi/order.c
+++ b/dlls/msi/order.c
@@ -285,6 +285,7 @@ static const MSIVIEWOPS order_ops =
NULL,
NULL,
NULL,
+ NULL,
};
static UINT ORDER_AddColumn( MSIORDERVIEW *ov, LPCWSTR name )
diff --git a/dlls/msi/select.c b/dlls/msi/select.c
index 6eaffaa..0643f50 100644
--- a/dlls/msi/select.c
+++ b/dlls/msi/select.c
@@ -278,6 +278,7 @@ static const MSIVIEWOPS select_ops =
NULL,
NULL,
NULL,
+ NULL,
};
static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name )
diff --git a/dlls/msi/sql.y b/dlls/msi/sql.y
index 96801f5..f5e1cf9 100644
--- a/dlls/msi/sql.y
+++ b/dlls/msi/sql.y
@@ -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;
}
;
diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c
index f17fb98..229a34f 100644
--- a/dlls/msi/streams.c
+++ b/dlls/msi/streams.c
@@ -340,6 +340,7 @@ static const MSIVIEWOPS streams_ops =
NULL,
NULL,
NULL,
+ NULL,
};
static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
diff --git a/dlls/msi/table.c b/dlls/msi/table.c
index 1dba764..d442916 100644
--- a/dlls/msi/table.c
+++ b/dlls/msi/table.c
@@ -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,
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( MSIDATABAS
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( st
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 tagMSIV
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 tagM
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 )
diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c
index 317425a..58c3f22 100755
--- a/dlls/msi/tests/db.c
+++ b/dlls/msi/tests/db.c
@@ -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";
diff --git a/dlls/msi/update.c b/dlls/msi/update.c
index feb12a9..10f7762 100644
--- a/dlls/msi/update.c
+++ b/dlls/msi/update.c
@@ -188,6 +188,7 @@ static const MSIVIEWOPS update_ops =
NULL,
NULL,
NULL,
+ NULL,
};
UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
diff --git a/dlls/msi/where.c b/dlls/msi/where.c
index fee7a30..fddb0e7 100644
--- a/dlls/msi/where.c
+++ b/dlls/msi/where.c
@@ -450,6 +450,7 @@ static const MSIVIEWOPS where_ops =
NULL,
NULL,
NULL,
+ NULL,
};
static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond,
--
1.4.1
More information about the wine-patches
mailing list