Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
62c544cf
Commit
62c544cf
authored
Oct 02, 2008
by
James Hawkins
Committed by
Alexandre Julliard
Oct 06, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Implement the DROP TABLE sql command.
parent
68525652
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
306 additions
and
13 deletions
+306
-13
Makefile.in
dlls/msi/Makefile.in
+1
-0
alter.c
dlls/msi/alter.c
+1
-0
create.c
dlls/msi/create.c
+7
-1
delete.c
dlls/msi/delete.c
+2
-1
distinct.c
dlls/msi/distinct.c
+1
-0
drop.c
dlls/msi/drop.c
+125
-0
insert.c
dlls/msi/insert.c
+1
-0
join.c
dlls/msi/join.c
+1
-0
msipriv.h
dlls/msi/msipriv.h
+5
-0
query.h
dlls/msi/query.h
+2
-0
select.c
dlls/msi/select.c
+1
-0
sql.y
dlls/msi/sql.y
+16
-2
storages.c
dlls/msi/storages.c
+1
-0
streams.c
dlls/msi/streams.c
+1
-0
table.c
dlls/msi/table.c
+48
-9
db.c
dlls/msi/tests/db.c
+89
-0
tokenize.c
dlls/msi/tokenize.c
+2
-0
update.c
dlls/msi/update.c
+1
-0
where.c
dlls/msi/where.c
+1
-0
No files found.
dlls/msi/Makefile.in
View file @
62c544cf
...
...
@@ -19,6 +19,7 @@ C_SRCS = \
delete.c
\
dialog.c
\
distinct.c
\
drop.c
\
events.c
\
files.c
\
font.c
\
...
...
dlls/msi/alter.c
View file @
62c544cf
...
...
@@ -242,6 +242,7 @@ static const MSIVIEWOPS alter_ops =
NULL
,
NULL
,
NULL
,
NULL
,
};
UINT
ALTER_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
name
,
column_info
*
colinfo
,
int
hold
)
...
...
dlls/msi/create.c
View file @
62c544cf
...
...
@@ -137,6 +137,7 @@ static const MSIVIEWOPS create_ops =
NULL
,
NULL
,
NULL
,
NULL
,
};
static
UINT
check_columns
(
column_info
*
col_info
)
...
...
@@ -157,7 +158,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
{
MSICREATEVIEW
*
cv
=
NULL
;
UINT
r
;
co
nst
co
lumn_info
*
col
;
column_info
*
col
;
BOOL
temp
=
TRUE
;
TRACE
(
"%p
\n
"
,
cv
);
...
...
@@ -171,11 +172,16 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPWSTR table,
return
ERROR_FUNCTION_FAILED
;
for
(
col
=
col_info
;
col
;
col
=
col
->
next
)
{
if
(
!
col
->
table
)
col
->
table
=
strdupW
(
table
);
if
(
!
col
->
temporary
)
{
temp
=
FALSE
;
break
;
}
}
/* fill the structure */
cv
->
view
.
ops
=
&
create_ops
;
...
...
dlls/msi/delete.c
View file @
62c544cf
...
...
@@ -191,7 +191,8 @@ static const MSIVIEWOPS delete_ops =
NULL
,
NULL
,
NULL
,
NULL
NULL
,
NULL
,
};
UINT
DELETE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
MSIVIEW
*
table
)
...
...
dlls/msi/distinct.c
View file @
62c544cf
...
...
@@ -296,6 +296,7 @@ static const MSIVIEWOPS distinct_ops =
NULL
,
NULL
,
DISTINCT_sort
,
NULL
,
};
UINT
DISTINCT_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
MSIVIEW
*
table
)
...
...
dlls/msi/drop.c
0 → 100644
View file @
62c544cf
/*
* Implementation of the Microsoft Installer (msi.dll)
*
* Copyright 2008 James Hawkins
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "wine/debug.h"
#include "msi.h"
#include "msiquery.h"
#include "objbase.h"
#include "objidl.h"
#include "msipriv.h"
#include "query.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
msidb
);
typedef
struct
tagMSIDROPVIEW
{
MSIVIEW
view
;
MSIDATABASE
*
db
;
MSIVIEW
*
table
;
column_info
*
colinfo
;
INT
hold
;
}
MSIDROPVIEW
;
static
UINT
DROP_execute
(
struct
tagMSIVIEW
*
view
,
MSIRECORD
*
record
)
{
MSIDROPVIEW
*
dv
=
(
MSIDROPVIEW
*
)
view
;
UINT
r
;
TRACE
(
"%p %p
\n
"
,
dv
,
record
);
if
(
!
dv
->
table
)
return
ERROR_FUNCTION_FAILED
;
r
=
dv
->
table
->
ops
->
execute
(
dv
->
table
,
record
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
return
dv
->
table
->
ops
->
drop
(
dv
->
table
);
}
static
UINT
DROP_close
(
struct
tagMSIVIEW
*
view
)
{
MSIDROPVIEW
*
dv
=
(
MSIDROPVIEW
*
)
view
;
TRACE
(
"%p
\n
"
,
dv
);
return
ERROR_SUCCESS
;
}
static
UINT
DROP_get_dimensions
(
struct
tagMSIVIEW
*
view
,
UINT
*
rows
,
UINT
*
cols
)
{
MSIDROPVIEW
*
dv
=
(
MSIDROPVIEW
*
)
view
;
TRACE
(
"%p %p %p
\n
"
,
dv
,
rows
,
cols
);
return
ERROR_FUNCTION_FAILED
;
}
static
const
MSIVIEWOPS
drop_ops
=
{
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
DROP_execute
,
DROP_close
,
DROP_get_dimensions
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
NULL
,
};
UINT
DROP_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
name
)
{
MSIDROPVIEW
*
dv
;
UINT
r
;
TRACE
(
"%p %s
\n
"
,
view
,
debugstr_w
(
name
));
dv
=
msi_alloc_zero
(
sizeof
*
dv
);
if
(
!
dv
)
return
ERROR_FUNCTION_FAILED
;
r
=
TABLE_CreateView
(
db
,
name
,
&
dv
->
table
);
if
(
r
!=
ERROR_SUCCESS
||
!
dv
->
table
)
return
r
;
dv
->
view
.
ops
=
&
drop_ops
;
dv
->
db
=
db
;
*
view
=
(
MSIVIEW
*
)
dv
;
return
ERROR_SUCCESS
;
}
dlls/msi/insert.c
View file @
62c544cf
...
...
@@ -239,6 +239,7 @@ static const MSIVIEWOPS insert_ops =
NULL
,
NULL
,
NULL
,
NULL
,
};
static
UINT
count_column_info
(
const
column_info
*
ci
)
...
...
dlls/msi/join.c
View file @
62c544cf
...
...
@@ -306,6 +306,7 @@ static const MSIVIEWOPS join_ops =
NULL
,
NULL
,
JOIN_sort
,
NULL
,
};
UINT
JOIN_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPWSTR
tables
)
...
...
dlls/msi/msipriv.h
View file @
62c544cf
...
...
@@ -274,6 +274,11 @@ typedef struct tagMSIVIEWOPS
* sort - orders the table by columns
*/
UINT
(
*
sort
)(
struct
tagMSIVIEW
*
view
,
column_info
*
columns
);
/*
* drop - drops the table from the database
*/
UINT
(
*
drop
)(
struct
tagMSIVIEW
*
view
);
}
MSIVIEWOPS
;
struct
tagMSIVIEW
...
...
dlls/msi/query.h
View file @
62c544cf
...
...
@@ -117,6 +117,8 @@ UINT STREAMS_CreateView( MSIDATABASE *db, MSIVIEW **view );
UINT
STORAGES_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
);
UINT
DROP_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
name
);
int
sqliteGetToken
(
const
WCHAR
*
z
,
int
*
tokenType
);
MSIRECORD
*
msi_query_merge_record
(
UINT
fields
,
const
column_info
*
vl
,
MSIRECORD
*
rec
);
...
...
dlls/msi/select.c
View file @
62c544cf
...
...
@@ -363,6 +363,7 @@ static const MSIVIEWOPS select_ops =
NULL
,
NULL
,
SELECT_sort
,
NULL
,
};
static
UINT
SELECT_AddColumn
(
MSISELECTVIEW
*
sv
,
LPCWSTR
name
)
...
...
dlls/msi/sql.y
View file @
62c544cf
...
...
@@ -81,7 +81,7 @@ static struct expr * EXPR_wildcard( void *info );
int integer;
}
%token TK_ALTER TK_AND TK_BY TK_CHAR TK_COMMA TK_CREATE TK_DELETE
%token TK_ALTER TK_AND TK_BY TK_CHAR TK_COMMA TK_CREATE TK_DELETE
TK_DROP
%token TK_DISTINCT TK_DOT TK_EQ TK_FREE TK_FROM TK_GE TK_GT TK_HOLD TK_ADD
%token <str> TK_ID
%token TK_ILLEGAL TK_INSERT TK_INT
...
...
@@ -106,7 +106,7 @@ static struct expr * EXPR_wildcard( void *info );
%type <column_list> selcollist column column_and_type column_def table_def
%type <column_list> column_assignment update_assign_list constlist
%type <query> query from fromtable selectfrom unorderedsel
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter
onedrop
%type <expr> expr val column_val const_val
%type <column_type> column_type data_type data_type_l data_count
%type <integer> number alterop
...
...
@@ -135,6 +135,7 @@ onequery:
| oneupdate
| onedelete
| onealter
| onedrop
;
oneinsert:
...
...
@@ -267,6 +268,19 @@ alterop:
}
;
onedrop:
TK_DROP TK_TABLE table
{
SQL_input* sql = (SQL_input*) info;
UINT r;
$$ = NULL;
r = DROP_CreateView( sql->db, &$$, $3 );
if( r != ERROR_SUCCESS || !$$ )
YYABORT;
}
;
table_def:
column_def TK_PRIMARY TK_KEY selcollist
{
...
...
dlls/msi/storages.c
View file @
62c544cf
...
...
@@ -474,6 +474,7 @@ static const MSIVIEWOPS storages_ops =
NULL
,
NULL
,
NULL
,
NULL
,
};
static
INT
add_storages_to_table
(
MSISTORAGESVIEW
*
sv
)
...
...
dlls/msi/streams.c
View file @
62c544cf
...
...
@@ -438,6 +438,7 @@ static const MSIVIEWOPS streams_ops =
NULL
,
NULL
,
NULL
,
NULL
,
};
static
INT
add_streams_to_table
(
MSISTREAMSVIEW
*
sv
)
...
...
dlls/msi/table.c
View file @
62c544cf
...
...
@@ -109,7 +109,7 @@ static const MSICOLUMNINFO _Columns_cols[4] = {
};
static
const
MSICOLUMNINFO
_Tables_cols
[
1
]
=
{
{
szTables
,
1
,
szName
,
MSITYPE_VALID
|
MSITYPE_STRING
|
64
,
0
,
0
,
NULL
},
{
szTables
,
1
,
szName
,
MSITYPE_VALID
|
MSITYPE_STRING
|
MSITYPE_KEY
|
64
,
0
,
0
,
NULL
},
};
#define MAX_STREAM_NAME 0x1f
...
...
@@ -1073,21 +1073,13 @@ BOOL TABLE_Exists( MSIDATABASE *db, LPCWSTR name )
count
=
table
->
row_count
;
for
(
i
=
0
;
i
<
count
;
i
++
)
if
(
table
->
data
[
i
][
0
]
==
table_id
)
break
;
if
(
i
!=
count
)
return
TRUE
;
count
=
table
->
nonpersistent_row_count
;
for
(
i
=
0
;
i
<
count
;
i
++
)
if
(
table
->
nonpersistent_data
[
i
][
0
]
==
table_id
)
break
;
if
(
i
!=
count
)
return
TRUE
;
TRACE
(
"Searched %d tables, but %d was not found
\n
"
,
count
,
table_id
);
return
FALSE
;
}
...
...
@@ -2058,6 +2050,52 @@ static UINT TABLE_sort(struct tagMSIVIEW *view, column_info *columns)
return
ERROR_SUCCESS
;
}
static
UINT
TABLE_drop
(
struct
tagMSIVIEW
*
view
)
{
MSITABLEVIEW
*
tv
=
(
MSITABLEVIEW
*
)
view
;
MSIVIEW
*
tables
=
NULL
;
MSIRECORD
*
rec
=
NULL
;
UINT
i
,
r
,
row
;
TRACE
(
"dropping table %s
\n
"
,
debugstr_w
(
tv
->
name
));
for
(
i
=
0
;
i
<
tv
->
table
->
col_count
;
i
++
)
{
r
=
TABLE_remove_column
(
view
,
tv
->
table
->
colinfo
[
i
].
tablename
,
tv
->
table
->
colinfo
[
i
].
number
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
}
rec
=
MSI_CreateRecord
(
1
);
if
(
!
rec
)
return
ERROR_OUTOFMEMORY
;
MSI_RecordSetStringW
(
rec
,
1
,
tv
->
name
);
r
=
TABLE_CreateView
(
tv
->
db
,
szTables
,
&
tables
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
msi_table_find_row
((
MSITABLEVIEW
*
)
tables
,
rec
,
&
row
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
r
=
TABLE_delete_row
(
tables
,
row
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
list_remove
(
&
tv
->
table
->
entry
);
free_table
(
tv
->
table
);
TABLE_delete
(
view
);
done:
msiobj_release
(
&
rec
->
hdr
);
tables
->
ops
->
delete
(
tables
);
return
r
;
}
static
const
MSIVIEWOPS
table_ops
=
{
TABLE_fetch_int
,
...
...
@@ -2078,6 +2116,7 @@ static const MSIVIEWOPS table_ops =
TABLE_add_column
,
TABLE_remove_column
,
TABLE_sort
,
TABLE_drop
,
};
UINT
TABLE_CreateView
(
MSIDATABASE
*
db
,
LPCWSTR
name
,
MSIVIEW
**
view
)
...
...
dlls/msi/tests/db.c
View file @
62c544cf
...
...
@@ -6313,6 +6313,94 @@ static void test_dbtopackage(void)
DeleteFileA
(
msifile
);
}
static
void
test_droptable
(
void
)
{
MSIHANDLE
hdb
,
hview
,
hrec
;
LPCSTR
query
;
UINT
r
;
r
=
MsiOpenDatabase
(
msifile
,
MSIDBOPEN_CREATE
,
&
hdb
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `One`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"Expected ERROR_NO_MORE_ITEMS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `_Tables` WHERE `Name` = 'One'"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
MsiCloseHandle
(
hrec
);
query
=
"SELECT * FROM `_Columns` WHERE `Table` = 'One'"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
MsiCloseHandle
(
hrec
);
query
=
"DROP `One`"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, got %d
\n
"
,
r
);
query
=
"DROP TABLE"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, got %d
\n
"
,
r
);
query
=
"DROP TABLE `One`"
;
hview
=
0
;
r
=
MsiDatabaseOpenViewA
(
hdb
,
query
,
&
hview
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiViewExecute
(
hview
,
0
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiViewFetch
(
hview
,
&
hrec
);
ok
(
r
==
ERROR_FUNCTION_FAILED
,
"Expected ERROR_FUNCTION_FAILED, got %d
\n
"
,
r
);
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
query
=
"SELECT * FROM `IDontExist`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `One`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"DROP TABLE One"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `One`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `_Tables` WHERE `Name` = 'One'"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"Expected ERROR_NO_MORE_ITEMS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `_Columns` WHERE `Table` = 'One'"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"Expected ERROR_NO_MORE_ITEMS, got %d
\n
"
,
r
);
MsiCloseHandle
(
hdb
);
DeleteFileA
(
msifile
);
}
START_TEST
(
db
)
{
test_msidatabase
();
...
...
@@ -6352,4 +6440,5 @@ START_TEST(db)
test_where_viewmodify
();
test_storages_table
();
test_dbtopackage
();
test_droptable
();
}
dlls/msi/tokenize.c
View file @
62c544cf
...
...
@@ -47,6 +47,7 @@ static const WCHAR CHARACTER_W[] = { 'C','H','A','R','A','C','T','E','R',0 };
static
const
WCHAR
CREATE_W
[]
=
{
'C'
,
'R'
,
'E'
,
'A'
,
'T'
,
'E'
,
0
};
static
const
WCHAR
DELETE_W
[]
=
{
'D'
,
'E'
,
'L'
,
'E'
,
'T'
,
'E'
,
0
};
static
const
WCHAR
DISTINCT_W
[]
=
{
'D'
,
'I'
,
'S'
,
'T'
,
'I'
,
'N'
,
'C'
,
'T'
,
0
};
static
const
WCHAR
DROP_W
[]
=
{
'D'
,
'R'
,
'O'
,
'P'
,
0
};
static
const
WCHAR
FREE_W
[]
=
{
'F'
,
'R'
,
'E'
,
'E'
,
0
};
static
const
WCHAR
FROM_W
[]
=
{
'F'
,
'R'
,
'O'
,
'M'
,
0
};
static
const
WCHAR
HOLD_W
[]
=
{
'H'
,
'O'
,
'L'
,
'D'
,
0
};
...
...
@@ -89,6 +90,7 @@ static const Keyword aKeywordTable[] = {
{
CREATE_W
,
TK_CREATE
},
{
DELETE_W
,
TK_DELETE
},
{
DISTINCT_W
,
TK_DISTINCT
},
{
DROP_W
,
TK_DROP
},
{
FREE_W
,
TK_FREE
},
{
FROM_W
,
TK_FROM
},
{
HOLD_W
,
TK_HOLD
},
...
...
dlls/msi/update.c
View file @
62c544cf
...
...
@@ -222,6 +222,7 @@ static const MSIVIEWOPS update_ops =
NULL
,
NULL
,
NULL
,
NULL
,
};
UINT
UPDATE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
table
,
...
...
dlls/msi/where.c
View file @
62c544cf
...
...
@@ -585,6 +585,7 @@ static const MSIVIEWOPS where_ops =
NULL
,
NULL
,
WHERE_sort
,
NULL
,
};
static
UINT
WHERE_VerifyCondition
(
MSIDATABASE
*
db
,
MSIVIEW
*
table
,
struct
expr
*
cond
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment