From 3b1ab76986afccaff08e9b649b42f27b60dd3e33 Mon Sep 17 00:00:00 2001 From: James Hawkins Date: Wed, 18 Jul 2007 18:21:00 -0700 Subject: [PATCH] msi: Implement reference counting for tables, manipulated with the HOLD and FREE sql commands. --- dlls/msi/alter.c | 23 +++++++++++++++++++---- dlls/msi/create.c | 5 +++-- dlls/msi/delete.c | 4 +++- dlls/msi/distinct.c | 2 ++ dlls/msi/insert.c | 4 +++- dlls/msi/join.c | 4 +++- dlls/msi/msipriv.h | 10 ++++++++++ dlls/msi/order.c | 4 +++- dlls/msi/select.c | 4 +++- dlls/msi/streams.c | 4 +++- dlls/msi/table.c | 35 ++++++++++++++++++++++++++++++++++- dlls/msi/tests/db.c | 7 +------ dlls/msi/update.c | 4 +++- dlls/msi/where.c | 4 +++- 14 files changed, 93 insertions(+), 21 deletions(-) diff --git a/dlls/msi/alter.c b/dlls/msi/alter.c index b506aa1e8cb..2815f115adb 100644 --- a/dlls/msi/alter.c +++ b/dlls/msi/alter.c @@ -38,6 +38,8 @@ typedef struct tagMSIALTERVIEW { MSIVIEW view; MSIDATABASE *db; + MSIVIEW *table; + INT hold; } MSIALTERVIEW; static UINT ALTER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) @@ -62,7 +64,12 @@ static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record ) { MSIALTERVIEW *av = (MSIALTERVIEW*)view; - FIXME("%p %p\n", av, record); + TRACE("%p %p\n", av, record); + + if (av->hold == 1) + av->table->ops->add_ref(av->table); + else if (av->hold == -1) + av->table->ops->release(av->table); return ERROR_SUCCESS; } @@ -111,6 +118,7 @@ static UINT ALTER_delete( struct tagMSIVIEW *view ) TRACE("%p\n", av ); msi_free( av ); + av->table->ops->delete( av->table ); return ERROR_SUCCESS; } @@ -123,7 +131,6 @@ static UINT ALTER_find_matching_rows( struct tagMSIVIEW *view, UINT col, return ERROR_FUNCTION_FAILED; } - static const MSIVIEWOPS alter_ops = { ALTER_fetch_int, @@ -137,22 +144,30 @@ static const MSIVIEWOPS alter_ops = ALTER_get_column_info, ALTER_modify, ALTER_delete, - ALTER_find_matching_rows + ALTER_find_matching_rows, + NULL, + NULL, }; UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, int hold ) { MSIALTERVIEW *av; + UINT r; - TRACE("%p\n", view ); + TRACE("%p %s %d\n", view, debugstr_w(name), hold ); av = msi_alloc_zero( sizeof *av ); if( !av ) return ERROR_FUNCTION_FAILED; + r = TABLE_CreateView( db, name, &av->table ); + if (r != ERROR_SUCCESS || !av->table) + return r; + /* fill the structure */ av->view.ops = &alter_ops; av->db = db; + av->hold = hold; *view = &av->view; diff --git a/dlls/msi/create.c b/dlls/msi/create.c index 9c3fb394e28..65a066ff086 100644 --- a/dlls/msi/create.c +++ b/dlls/msi/create.c @@ -117,7 +117,6 @@ static UINT CREATE_delete( struct tagMSIVIEW *view ) return ERROR_SUCCESS; } - static const MSIVIEWOPS create_ops = { CREATE_fetch_int, @@ -130,7 +129,9 @@ static const MSIVIEWOPS create_ops = CREATE_get_dimensions, CREATE_get_column_info, CREATE_modify, - CREATE_delete + CREATE_delete, + NULL, + NULL, }; static UINT check_columns( column_info *col_info ) diff --git a/dlls/msi/delete.c b/dlls/msi/delete.c index bd33956cccf..8d668c4575f 100644 --- a/dlls/msi/delete.c +++ b/dlls/msi/delete.c @@ -192,7 +192,9 @@ static const MSIVIEWOPS delete_ops = DELETE_get_column_info, DELETE_modify, DELETE_delete, - DELETE_find_matching_rows + DELETE_find_matching_rows, + NULL, + NULL, }; UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) diff --git a/dlls/msi/distinct.c b/dlls/msi/distinct.c index 851382313ba..6d737d9d56b 100644 --- a/dlls/msi/distinct.c +++ b/dlls/msi/distinct.c @@ -282,6 +282,8 @@ static const MSIVIEWOPS distinct_ops = DISTINCT_modify, DISTINCT_delete, DISTINCT_find_matching_rows, + NULL, + NULL, }; UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) diff --git a/dlls/msi/insert.c b/dlls/msi/insert.c index 95c35f38a19..207f1538325 100644 --- a/dlls/msi/insert.c +++ b/dlls/msi/insert.c @@ -232,7 +232,9 @@ static const MSIVIEWOPS insert_ops = INSERT_get_column_info, INSERT_modify, INSERT_delete, - INSERT_find_matching_rows + INSERT_find_matching_rows, + NULL, + NULL, }; static UINT count_column_info( const column_info *ci ) diff --git a/dlls/msi/join.c b/dlls/msi/join.c index ab1935ee2ac..7ff2b91e03e 100644 --- a/dlls/msi/join.c +++ b/dlls/msi/join.c @@ -252,7 +252,9 @@ static const MSIVIEWOPS join_ops = JOIN_get_column_info, JOIN_modify, JOIN_delete, - JOIN_find_matching_rows + JOIN_find_matching_rows, + NULL, + NULL, }; UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h index a94866aef82..39719d5eade 100644 --- a/dlls/msi/msipriv.h +++ b/dlls/msi/msipriv.h @@ -221,6 +221,16 @@ typedef struct tagMSIVIEWOPS * first call and continued to be passed in to subsequent calls. */ UINT (*find_matching_rows)( struct tagMSIVIEW *view, UINT col, UINT val, UINT *row, MSIITERHANDLE *handle ); + + /* + * add_ref - increases the reference count of the table + */ + UINT (*add_ref)( struct tagMSIVIEW *view ); + + /* + * release - decreases the reference count of the table + */ + UINT (*release)( struct tagMSIVIEW *view ); } MSIVIEWOPS; struct tagMSIVIEW diff --git a/dlls/msi/order.c b/dlls/msi/order.c index c0ab643a15f..feb9a31238e 100644 --- a/dlls/msi/order.c +++ b/dlls/msi/order.c @@ -281,7 +281,9 @@ static const MSIVIEWOPS order_ops = ORDER_get_column_info, ORDER_modify, ORDER_delete, - ORDER_find_matching_rows + ORDER_find_matching_rows, + NULL, + NULL, }; static UINT ORDER_AddColumn( MSIORDERVIEW *ov, LPCWSTR name ) diff --git a/dlls/msi/select.c b/dlls/msi/select.c index 6953e1f0fc5..fc2f7be3f86 100644 --- a/dlls/msi/select.c +++ b/dlls/msi/select.c @@ -274,7 +274,9 @@ static const MSIVIEWOPS select_ops = SELECT_get_column_info, SELECT_modify, SELECT_delete, - SELECT_find_matching_rows + SELECT_find_matching_rows, + NULL, + NULL, }; static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name ) diff --git a/dlls/msi/streams.c b/dlls/msi/streams.c index fbb8b793df9..6828277b33f 100644 --- a/dlls/msi/streams.c +++ b/dlls/msi/streams.c @@ -336,7 +336,9 @@ static const MSIVIEWOPS streams_ops = STREAMS_get_column_info, STREAMS_modify, STREAMS_delete, - STREAMS_find_matching_rows + STREAMS_find_matching_rows, + NULL, + NULL, }; static UINT add_streams_to_table(MSISTREAMSVIEW *sv) diff --git a/dlls/msi/table.c b/dlls/msi/table.c index 69a033cda06..33d6aa50561 100644 --- a/dlls/msi/table.c +++ b/dlls/msi/table.c @@ -71,6 +71,7 @@ struct tagMSITABLE MSICOLUMNINFO *colinfo; UINT col_count; BOOL persistent; + INT ref_count; WCHAR name[1]; }; @@ -632,6 +633,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info, if( !table ) return ERROR_FUNCTION_FAILED; + table->ref_count = 1; table->row_count = 0; table->data = NULL; table->nonpersistent_row_count = 0; @@ -1642,6 +1644,35 @@ static UINT TABLE_find_matching_rows( struct tagMSIVIEW *view, UINT col, return ERROR_SUCCESS; } +static UINT TABLE_add_ref(struct tagMSIVIEW *view) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW*)view; + + TRACE("%p %d\n", view, tv->table->ref_count); + + return InterlockedIncrement(&tv->table->ref_count); +} + +static UINT TABLE_release(struct tagMSIVIEW *view) +{ + MSITABLEVIEW *tv = (MSITABLEVIEW*)view; + INT ref = tv->table->ref_count; + + TRACE("%p %d\n", view, ref); + + ref = InterlockedDecrement(&tv->table->ref_count); + if (ref == 0) + { + if (!tv->table->row_count) + { + list_remove(&tv->table->entry); + free_table(tv->table); + TABLE_delete(view); + } + } + + return ref; +} static const MSIVIEWOPS table_ops = { @@ -1656,7 +1687,9 @@ static const MSIVIEWOPS table_ops = TABLE_get_column_info, TABLE_modify, TABLE_delete, - TABLE_find_matching_rows + TABLE_find_matching_rows, + TABLE_add_ref, + TABLE_release, }; UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view ) diff --git a/dlls/msi/tests/db.c b/dlls/msi/tests/db.c index 7d06efb71da..4b54e8a9179 100644 --- a/dlls/msi/tests/db.c +++ b/dlls/msi/tests/db.c @@ -2932,7 +2932,6 @@ static void test_alter(void) r = run_query(hdb, 0, query); ok(r == ERROR_SUCCESS, "failed to free table\n"); - todo_wine { query = "ALTER TABLE `T` FREE"; r = run_query(hdb, 0, query); ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n"); @@ -2940,15 +2939,11 @@ static void test_alter(void) query = "ALTER TABLE `T` HOLD"; r = run_query(hdb, 0, query); ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r); - } /* table T is removed */ query = "SELECT * FROM `T`"; 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); /* create the table again */ query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)"; diff --git a/dlls/msi/update.c b/dlls/msi/update.c index bc3fb2ed15e..037c282bd2e 100644 --- a/dlls/msi/update.c +++ b/dlls/msi/update.c @@ -184,7 +184,9 @@ static const MSIVIEWOPS update_ops = UPDATE_get_column_info, UPDATE_modify, UPDATE_delete, - UPDATE_find_matching_rows + UPDATE_find_matching_rows, + NULL, + NULL, }; UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table, diff --git a/dlls/msi/where.c b/dlls/msi/where.c index ab9c9a6b2f1..5b5d8678b37 100644 --- a/dlls/msi/where.c +++ b/dlls/msi/where.c @@ -446,7 +446,9 @@ static const MSIVIEWOPS where_ops = WHERE_get_column_info, WHERE_modify, WHERE_delete, - WHERE_find_matching_rows + WHERE_find_matching_rows, + NULL, + NULL, }; static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond,