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
{
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;
......
......@@ -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 )
......
......@@ -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 )
......
......@@ -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 )
......
......@@ -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 )
......
......@@ -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,
......
......@@ -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
......
......@@ -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 )
......
......@@ -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 )
......
......@@ -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)
......
......@@ -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 )
......
......@@ -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`)";
......
......@@ -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,
......
......@@ -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,
......
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