msi: Implement reference counting for tables, manipulated with the HOLD and FREE sql commands.
This commit is contained in:
parent
0169533be8
commit
3b1ab76986
|
@ -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 )
|
||||||
{
|
{
|
||||||
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 )
|
||||||
|
|
||||||
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,
|
||||||
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 =
|
||||||
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 )
|
||||||
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 =
|
||||||
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 =
|
||||||
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 =
|
||||||
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 =
|
||||||
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 =
|
||||||
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
|
||||||
* 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 =
|
||||||
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 =
|
||||||
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 =
|
||||||
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
|
||||||
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,
|
||||||
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,
|
||||||
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 =
|
||||||
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)
|
||||||
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)
|
||||||
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 =
|
||||||
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 =
|
||||||
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,
|
||||||
|
|
Loading…
Reference in New Issue