Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
a52c2bf9
Commit
a52c2bf9
authored
Aug 26, 2011
by
Bernhard Loos
Committed by
Alexandre Julliard
Aug 26, 2011
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Make WHEREVIEW able to deal directly with multiple tables.
parent
9b79fd57
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
478 additions
and
211 deletions
+478
-211
query.h
dlls/msi/query.h
+15
-7
sql.y
dlls/msi/sql.y
+4
-4
db.c
dlls/msi/tests/db.c
+1
-1
update.c
dlls/msi/update.c
+7
-16
where.c
dlls/msi/where.c
+451
-183
No files found.
dlls/msi/query.h
View file @
a52c2bf9
...
...
@@ -68,10 +68,19 @@ struct complex_expr
struct
expr
*
right
;
};
struct
ext_column
struct
tagJOINTABLE
;
union
ext_column
{
LPCWSTR
column
;
LPCWSTR
table
;
struct
{
LPCWSTR
column
;
LPCWSTR
table
;
}
unparsed
;
struct
{
UINT
column
;
struct
tagJOINTABLE
*
table
;
}
parsed
;
};
struct
expr
...
...
@@ -83,8 +92,7 @@ struct expr
INT
ival
;
UINT
uval
;
LPCWSTR
sval
;
struct
ext_column
column
;
UINT
col_number
;
union
ext_column
column
;
}
u
;
};
...
...
@@ -101,7 +109,7 @@ UINT DISTINCT_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table ) DECL
UINT
ORDER_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
MSIVIEW
*
table
,
column_info
*
columns
)
DECLSPEC_HIDDEN
;
UINT
WHERE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
MSIVIEW
*
table
,
UINT
WHERE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPWSTR
tables
,
struct
expr
*
cond
)
DECLSPEC_HIDDEN
;
UINT
CREATE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
table
,
...
...
@@ -110,7 +118,7 @@ UINT CREATE_CreateView( MSIDATABASE *db, MSIVIEW **view, LPCWSTR table,
UINT
INSERT_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
table
,
column_info
*
columns
,
column_info
*
values
,
BOOL
temp
)
DECLSPEC_HIDDEN
;
UINT
UPDATE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LP
C
WSTR
table
,
UINT
UPDATE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPWSTR
table
,
column_info
*
list
,
struct
expr
*
expr
)
DECLSPEC_HIDDEN
;
UINT
DELETE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
MSIVIEW
*
table
)
DECLSPEC_HIDDEN
;
...
...
dlls/msi/sql.y
View file @
a52c2bf9
...
...
@@ -478,13 +478,13 @@ selcollist:
from:
fromtable
|
fromtable
TK_WHERE expr
|
TK_FROM tablelist
TK_WHERE expr
{
SQL_input* sql = (SQL_input*) info;
MSIVIEW* where = NULL;
UINT r;
r = WHERE_CreateView( sql->db, &where, $
1, $3
);
r = WHERE_CreateView( sql->db, &where, $
2, $4
);
if( r != ERROR_SUCCESS )
YYABORT;
...
...
@@ -877,8 +877,8 @@ static struct expr * EXPR_column( void *info, const column_info *column )
if( e )
{
e->type = EXPR_COLUMN;
e->u.column.column = column->column;
e->u.column.table = column->table;
e->u.column.
unparsed.
column = column->column;
e->u.column.
unparsed.
table = column->table;
}
return e;
}
...
...
dlls/msi/tests/db.c
View file @
a52c2bf9
...
...
@@ -3895,7 +3895,7 @@ static void test_join(void)
/* primary key cannot be updated */
r
=
MsiViewModify
(
hview
,
MSIMODIFY_UPDATE
,
hrec
);
todo_wine
ok
(
r
==
ERROR_FUNCTION_FAILED
,
"failed to update row: %d
\n
"
,
r
);
ok
(
r
==
ERROR_FUNCTION_FAILED
,
"failed to update row: %d
\n
"
,
r
);
MsiCloseHandle
(
hrec
);
MsiViewClose
(
hview
);
...
...
dlls/msi/update.c
View file @
a52c2bf9
...
...
@@ -225,31 +225,22 @@ static const MSIVIEWOPS update_ops =
NULL
,
};
UINT
UPDATE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LP
C
WSTR
table
,
UINT
UPDATE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPWSTR
table
,
column_info
*
columns
,
struct
expr
*
expr
)
{
MSIUPDATEVIEW
*
uv
=
NULL
;
UINT
r
;
MSIVIEW
*
tv
=
NULL
,
*
sv
=
NULL
,
*
wv
=
NULL
;
MSIVIEW
*
sv
=
NULL
,
*
wv
=
NULL
;
TRACE
(
"%p
\n
"
,
uv
);
r
=
TABLE_CreateView
(
db
,
table
,
&
tv
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
expr
)
{
/* add conditions first */
r
=
WHERE_CreateView
(
db
,
&
wv
,
tv
,
expr
);
if
(
r
!=
ERROR_SUCCESS
)
{
tv
->
ops
->
delete
(
tv
);
return
r
;
}
}
r
=
WHERE_CreateView
(
db
,
&
wv
,
table
,
expr
);
else
wv
=
tv
;
r
=
TABLE_CreateView
(
db
,
table
,
&
wv
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
/* then select the columns we want */
r
=
SELECT_CreateView
(
db
,
&
sv
,
wv
,
columns
);
...
...
dlls/msi/where.c
View file @
a52c2bf9
...
...
@@ -19,6 +19,7 @@
*/
#include <stdarg.h>
#include <assert.h>
#include "windef.h"
#include "winbase.h"
...
...
@@ -36,19 +37,30 @@
WINE_DEFAULT_DEBUG_CHANNEL
(
msidb
);
/* below is the query interface to a table */
typedef
struct
tagMSIROWENTRY
{
UINT
value
;
UINT
value
s
[
1
]
;
}
MSIROWENTRY
;
/* below is the query interface to a table */
typedef
struct
tagJOINTABLE
{
struct
tagJOINTABLE
*
next
;
MSIVIEW
*
view
;
UINT
col_count
;
UINT
row_count
;
UINT
table_index
;
}
JOINTABLE
;
typedef
struct
tagMSIWHEREVIEW
{
MSIVIEW
view
;
MSIDATABASE
*
db
;
MSIVIEW
*
table
;
JOINTABLE
*
tables
;
UINT
row_count
;
UINT
col_count
;
UINT
table_count
;
MSIROWENTRY
**
reorder
;
UINT
reorder_size
;
/* number of entries available in reorder */
struct
expr
*
cond
;
...
...
@@ -89,20 +101,17 @@ static void free_reorder(MSIWHEREVIEW *wv)
wv
->
row_count
=
0
;
}
static
inline
UINT
find_row
(
MSIWHEREVIEW
*
wv
,
UINT
row
,
UINT
*
value
)
static
inline
UINT
find_row
(
MSIWHEREVIEW
*
wv
,
UINT
row
,
UINT
*
(
values
[])
)
{
if
(
row
>=
wv
->
row_count
)
{
*
value
=
-
2
;
return
ERROR_NO_MORE_ITEMS
;
}
*
value
=
wv
->
reorder
[
row
]
->
value
;
*
value
s
=
wv
->
reorder
[
row
]
->
values
;
return
ERROR_SUCCESS
;
}
static
UINT
add_row
(
MSIWHEREVIEW
*
wv
,
UINT
val
)
static
UINT
add_row
(
MSIWHEREVIEW
*
wv
,
UINT
val
s
[]
)
{
MSIROWENTRY
*
new
;
...
...
@@ -119,101 +128,204 @@ static UINT add_row(MSIWHEREVIEW *wv, UINT val)
wv
->
reorder_size
=
newsize
;
}
new
=
msi_alloc
(
sizeof
(
MSIROWENTRY
));
new
=
msi_alloc
(
FIELD_OFFSET
(
MSIROWENTRY
,
values
[
wv
->
table_count
]
));
if
(
!
new
)
return
ERROR_OUTOFMEMORY
;
wv
->
reorder
[
wv
->
row_count
++
]
=
new
;
new
->
value
=
val
;
memcpy
(
new
->
values
,
vals
,
wv
->
table_count
*
sizeof
(
UINT
))
;
return
ERROR_SUCCESS
;
}
JOINTABLE
*
find_table
(
MSIWHEREVIEW
*
wv
,
UINT
col
,
UINT
*
table_col
)
{
JOINTABLE
*
table
=
wv
->
tables
;
if
(
col
==
0
||
col
>
wv
->
col_count
)
return
NULL
;
while
(
col
>
table
->
col_count
)
{
col
-=
table
->
col_count
;
table
=
table
->
next
;
assert
(
table
);
}
*
table_col
=
col
;
return
table
;
}
static
UINT
parse_column
(
MSIWHEREVIEW
*
wv
,
union
ext_column
*
column
,
UINT
*
column_type
)
{
JOINTABLE
*
table
=
wv
->
tables
;
UINT
i
,
r
;
do
{
LPCWSTR
table_name
;
if
(
column
->
unparsed
.
table
)
{
r
=
table
->
view
->
ops
->
get_column_info
(
table
->
view
,
1
,
NULL
,
NULL
,
NULL
,
&
table_name
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
strcmpW
(
table_name
,
column
->
unparsed
.
table
)
!=
0
)
continue
;
}
for
(
i
=
1
;
i
<=
table
->
col_count
;
i
++
)
{
LPCWSTR
col_name
;
r
=
table
->
view
->
ops
->
get_column_info
(
table
->
view
,
i
,
&
col_name
,
column_type
,
NULL
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
strcmpW
(
col_name
,
column
->
unparsed
.
column
))
continue
;
column
->
parsed
.
column
=
i
;
column
->
parsed
.
table
=
table
;
return
ERROR_SUCCESS
;
break
;
}
}
while
((
table
=
table
->
next
));
WARN
(
"Couldn't find column %s.%s
\n
"
,
debugstr_w
(
column
->
unparsed
.
table
),
debugstr_w
(
column
->
unparsed
.
column
)
);
return
ERROR_BAD_QUERY_SYNTAX
;
}
static
UINT
WHERE_fetch_int
(
struct
tagMSIVIEW
*
view
,
UINT
row
,
UINT
col
,
UINT
*
val
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
JOINTABLE
*
table
;
UINT
*
rows
;
UINT
r
;
TRACE
(
"%p %d %d %p
\n
"
,
wv
,
row
,
col
,
val
);
if
(
!
wv
->
table
)
if
(
!
wv
->
table
s
)
return
ERROR_FUNCTION_FAILED
;
r
=
find_row
(
wv
,
row
,
&
row
);
r
=
find_row
(
wv
,
row
,
&
row
s
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
return
wv
->
table
->
ops
->
fetch_int
(
wv
->
table
,
row
,
col
,
val
);
table
=
find_table
(
wv
,
col
,
&
col
);
if
(
!
table
)
return
ERROR_FUNCTION_FAILED
;
return
table
->
view
->
ops
->
fetch_int
(
table
->
view
,
rows
[
table
->
table_index
],
col
,
val
);
}
static
UINT
WHERE_fetch_stream
(
struct
tagMSIVIEW
*
view
,
UINT
row
,
UINT
col
,
IStream
**
stm
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
JOINTABLE
*
table
;
UINT
*
rows
;
UINT
r
;
TRACE
(
"%p %d %d %p
\n
"
,
wv
,
row
,
col
,
stm
);
if
(
!
wv
->
table
)
if
(
!
wv
->
table
s
)
return
ERROR_FUNCTION_FAILED
;
r
=
find_row
(
wv
,
row
,
&
row
);
r
=
find_row
(
wv
,
row
,
&
row
s
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
return
wv
->
table
->
ops
->
fetch_stream
(
wv
->
table
,
row
,
col
,
stm
);
table
=
find_table
(
wv
,
col
,
&
col
);
if
(
!
table
)
return
ERROR_FUNCTION_FAILED
;
return
table
->
view
->
ops
->
fetch_stream
(
table
->
view
,
rows
[
table
->
table_index
],
col
,
stm
);
}
static
UINT
WHERE_get_row
(
struct
tagMSIVIEW
*
view
,
UINT
row
,
MSIRECORD
**
rec
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
UINT
r
;
TRACE
(
"%p %d %p
\n
"
,
wv
,
row
,
rec
);
if
(
!
wv
->
table
)
if
(
!
wv
->
table
s
)
return
ERROR_FUNCTION_FAILED
;
r
=
find_row
(
wv
,
row
,
&
row
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
return
wv
->
table
->
ops
->
get_row
(
wv
->
table
,
row
,
rec
);
return
msi_view_get_row
(
wv
->
db
,
view
,
row
,
rec
);
}
static
UINT
WHERE_set_row
(
struct
tagMSIVIEW
*
view
,
UINT
row
,
MSIRECORD
*
rec
,
UINT
mask
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
UINT
r
;
UINT
r
,
offset
=
0
,
reduced_mask
=
0
;
JOINTABLE
*
table
=
wv
->
tables
;
UINT
*
rows
;
TRACE
(
"%p %d %p %08x
\n
"
,
wv
,
row
,
rec
,
mask
);
if
(
!
wv
->
table
)
if
(
!
wv
->
table
s
)
return
ERROR_FUNCTION_FAILED
;
r
=
find_row
(
wv
,
row
,
&
row
);
r
=
find_row
(
wv
,
row
,
&
row
s
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
return
wv
->
table
->
ops
->
set_row
(
wv
->
table
,
row
,
rec
,
mask
);
if
(
mask
>=
1
<<
wv
->
col_count
)
return
ERROR_INVALID_PARAMETER
;
do
{
const
UINT
col_count
=
table
->
col_count
;
UINT
i
;
MSIRECORD
*
reduced
;
reduced
=
MSI_CreateRecord
(
col_count
);
if
(
!
reduced
)
return
ERROR_FUNCTION_FAILED
;
for
(
i
=
0
;
i
<
col_count
;
i
++
)
{
r
=
MSI_RecordCopyField
(
rec
,
i
+
offset
+
1
,
reduced
,
i
+
1
);
if
(
r
!=
ERROR_SUCCESS
)
break
;
}
offset
+=
col_count
;
reduced_mask
=
mask
>>
(
wv
->
col_count
-
offset
)
&
((
1
<<
col_count
)
-
1
);
if
(
r
==
ERROR_SUCCESS
)
r
=
table
->
view
->
ops
->
set_row
(
table
->
view
,
rows
[
table
->
table_index
],
reduced
,
reduced_mask
);
msiobj_release
(
&
reduced
->
hdr
);
}
while
((
table
=
table
->
next
));
return
r
;
}
static
UINT
WHERE_delete_row
(
struct
tagMSIVIEW
*
view
,
UINT
row
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
UINT
r
;
UINT
*
rows
;
TRACE
(
"(%p %d)
\n
"
,
view
,
row
);
if
(
!
wv
->
table
)
if
(
!
wv
->
tables
)
return
ERROR_FUNCTION_FAILED
;
r
=
find_row
(
wv
,
row
,
&
row
);
r
=
find_row
(
wv
,
row
,
&
rows
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
return
wv
->
table
->
ops
->
delete_row
(
wv
->
table
,
row
);
if
(
wv
->
table_count
>
1
)
return
ERROR_CALL_NOT_IMPLEMENTED
;
return
wv
->
tables
->
view
->
ops
->
delete_row
(
wv
->
tables
->
view
,
rows
[
0
]);
}
static
INT
INT_evaluate_binary
(
INT
lval
,
UINT
op
,
INT
rval
)
...
...
@@ -242,6 +354,15 @@ static INT INT_evaluate_binary( INT lval, UINT op, INT rval )
return
0
;
}
static
inline
UINT
expr_fetch_value
(
const
union
ext_column
*
expr
,
const
UINT
rows
[],
UINT
*
val
)
{
JOINTABLE
*
table
=
expr
->
parsed
.
table
;
return
table
->
view
->
ops
->
fetch_int
(
table
->
view
,
rows
[
table
->
table_index
],
expr
->
parsed
.
column
,
val
);
}
static
INT
INT_evaluate_unary
(
INT
lval
,
UINT
op
)
{
switch
(
op
)
...
...
@@ -256,7 +377,7 @@ static INT INT_evaluate_unary( INT lval, UINT op )
return
0
;
}
static
const
WCHAR
*
STRING_evaluate
(
MSIWHEREVIEW
*
wv
,
UINT
row
,
static
const
WCHAR
*
STRING_evaluate
(
MSIWHEREVIEW
*
wv
,
const
UINT
rows
[]
,
const
struct
expr
*
expr
,
const
MSIRECORD
*
record
)
{
...
...
@@ -265,7 +386,7 @@ static const WCHAR *STRING_evaluate( MSIWHEREVIEW *wv, UINT row,
switch
(
expr
->
type
)
{
case
EXPR_COL_NUMBER_STRING
:
r
=
wv
->
table
->
ops
->
fetch_int
(
wv
->
table
,
row
,
expr
->
u
.
col_number
,
&
val
);
r
=
expr_fetch_value
(
&
expr
->
u
.
column
,
rows
,
&
val
);
if
(
r
!=
ERROR_SUCCESS
)
return
NULL
;
return
msi_string_lookup_id
(
wv
->
db
->
strings
,
val
);
...
...
@@ -283,14 +404,14 @@ static const WCHAR *STRING_evaluate( MSIWHEREVIEW *wv, UINT row,
return
NULL
;
}
static
UINT
STRCMP_Evaluate
(
MSIWHEREVIEW
*
wv
,
UINT
row
,
const
struct
expr
*
cond
,
static
UINT
STRCMP_Evaluate
(
MSIWHEREVIEW
*
wv
,
const
UINT
rows
[]
,
const
struct
expr
*
cond
,
INT
*
val
,
const
MSIRECORD
*
record
)
{
int
sr
;
const
WCHAR
*
l_str
,
*
r_str
;
l_str
=
STRING_evaluate
(
wv
,
row
,
cond
->
u
.
expr
.
left
,
record
);
r_str
=
STRING_evaluate
(
wv
,
row
,
cond
->
u
.
expr
.
right
,
record
);
l_str
=
STRING_evaluate
(
wv
,
row
s
,
cond
->
u
.
expr
.
left
,
record
);
r_str
=
STRING_evaluate
(
wv
,
row
s
,
cond
->
u
.
expr
.
right
,
record
);
if
(
l_str
==
r_str
||
((
!
l_str
||
!*
l_str
)
&&
(
!
r_str
||
!*
r_str
))
)
sr
=
0
;
...
...
@@ -307,26 +428,29 @@ static UINT STRCMP_Evaluate( MSIWHEREVIEW *wv, UINT row, const struct expr *cond
return
ERROR_SUCCESS
;
}
static
UINT
WHERE_evaluate
(
MSIWHEREVIEW
*
wv
,
UINT
row
,
static
UINT
WHERE_evaluate
(
MSIWHEREVIEW
*
wv
,
const
UINT
rows
[]
,
struct
expr
*
cond
,
INT
*
val
,
MSIRECORD
*
record
)
{
UINT
r
,
tval
;
INT
lval
,
rval
;
if
(
!
cond
)
{
*
val
=
TRUE
;
return
ERROR_SUCCESS
;
}
switch
(
cond
->
type
)
{
case
EXPR_COL_NUMBER
:
r
=
wv
->
table
->
ops
->
fetch_int
(
wv
->
table
,
row
,
cond
->
u
.
col_number
,
&
tval
);
r
=
expr_fetch_value
(
&
cond
->
u
.
column
,
rows
,
&
tval
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
*
val
=
tval
-
0x8000
;
return
ERROR_SUCCESS
;
case
EXPR_COL_NUMBER32
:
r
=
wv
->
table
->
ops
->
fetch_int
(
wv
->
table
,
row
,
cond
->
u
.
col_number
,
&
tval
);
r
=
expr_fetch_value
(
&
cond
->
u
.
column
,
rows
,
&
tval
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
*
val
=
tval
-
0x80000000
;
...
...
@@ -337,24 +461,24 @@ static UINT WHERE_evaluate( MSIWHEREVIEW *wv, UINT row,
return
ERROR_SUCCESS
;
case
EXPR_COMPLEX
:
r
=
WHERE_evaluate
(
wv
,
row
,
cond
->
u
.
expr
.
left
,
&
lval
,
record
);
r
=
WHERE_evaluate
(
wv
,
row
s
,
cond
->
u
.
expr
.
left
,
&
lval
,
record
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
WHERE_evaluate
(
wv
,
row
,
cond
->
u
.
expr
.
right
,
&
rval
,
record
);
r
=
WHERE_evaluate
(
wv
,
row
s
,
cond
->
u
.
expr
.
right
,
&
rval
,
record
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
*
val
=
INT_evaluate_binary
(
lval
,
cond
->
u
.
expr
.
op
,
rval
);
return
ERROR_SUCCESS
;
case
EXPR_UNARY
:
r
=
wv
->
table
->
ops
->
fetch_int
(
wv
->
table
,
row
,
cond
->
u
.
expr
.
left
->
u
.
col_number
,
&
tval
);
r
=
expr_fetch_value
(
&
cond
->
u
.
expr
.
left
->
u
.
column
,
rows
,
&
tval
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
*
val
=
INT_evaluate_unary
(
tval
,
cond
->
u
.
expr
.
op
);
return
ERROR_SUCCESS
;
case
EXPR_STRCMP
:
return
STRCMP_Evaluate
(
wv
,
row
,
cond
,
val
,
record
);
return
STRCMP_Evaluate
(
wv
,
row
s
,
cond
,
val
,
record
);
case
EXPR_WILDCARD
:
*
val
=
MSI_RecordGetInteger
(
record
,
++
wv
->
rec_index
);
...
...
@@ -368,102 +492,88 @@ static UINT WHERE_evaluate( MSIWHEREVIEW *wv, UINT row,
return
ERROR_SUCCESS
;
}
static
UINT
check_condition
(
MSIWHEREVIEW
*
wv
,
MSIRECORD
*
record
,
JOINTABLE
*
table
,
UINT
table_rows
[]
)
{
UINT
r
=
ERROR_FUNCTION_FAILED
;
INT
val
;
for
(
table_rows
[
table
->
table_index
]
=
0
;
table_rows
[
table
->
table_index
]
<
table
->
row_count
;
table_rows
[
table
->
table_index
]
++
)
{
if
(
table
->
next
)
{
r
=
check_condition
(
wv
,
record
,
table
->
next
,
table_rows
);
if
(
r
!=
ERROR_SUCCESS
)
break
;
}
else
{
val
=
0
;
wv
->
rec_index
=
0
;
r
=
WHERE_evaluate
(
wv
,
table_rows
,
wv
->
cond
,
&
val
,
record
);
if
(
r
!=
ERROR_SUCCESS
)
break
;
if
(
!
val
)
continue
;
add_row
(
wv
,
table_rows
);
}
}
return
r
;
}
static
UINT
WHERE_execute
(
struct
tagMSIVIEW
*
view
,
MSIRECORD
*
record
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
UINT
count
=
0
,
r
,
i
;
INT
val
;
MSIVIEW
*
table
=
wv
->
table
;
UINT
r
;
JOINTABLE
*
table
=
wv
->
tables
;
UINT
rows
[
wv
->
table_count
]
;
TRACE
(
"%p %p
\n
"
,
wv
,
record
);
if
(
!
table
)
return
ERROR_FUNCTION_FAILED
;
r
=
table
->
ops
->
execute
(
table
,
record
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
table
->
ops
->
get_dimensions
(
table
,
&
count
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
init_reorder
(
wv
);
if
(
r
!=
ERROR_SUCCESS
)
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
0
)
/* disable optimization, there's no guarantee that strings are in the string table */
{
if
(
wv
->
cond
->
type
==
EXPR_STRCMP
)
do
{
MSIITERHANDLE
handle
=
NULL
;
UINT
row
,
value
,
col
;
struct
expr
*
col_cond
=
wv
->
cond
->
u
.
expr
.
left
;
struct
expr
*
val_cond
=
wv
->
cond
->
u
.
expr
.
right
;
/* swap conditionals */
if
(
col_cond
->
type
!=
EXPR_COL_NUMBER_STRING
)
{
val_cond
=
wv
->
cond
->
u
.
expr
.
left
;
col_cond
=
wv
->
cond
->
u
.
expr
.
right
;
}
table
->
view
->
ops
->
execute
(
table
->
view
,
NULL
);
if
((
col_cond
->
type
==
EXPR_COL_NUMBER_STRING
)
&&
(
val_cond
->
type
==
EXPR_SVAL
))
r
=
table
->
view
->
ops
->
get_dimensions
(
table
->
view
,
&
table
->
row_count
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
{
col
=
col_cond
->
u
.
col_number
;
/* special case for "" - translate it into nil */
if
(
!
val_cond
->
u
.
sval
[
0
])
value
=
0
;
else
{
r
=
msi_string2idW
(
wv
->
db
->
strings
,
val_cond
->
u
.
sval
,
&
value
);
if
(
r
!=
ERROR_SUCCESS
)
{
TRACE
(
"no id for %s, assuming it doesn't exist in the table
\n
"
,
debugstr_w
(
wv
->
cond
->
u
.
expr
.
right
->
u
.
sval
));
return
ERROR_SUCCESS
;
}
}
do
{
r
=
table
->
ops
->
find_matching_rows
(
table
,
col
,
value
,
&
row
,
&
handle
);
if
(
r
==
ERROR_SUCCESS
)
add_row
(
wv
,
row
);
}
while
(
r
==
ERROR_SUCCESS
);
if
(
r
==
ERROR_NO_MORE_ITEMS
)
return
ERROR_SUCCESS
;
else
return
r
;
ERR
(
"failed to get table dimensions
\n
"
);
return
r
;
}
/* else fallback to slow case */
}
}
for
(
i
=
0
;
i
<
count
;
i
++
)
{
val
=
0
;
wv
->
rec_index
=
0
;
r
=
WHERE_evaluate
(
wv
,
i
,
wv
->
cond
,
&
val
,
record
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
val
)
add_row
(
wv
,
i
);
/* each table must have at least one row */
if
(
table
->
row_count
==
0
)
return
ERROR_SUCCESS
;
}
while
((
table
=
table
->
next
));
return
ERROR_SUCCESS
;
r
=
check_condition
(
wv
,
record
,
wv
->
tables
,
rows
);
return
r
;
}
static
UINT
WHERE_close
(
struct
tagMSIVIEW
*
view
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
JOINTABLE
*
table
=
wv
->
tables
;
TRACE
(
"%p
\n
"
,
wv
);
if
(
!
wv
->
table
)
if
(
!
table
)
return
ERROR_FUNCTION_FAILED
;
return
wv
->
table
->
ops
->
close
(
wv
->
table
);
do
table
->
view
->
ops
->
close
(
table
->
view
);
while
((
table
=
table
->
next
));
return
ERROR_SUCCESS
;
}
static
UINT
WHERE_get_dimensions
(
struct
tagMSIVIEW
*
view
,
UINT
*
rows
,
UINT
*
cols
)
...
...
@@ -472,55 +582,152 @@ static UINT WHERE_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *col
TRACE
(
"%p %p %p
\n
"
,
wv
,
rows
,
cols
);
if
(
!
wv
->
table
)
if
(
!
wv
->
tables
)
return
ERROR_FUNCTION_FAILED
;
if
(
rows
)
if
(
rows
)
{
if
(
!
wv
->
reorder
)
if
(
!
wv
->
reorder
)
return
ERROR_FUNCTION_FAILED
;
*
rows
=
wv
->
row_count
;
}
return
wv
->
table
->
ops
->
get_dimensions
(
wv
->
table
,
NULL
,
cols
);
if
(
cols
)
*
cols
=
wv
->
col_count
;
return
ERROR_SUCCESS
;
}
static
UINT
WHERE_get_column_info
(
struct
tagMSIVIEW
*
view
,
UINT
n
,
LPCWSTR
*
name
,
UINT
*
type
,
BOOL
*
temporary
,
LPCWSTR
*
table_name
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
JOINTABLE
*
table
;
TRACE
(
"%p %d %p %p %p %p
\n
"
,
wv
,
n
,
name
,
type
,
temporary
,
table_name
);
if
(
!
wv
->
table
)
if
(
!
wv
->
tables
)
return
ERROR_FUNCTION_FAILED
;
return
wv
->
table
->
ops
->
get_column_info
(
wv
->
table
,
n
,
name
,
type
,
temporary
,
table_name
);
table
=
find_table
(
wv
,
n
,
&
n
);
if
(
!
table
)
return
ERROR_FUNCTION_FAILED
;
return
table
->
view
->
ops
->
get_column_info
(
table
->
view
,
n
,
name
,
type
,
temporary
,
table_name
);
}
static
UINT
join_find_row
(
MSIWHEREVIEW
*
wv
,
MSIRECORD
*
rec
,
UINT
*
row
)
{
LPCWSTR
str
;
UINT
r
,
i
,
id
,
data
;
str
=
MSI_RecordGetString
(
rec
,
1
);
r
=
msi_string2idW
(
wv
->
db
->
strings
,
str
,
&
id
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
for
(
i
=
0
;
i
<
wv
->
row_count
;
i
++
)
{
WHERE_fetch_int
(
&
wv
->
view
,
i
,
1
,
&
data
);
if
(
data
==
id
)
{
*
row
=
i
;
return
ERROR_SUCCESS
;
}
}
return
ERROR_FUNCTION_FAILED
;
}
static
UINT
join_modify_update
(
struct
tagMSIVIEW
*
view
,
MSIRECORD
*
rec
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
UINT
r
,
row
;
r
=
join_find_row
(
wv
,
rec
,
&
row
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
return
WHERE_set_row
(
view
,
row
,
rec
,
(
1
<<
wv
->
col_count
)
-
1
);
}
static
UINT
WHERE_modify
(
struct
tagMSIVIEW
*
view
,
MSIMODIFY
eModifyMode
,
MSIRECORD
*
rec
,
UINT
row
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
JOINTABLE
*
table
=
wv
->
tables
;
UINT
r
;
TRACE
(
"%p %d %p
\n
"
,
wv
,
eModifyMode
,
rec
);
find_row
(
wv
,
row
-
1
,
&
row
);
row
++
;
if
(
!
table
)
return
ERROR_FUNCTION_FAILED
;
if
(
!
table
->
next
)
{
UINT
*
rows
;
if
(
find_row
(
wv
,
row
-
1
,
&
rows
)
==
ERROR_SUCCESS
)
row
=
rows
[
0
]
+
1
;
else
row
=
-
1
;
return
wv
->
table
->
ops
->
modify
(
wv
->
table
,
eModifyMode
,
rec
,
row
);
return
table
->
view
->
ops
->
modify
(
table
->
view
,
eModifyMode
,
rec
,
row
);
}
switch
(
eModifyMode
)
{
case
MSIMODIFY_UPDATE
:
return
join_modify_update
(
view
,
rec
);
case
MSIMODIFY_ASSIGN
:
case
MSIMODIFY_DELETE
:
case
MSIMODIFY_INSERT
:
case
MSIMODIFY_INSERT_TEMPORARY
:
case
MSIMODIFY_MERGE
:
case
MSIMODIFY_REPLACE
:
case
MSIMODIFY_SEEK
:
case
MSIMODIFY_VALIDATE
:
case
MSIMODIFY_VALIDATE_DELETE
:
case
MSIMODIFY_VALIDATE_FIELD
:
case
MSIMODIFY_VALIDATE_NEW
:
r
=
ERROR_FUNCTION_FAILED
;
break
;
case
MSIMODIFY_REFRESH
:
r
=
ERROR_CALL_NOT_IMPLEMENTED
;
break
;
default:
WARN
(
"%p %d %p %u - unknown mode
\n
"
,
view
,
eModifyMode
,
rec
,
row
);
r
=
ERROR_INVALID_PARAMETER
;
break
;
}
return
r
;
}
static
UINT
WHERE_delete
(
struct
tagMSIVIEW
*
view
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
JOINTABLE
*
table
=
wv
->
tables
;
TRACE
(
"%p
\n
"
,
wv
);
if
(
wv
->
table
)
wv
->
table
->
ops
->
delete
(
wv
->
table
);
wv
->
table
=
0
;
while
(
table
)
{
JOINTABLE
*
next
;
table
->
view
->
ops
->
delete
(
table
->
view
);
table
->
view
=
NULL
;
next
=
table
->
next
;
msi_free
(
table
);
table
=
next
;
}
wv
->
tables
=
NULL
;
wv
->
table_count
=
0
;
free_reorder
(
wv
);
...
...
@@ -534,27 +741,52 @@ static UINT WHERE_find_matching_rows( struct tagMSIVIEW *view, UINT col,
UINT
val
,
UINT
*
row
,
MSIITERHANDLE
*
handle
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
UINT
r
;
UINT
i
,
row_value
;
TRACE
(
"%p, %d, %u, %p
\n
"
,
view
,
col
,
val
,
*
handle
);
if
(
!
wv
->
table
)
if
(
!
wv
->
tables
)
return
ERROR_FUNCTION_FAILED
;
r
=
wv
->
table
->
ops
->
find_matching_rows
(
wv
->
table
,
col
,
val
,
row
,
handle
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
col
==
0
||
col
>
wv
->
col_count
)
return
ERROR_INVALID_PARAMETER
;
return
find_row
(
wv
,
*
row
,
row
);
for
(
i
=
PtrToUlong
(
*
handle
);
i
<
wv
->
row_count
;
i
++
)
{
if
(
view
->
ops
->
fetch_int
(
view
,
i
,
col
,
&
row_value
)
!=
ERROR_SUCCESS
)
continue
;
if
(
row_value
==
val
)
{
*
row
=
i
;
*
handle
=
UlongToPtr
(
i
+
1
);
return
ERROR_SUCCESS
;
}
}
return
ERROR_NO_MORE_ITEMS
;
}
static
UINT
WHERE_sort
(
struct
tagMSIVIEW
*
view
,
column_info
*
columns
)
{
MSIWHEREVIEW
*
wv
=
(
MSIWHEREVIEW
*
)
view
;
JOINTABLE
*
table
=
wv
->
tables
;
UINT
r
;
TRACE
(
"%p %p
\n
"
,
view
,
columns
);
return
wv
->
table
->
ops
->
sort
(
wv
->
table
,
columns
);
if
(
!
table
)
return
ERROR_FUNCTION_FAILED
;
do
{
r
=
table
->
view
->
ops
->
sort
(
table
->
view
,
columns
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
}
while
((
table
=
table
->
next
));
return
ERROR_SUCCESS
;
}
static
const
MSIVIEWOPS
where_ops
=
...
...
@@ -580,48 +812,40 @@ static const MSIVIEWOPS where_ops =
NULL
,
};
static
UINT
WHERE_VerifyCondition
(
MSI
DATABASE
*
db
,
MSIVIEW
*
table
,
struct
expr
*
cond
,
static
UINT
WHERE_VerifyCondition
(
MSI
WHEREVIEW
*
wv
,
struct
expr
*
cond
,
UINT
*
valid
)
{
UINT
r
,
val
=
0
;
UINT
r
;
switch
(
cond
->
type
)
{
case
EXPR_COLUMN
:
r
=
VIEW_find_column
(
table
,
cond
->
u
.
column
.
column
,
cond
->
u
.
column
.
table
,
&
val
);
if
(
r
==
ERROR_SUCCESS
)
{
UINT
type
=
0
;
r
=
table
->
ops
->
get_column_info
(
table
,
val
,
NULL
,
&
type
,
NULL
,
NULL
);
if
(
r
==
ERROR_SUCCESS
)
{
if
(
type
&
MSITYPE_STRING
)
cond
->
type
=
EXPR_COL_NUMBER_STRING
;
else
if
((
type
&
0xff
)
==
4
)
cond
->
type
=
EXPR_COL_NUMBER32
;
else
cond
->
type
=
EXPR_COL_NUMBER
;
cond
->
u
.
col_number
=
val
;
*
valid
=
1
;
}
else
*
valid
=
0
;
}
{
UINT
type
;
*
valid
=
FALSE
;
r
=
parse_column
(
wv
,
&
cond
->
u
.
column
,
&
type
);
if
(
r
!=
ERROR_SUCCESS
)
break
;
if
(
type
&
MSITYPE_STRING
)
cond
->
type
=
EXPR_COL_NUMBER_STRING
;
else
if
((
type
&
0xff
)
==
4
)
cond
->
type
=
EXPR_COL_NUMBER32
;
else
{
*
valid
=
0
;
WARN
(
"Couldn't find column %s.%s
\n
"
,
debugstr_w
(
cond
->
u
.
column
.
table
),
debugstr_w
(
cond
->
u
.
column
.
column
)
);
}
cond
->
type
=
EXPR_COL_NUMBER
;
*
valid
=
TRUE
;
break
;
}
case
EXPR_COMPLEX
:
r
=
WHERE_VerifyCondition
(
db
,
table
,
cond
->
u
.
expr
.
left
,
valid
);
r
=
WHERE_VerifyCondition
(
wv
,
cond
->
u
.
expr
.
left
,
valid
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
!*
valid
)
return
ERROR_SUCCESS
;
r
=
WHERE_VerifyCondition
(
db
,
table
,
cond
->
u
.
expr
.
right
,
valid
);
r
=
WHERE_VerifyCondition
(
wv
,
cond
->
u
.
expr
.
right
,
valid
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
...
...
@@ -653,7 +877,7 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr
*
valid
=
FALSE
;
return
ERROR_INVALID_PARAMETER
;
}
r
=
WHERE_VerifyCondition
(
db
,
table
,
cond
->
u
.
expr
.
left
,
valid
);
r
=
WHERE_VerifyCondition
(
wv
,
cond
->
u
.
expr
.
left
,
valid
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
break
;
...
...
@@ -677,29 +901,15 @@ static UINT WHERE_VerifyCondition( MSIDATABASE *db, MSIVIEW *table, struct expr
return
ERROR_SUCCESS
;
}
UINT
WHERE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
MSIVIEW
*
table
,
UINT
WHERE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPWSTR
tables
,
struct
expr
*
cond
)
{
MSIWHEREVIEW
*
wv
=
NULL
;
UINT
count
=
0
,
r
,
valid
=
0
;
UINT
r
,
valid
=
0
;
WCHAR
*
ptr
;
JOINTABLE
**
lastnext
;
TRACE
(
"%p
\n
"
,
table
);
r
=
table
->
ops
->
get_dimensions
(
table
,
NULL
,
&
count
);
if
(
r
!=
ERROR_SUCCESS
)
{
ERR
(
"can't get table dimensions
\n
"
);
return
r
;
}
if
(
cond
)
{
r
=
WHERE_VerifyCondition
(
db
,
table
,
cond
,
&
valid
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
!
valid
)
return
ERROR_FUNCTION_FAILED
;
}
TRACE
(
"(%s)
\n
"
,
debugstr_w
(
tables
)
);
wv
=
msi_alloc_zero
(
sizeof
*
wv
);
if
(
!
wv
)
...
...
@@ -709,12 +919,70 @@ UINT WHERE_CreateView( MSIDATABASE *db, MSIVIEW **view, MSIVIEW *table,
wv
->
view
.
ops
=
&
where_ops
;
msiobj_addref
(
&
db
->
hdr
);
wv
->
db
=
db
;
wv
->
table
=
table
;
wv
->
row_count
=
0
;
wv
->
reorder
=
NULL
;
wv
->
cond
=
cond
;
wv
->
rec_index
=
0
;
lastnext
=
&
wv
->
tables
;
while
(
*
tables
)
{
JOINTABLE
*
table
;
if
((
ptr
=
strchrW
(
tables
,
' '
)))
*
ptr
=
'\0'
;
table
=
msi_alloc
(
sizeof
(
JOINTABLE
));
if
(
!
table
)
{
r
=
ERROR_OUTOFMEMORY
;
goto
end
;
}
r
=
TABLE_CreateView
(
db
,
tables
,
&
table
->
view
);
if
(
r
!=
ERROR_SUCCESS
)
{
WARN
(
"can't create table: %s
\n
"
,
debugstr_w
(
tables
));
msi_free
(
table
);
r
=
ERROR_BAD_QUERY_SYNTAX
;
goto
end
;
}
r
=
table
->
view
->
ops
->
get_dimensions
(
table
->
view
,
NULL
,
&
table
->
col_count
);
if
(
r
!=
ERROR_SUCCESS
)
{
ERR
(
"can't get table dimensions
\n
"
);
goto
end
;
}
wv
->
col_count
+=
table
->
col_count
;
table
->
table_index
=
wv
->
table_count
++
;
table
->
next
=
NULL
;
*
lastnext
=
table
;
lastnext
=
&
table
->
next
;
if
(
!
ptr
)
break
;
tables
=
ptr
+
1
;
}
if
(
cond
)
{
r
=
WHERE_VerifyCondition
(
wv
,
cond
,
&
valid
);
if
(
r
!=
ERROR_SUCCESS
)
goto
end
;
if
(
!
valid
)
{
r
=
ERROR_FUNCTION_FAILED
;
goto
end
;
}
}
*
view
=
(
MSIVIEW
*
)
wv
;
return
ERROR_SUCCESS
;
end:
WHERE_delete
(
&
wv
->
view
);
return
r
;
}
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