Commit 3b1ab769 authored by James Hawkins's avatar James Hawkins Committed by Alexandre Julliard

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

parent 0169533b
...@@ -38,6 +38,8 @@ typedef struct tagMSIALTERVIEW ...@@ -38,6 +38,8 @@ typedef struct tagMSIALTERVIEW
{ {
MSIVIEW view; MSIVIEW view;
MSIDATABASE *db; MSIDATABASE *db;
MSIVIEW *table;
INT hold;
} MSIALTERVIEW; } MSIALTERVIEW;
static UINT ALTER_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *val ) 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 ) ...@@ -62,7 +64,12 @@ static UINT ALTER_execute( struct tagMSIVIEW *view, MSIRECORD *record )
{ {
MSIALTERVIEW *av = (MSIALTERVIEW*)view; 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; return ERROR_SUCCESS;
} }
...@@ -111,6 +118,7 @@ static UINT ALTER_delete( struct tagMSIVIEW *view ) ...@@ -111,6 +118,7 @@ static UINT ALTER_delete( struct tagMSIVIEW *view )
TRACE("%p\n", av ); TRACE("%p\n", av );
msi_free( av ); msi_free( av );
av->table->ops->delete( av->table );
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
...@@ -123,7 +131,6 @@ static UINT ALTER_find_matching_rows( struct tagMSIVIEW *view, UINT col, ...@@ -123,7 +131,6 @@ static UINT ALTER_find_matching_rows( struct tagMSIVIEW *view, UINT col,
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
} }
static const MSIVIEWOPS alter_ops = static const MSIVIEWOPS alter_ops =
{ {
ALTER_fetch_int, ALTER_fetch_int,
...@@ -137,22 +144,30 @@ static const MSIVIEWOPS alter_ops = ...@@ -137,22 +144,30 @@ static const MSIVIEWOPS alter_ops =
ALTER_get_column_info, ALTER_get_column_info,
ALTER_modify, ALTER_modify,
ALTER_delete, ALTER_delete,
ALTER_find_matching_rows ALTER_find_matching_rows,
NULL,
NULL,
}; };
UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, int hold ) UINT ALTER_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR name, int hold )
{ {
MSIALTERVIEW *av; MSIALTERVIEW *av;
UINT r;
TRACE("%p\n", view ); TRACE("%p %s %d\n", view, debugstr_w(name), hold );
av = msi_alloc_zero( sizeof *av ); av = msi_alloc_zero( sizeof *av );
if( !av ) if( !av )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
r = TABLE_CreateView( db, name, &av->table );
if (r != ERROR_SUCCESS || !av->table)
return r;
/* fill the structure */ /* fill the structure */
av->view.ops = &alter_ops; av->view.ops = &alter_ops;
av->db = db; av->db = db;
av->hold = hold;
*view = &av->view; *view = &av->view;
......
...@@ -117,7 +117,6 @@ static UINT CREATE_delete( struct tagMSIVIEW *view ) ...@@ -117,7 +117,6 @@ static UINT CREATE_delete( struct tagMSIVIEW *view )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static const MSIVIEWOPS create_ops = static const MSIVIEWOPS create_ops =
{ {
CREATE_fetch_int, CREATE_fetch_int,
...@@ -130,7 +129,9 @@ static const MSIVIEWOPS create_ops = ...@@ -130,7 +129,9 @@ static const MSIVIEWOPS create_ops =
CREATE_get_dimensions, CREATE_get_dimensions,
CREATE_get_column_info, CREATE_get_column_info,
CREATE_modify, CREATE_modify,
CREATE_delete CREATE_delete,
NULL,
NULL,
}; };
static UINT check_columns( column_info *col_info ) static UINT check_columns( column_info *col_info )
......
...@@ -192,7 +192,9 @@ static const MSIVIEWOPS delete_ops = ...@@ -192,7 +192,9 @@ static const MSIVIEWOPS delete_ops =
DELETE_get_column_info, DELETE_get_column_info,
DELETE_modify, DELETE_modify,
DELETE_delete, DELETE_delete,
DELETE_find_matching_rows DELETE_find_matching_rows,
NULL,
NULL,
}; };
UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) UINT DELETE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
......
...@@ -282,6 +282,8 @@ static const MSIVIEWOPS distinct_ops = ...@@ -282,6 +282,8 @@ static const MSIVIEWOPS distinct_ops =
DISTINCT_modify, DISTINCT_modify,
DISTINCT_delete, DISTINCT_delete,
DISTINCT_find_matching_rows, DISTINCT_find_matching_rows,
NULL,
NULL,
}; };
UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table )
......
...@@ -232,7 +232,9 @@ static const MSIVIEWOPS insert_ops = ...@@ -232,7 +232,9 @@ static const MSIVIEWOPS insert_ops =
INSERT_get_column_info, INSERT_get_column_info,
INSERT_modify, INSERT_modify,
INSERT_delete, INSERT_delete,
INSERT_find_matching_rows INSERT_find_matching_rows,
NULL,
NULL,
}; };
static UINT count_column_info( const column_info *ci ) static UINT count_column_info( const column_info *ci )
......
...@@ -252,7 +252,9 @@ static const MSIVIEWOPS join_ops = ...@@ -252,7 +252,9 @@ static const MSIVIEWOPS join_ops =
JOIN_get_column_info, JOIN_get_column_info,
JOIN_modify, JOIN_modify,
JOIN_delete, JOIN_delete,
JOIN_find_matching_rows JOIN_find_matching_rows,
NULL,
NULL,
}; };
UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view, UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view,
......
...@@ -221,6 +221,16 @@ typedef struct tagMSIVIEWOPS ...@@ -221,6 +221,16 @@ typedef struct tagMSIVIEWOPS
* first call and continued to be passed in to subsequent calls. * 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 ); 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; } MSIVIEWOPS;
struct tagMSIVIEW struct tagMSIVIEW
......
...@@ -281,7 +281,9 @@ static const MSIVIEWOPS order_ops = ...@@ -281,7 +281,9 @@ static const MSIVIEWOPS order_ops =
ORDER_get_column_info, ORDER_get_column_info,
ORDER_modify, ORDER_modify,
ORDER_delete, ORDER_delete,
ORDER_find_matching_rows ORDER_find_matching_rows,
NULL,
NULL,
}; };
static UINT ORDER_AddColumn( MSIORDERVIEW *ov, LPCWSTR name ) static UINT ORDER_AddColumn( MSIORDERVIEW *ov, LPCWSTR name )
......
...@@ -274,7 +274,9 @@ static const MSIVIEWOPS select_ops = ...@@ -274,7 +274,9 @@ static const MSIVIEWOPS select_ops =
SELECT_get_column_info, SELECT_get_column_info,
SELECT_modify, SELECT_modify,
SELECT_delete, SELECT_delete,
SELECT_find_matching_rows SELECT_find_matching_rows,
NULL,
NULL,
}; };
static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name ) static UINT SELECT_AddColumn( MSISELECTVIEW *sv, LPCWSTR name )
......
...@@ -336,7 +336,9 @@ static const MSIVIEWOPS streams_ops = ...@@ -336,7 +336,9 @@ static const MSIVIEWOPS streams_ops =
STREAMS_get_column_info, STREAMS_get_column_info,
STREAMS_modify, STREAMS_modify,
STREAMS_delete, STREAMS_delete,
STREAMS_find_matching_rows STREAMS_find_matching_rows,
NULL,
NULL,
}; };
static UINT add_streams_to_table(MSISTREAMSVIEW *sv) static UINT add_streams_to_table(MSISTREAMSVIEW *sv)
......
...@@ -71,6 +71,7 @@ struct tagMSITABLE ...@@ -71,6 +71,7 @@ struct tagMSITABLE
MSICOLUMNINFO *colinfo; MSICOLUMNINFO *colinfo;
UINT col_count; UINT col_count;
BOOL persistent; BOOL persistent;
INT ref_count;
WCHAR name[1]; WCHAR name[1];
}; };
...@@ -632,6 +633,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info, ...@@ -632,6 +633,7 @@ UINT msi_create_table( MSIDATABASE *db, LPCWSTR name, column_info *col_info,
if( !table ) if( !table )
return ERROR_FUNCTION_FAILED; return ERROR_FUNCTION_FAILED;
table->ref_count = 1;
table->row_count = 0; table->row_count = 0;
table->data = NULL; table->data = NULL;
table->nonpersistent_row_count = 0; table->nonpersistent_row_count = 0;
...@@ -1642,6 +1644,35 @@ static UINT TABLE_find_matching_rows( struct tagMSIVIEW *view, UINT col, ...@@ -1642,6 +1644,35 @@ static UINT TABLE_find_matching_rows( struct tagMSIVIEW *view, UINT col,
return ERROR_SUCCESS; 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 = static const MSIVIEWOPS table_ops =
{ {
...@@ -1656,7 +1687,9 @@ static const MSIVIEWOPS table_ops = ...@@ -1656,7 +1687,9 @@ static const MSIVIEWOPS table_ops =
TABLE_get_column_info, TABLE_get_column_info,
TABLE_modify, TABLE_modify,
TABLE_delete, TABLE_delete,
TABLE_find_matching_rows TABLE_find_matching_rows,
TABLE_add_ref,
TABLE_release,
}; };
UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view ) UINT TABLE_CreateView( MSIDATABASE *db, LPCWSTR name, MSIVIEW **view )
......
...@@ -2932,7 +2932,6 @@ static void test_alter(void) ...@@ -2932,7 +2932,6 @@ static void test_alter(void)
r = run_query(hdb, 0, query); r = run_query(hdb, 0, query);
ok(r == ERROR_SUCCESS, "failed to free table\n"); ok(r == ERROR_SUCCESS, "failed to free table\n");
todo_wine {
query = "ALTER TABLE `T` FREE"; query = "ALTER TABLE `T` FREE";
r = run_query(hdb, 0, query); r = run_query(hdb, 0, query);
ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n"); ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to free table\n");
...@@ -2940,15 +2939,11 @@ static void test_alter(void) ...@@ -2940,15 +2939,11 @@ static void test_alter(void)
query = "ALTER TABLE `T` HOLD"; query = "ALTER TABLE `T` HOLD";
r = run_query(hdb, 0, query); r = run_query(hdb, 0, query);
ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r); ok(r == ERROR_BAD_QUERY_SYNTAX, "failed to hold table %d\n", r);
}
/* table T is removed */ /* table T is removed */
query = "SELECT * FROM `T`"; query = "SELECT * FROM `T`";
r = run_query(hdb, 0, query); 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 */ /* create the table again */
query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)"; query = "CREATE TABLE `U` ( `A` INTEGER, `B` INTEGER PRIMARY KEY `B`)";
......
...@@ -184,7 +184,9 @@ static const MSIVIEWOPS update_ops = ...@@ -184,7 +184,9 @@ static const MSIVIEWOPS update_ops =
UPDATE_get_column_info, UPDATE_get_column_info,
UPDATE_modify, UPDATE_modify,
UPDATE_delete, UPDATE_delete,
UPDATE_find_matching_rows UPDATE_find_matching_rows,
NULL,
NULL,
}; };
UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table, UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
......
...@@ -446,7 +446,9 @@ static const MSIVIEWOPS where_ops = ...@@ -446,7 +446,9 @@ static const MSIVIEWOPS where_ops =
WHERE_get_column_info, WHERE_get_column_info,
WHERE_modify, WHERE_modify,
WHERE_delete, WHERE_delete,
WHERE_find_matching_rows WHERE_find_matching_rows,
NULL,
NULL,
}; };
static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond, static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr *cond,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment