James Hawkins : msi: Implement reference counting for tables, manipulated with the HOLD and FREE sql commands.

Alexandre Julliard julliard at wine.codeweavers.com
Thu Jul 19 07:59:50 CDT 2007


Module: wine
Branch: master
Commit: 3b1ab76986afccaff08e9b649b42f27b60dd3e33
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=3b1ab76986afccaff08e9b649b42f27b60dd3e33

Author: James Hawkins <truiken at gmail.com>
Date:   Wed Jul 18 18:21:00 2007 -0700

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 b506aa1..2815f11 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 9c3fb39..65a066f 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 bd33956..8d668c4 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 8513823..6d737d9 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 95c35f3..207f153 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 ab1935e..7ff2b91 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 a94866a..39719d5 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 c0ab643..feb9a31 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 6953e1f..fc2f7be 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 fbb8b79..6828277 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 69a033c..33d6aa5 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 7d06efb..4b54e8a 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 bc3fb2e..037c282 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 ab9c9a6..5b5d867 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,




More information about the wine-cvs mailing list