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
c6124db9
Commit
c6124db9
authored
Oct 31, 2006
by
Mike McCormack
Committed by
Alexandre Julliard
Oct 31, 2006
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Use a simpler algorithm for joins.
parent
8fc5fbe7
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
40 additions
and
245 deletions
+40
-245
join.c
dlls/msi/join.c
+24
-158
query.h
dlls/msi/query.h
+1
-2
sql.y
dlls/msi/sql.y
+12
-16
db.c
dlls/msi/tests/db.c
+3
-69
No files found.
dlls/msi/join.c
View file @
c6124db9
...
...
@@ -39,9 +39,7 @@ typedef struct tagMSIJOINVIEW
MSIDATABASE
*
db
;
MSIVIEW
*
left
,
*
right
;
UINT
left_count
,
right_count
;
UINT
left_key
,
right_key
;
UINT
*
pairs
;
UINT
pair_count
;
UINT
left_rows
,
right_rows
;
}
MSIJOINVIEW
;
static
UINT
JOIN_fetch_int
(
struct
tagMSIVIEW
*
view
,
UINT
row
,
UINT
col
,
UINT
*
val
)
...
...
@@ -57,18 +55,18 @@ static UINT JOIN_fetch_int( struct tagMSIVIEW *view, UINT row, UINT col, UINT *v
if
(
(
col
==
0
)
||
(
col
>
(
jv
->
left_count
+
jv
->
right_count
))
)
return
ERROR_FUNCTION_FAILED
;
if
(
row
>=
jv
->
pair_count
)
if
(
row
>=
(
jv
->
left_rows
*
jv
->
right_rows
)
)
return
ERROR_FUNCTION_FAILED
;
if
(
col
<=
jv
->
left_count
)
{
table
=
jv
->
left
;
row
=
jv
->
pairs
[
row
*
2
]
;
row
=
(
row
/
jv
->
right_rows
)
;
}
else
{
table
=
jv
->
right
;
row
=
jv
->
pairs
[
row
*
2
+
1
]
;
row
=
(
row
%
jv
->
right_rows
)
;
col
-=
jv
->
left_count
;
}
...
...
@@ -88,115 +86,28 @@ static UINT JOIN_fetch_stream( struct tagMSIVIEW *view, UINT row, UINT col, IStr
if
(
(
col
==
0
)
||
(
col
>
(
jv
->
left_count
+
jv
->
right_count
))
)
return
ERROR_FUNCTION_FAILED
;
if
(
row
>=
jv
->
left_rows
*
jv
->
right_rows
)
return
ERROR_FUNCTION_FAILED
;
if
(
row
<=
jv
->
left_count
)
{
table
=
jv
->
left
;
row
=
jv
->
pairs
[
row
*
2
]
;
row
=
(
row
/
jv
->
right_rows
)
;
}
else
{
table
=
jv
->
right
;
row
=
jv
->
pairs
[
row
*
2
+
1
]
;
row
=
(
row
%
jv
->
right_rows
)
;
col
-=
jv
->
left_count
;
}
return
table
->
ops
->
fetch_stream
(
table
,
row
,
col
,
stm
);
}
static
int
join_key_compare
(
const
void
*
l
,
const
void
*
r
)
{
const
UINT
*
left
=
l
,
*
right
=
r
;
if
(
left
[
1
]
<
right
[
1
])
return
-
1
;
if
(
left
[
1
]
==
right
[
1
])
return
0
;
return
1
;
}
static
UINT
join_load_key_column
(
MSIJOINVIEW
*
jv
,
MSIVIEW
*
table
,
UINT
column
,
UINT
**
pdata
,
UINT
*
pcount
)
{
UINT
r
,
i
,
count
=
0
,
*
data
=
NULL
;
r
=
table
->
ops
->
get_dimensions
(
table
,
&
count
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
if
(
!
count
)
goto
end
;
data
=
msi_alloc
(
count
*
2
*
sizeof
(
UINT
)
);
if
(
!
data
)
return
ERROR_SUCCESS
;
for
(
i
=
0
;
i
<
count
;
i
++
)
{
data
[
i
*
2
]
=
i
;
r
=
table
->
ops
->
fetch_int
(
table
,
i
,
column
,
&
data
[
i
*
2
+
1
]
);
if
(
r
!=
ERROR_SUCCESS
)
ERR
(
"fetch data (%u,%u) failed
\n
"
,
i
,
column
);
}
qsort
(
data
,
count
,
2
*
sizeof
(
UINT
),
join_key_compare
);
end:
*
pdata
=
data
;
*
pcount
=
count
;
return
ERROR_SUCCESS
;
}
static
UINT
join_match
(
UINT
*
ldata
,
UINT
lcount
,
UINT
*
rdata
,
UINT
rcount
,
UINT
**
ppairs
,
UINT
*
ppair_count
)
{
UINT
*
pairs
;
UINT
n
,
i
,
j
;
TRACE
(
"left %u right %u
\n
"
,
rcount
,
lcount
);
/* there can be at most max(lcount, rcount) matches */
if
(
lcount
>
rcount
)
n
=
lcount
;
else
n
=
rcount
;
pairs
=
msi_alloc
(
n
*
2
*
sizeof
(
UINT
)
);
if
(
!
pairs
)
return
ERROR_OUTOFMEMORY
;
for
(
n
=
0
,
i
=
0
,
j
=
0
;
i
<
lcount
&&
j
<
rcount
;
)
{
/* values match... store the row numbers */
if
(
ldata
[
i
*
2
+
1
]
==
rdata
[
j
*
2
+
1
])
{
pairs
[
n
*
2
]
=
ldata
[
i
*
2
];
pairs
[
n
*
2
+
1
]
=
rdata
[
j
*
2
];
n
++
;
if
(
ldata
[
i
*
2
+
3
]
<
rdata
[
j
*
2
+
3
])
i
++
;
else
j
++
;
}
/* values differ... move along */
else
if
(
ldata
[
i
*
2
+
1
]
<
rdata
[
j
*
2
+
1
])
i
++
;
else
j
++
;
}
*
ppairs
=
pairs
;
*
ppair_count
=
n
;
return
ERROR_SUCCESS
;
}
static
UINT
JOIN_execute
(
struct
tagMSIVIEW
*
view
,
MSIRECORD
*
record
)
{
MSIJOINVIEW
*
jv
=
(
MSIJOINVIEW
*
)
view
;
UINT
r
,
*
ldata
=
NULL
,
*
rdata
=
NULL
,
lcount
=
0
,
rcount
=
0
;
UINT
r
,
*
ldata
=
NULL
,
*
rdata
=
NULL
;
TRACE
(
"%p %p
\n
"
,
jv
,
record
);
...
...
@@ -211,15 +122,20 @@ static UINT JOIN_execute( struct tagMSIVIEW *view, MSIRECORD *record )
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
join_load_key_column
(
jv
,
jv
->
left
,
jv
->
left_key
,
&
ldata
,
&
lcount
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
join_load_key_column
(
jv
,
jv
->
right
,
jv
->
right_key
,
&
rdata
,
&
rcount
);
if
(
r
!=
ERROR_SUCCESS
)
/* get the number of rows in each table */
r
=
jv
->
left
->
ops
->
get_dimensions
(
jv
->
left
,
&
jv
->
left_rows
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
{
ERR
(
"can't get left table dimensions
\n
"
);
goto
end
;
}
r
=
join_match
(
ldata
,
lcount
,
rdata
,
rcount
,
&
jv
->
pairs
,
&
jv
->
pair_count
);
r
=
jv
->
right
->
ops
->
get_dimensions
(
jv
->
right
,
&
jv
->
right_rows
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
{
ERR
(
"can't get right table dimensions
\n
"
);
goto
end
;
}
end:
msi_free
(
ldata
);
...
...
@@ -257,7 +173,7 @@ static UINT JOIN_get_dimensions( struct tagMSIVIEW *view, UINT *rows, UINT *cols
if
(
!
jv
->
left
||
!
jv
->
right
)
return
ERROR_FUNCTION_FAILED
;
*
rows
=
jv
->
pair_count
;
*
rows
=
jv
->
left_rows
*
jv
->
right_rows
;
}
return
ERROR_SUCCESS
;
...
...
@@ -308,9 +224,6 @@ static UINT JOIN_delete( struct tagMSIVIEW *view )
jv
->
right
->
ops
->
delete
(
jv
->
right
);
jv
->
right
=
NULL
;
msi_free
(
jv
->
pairs
);
jv
->
pairs
=
NULL
;
msi_free
(
jv
);
return
ERROR_SUCCESS
;
...
...
@@ -341,48 +254,8 @@ static const MSIVIEWOPS join_ops =
JOIN_find_matching_rows
};
/*
* join_check_condition
*
* This is probably overly strict about what kind of condition we need
* for a join query.
*/
static
UINT
join_check_condition
(
MSIJOINVIEW
*
jv
,
struct
expr
*
cond
)
{
UINT
r
;
/* assume that we have `KeyColumn` = `SubkeyColumn` */
if
(
cond
->
type
!=
EXPR_COMPLEX
)
return
ERROR_FUNCTION_FAILED
;
if
(
cond
->
u
.
expr
.
op
!=
OP_EQ
)
return
ERROR_FUNCTION_FAILED
;
if
(
cond
->
u
.
expr
.
left
->
type
!=
EXPR_COLUMN
)
return
ERROR_FUNCTION_FAILED
;
if
(
cond
->
u
.
expr
.
right
->
type
!=
EXPR_COLUMN
)
return
ERROR_FUNCTION_FAILED
;
/* make sure both columns exist */
r
=
VIEW_find_column
(
jv
->
left
,
cond
->
u
.
expr
.
left
->
u
.
column
,
&
jv
->
left_key
);
if
(
r
!=
ERROR_SUCCESS
)
return
ERROR_FUNCTION_FAILED
;
r
=
VIEW_find_column
(
jv
->
right
,
cond
->
u
.
expr
.
right
->
u
.
column
,
&
jv
->
right_key
);
if
(
r
!=
ERROR_SUCCESS
)
return
ERROR_FUNCTION_FAILED
;
TRACE
(
"left %s (%u) right %s (%u)
\n
"
,
debugstr_w
(
cond
->
u
.
expr
.
left
->
u
.
column
),
jv
->
left_key
,
debugstr_w
(
cond
->
u
.
expr
.
right
->
u
.
column
),
jv
->
right_key
);
return
ERROR_SUCCESS
;
}
UINT
JOIN_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
left
,
LPCWSTR
right
,
struct
expr
*
cond
)
LPCWSTR
left
,
LPCWSTR
right
)
{
MSIJOINVIEW
*
jv
=
NULL
;
UINT
r
=
ERROR_SUCCESS
;
...
...
@@ -427,13 +300,6 @@ UINT JOIN_CreateView( MSIDATABASE *db, MSIVIEW **view,
goto
end
;
}
r
=
join_check_condition
(
jv
,
cond
);
if
(
r
!=
ERROR_SUCCESS
)
{
ERR
(
"can't get join condition
\n
"
);
goto
end
;
}
*
view
=
&
jv
->
view
;
return
ERROR_SUCCESS
;
...
...
dlls/msi/query.h
View file @
c6124db9
...
...
@@ -118,8 +118,7 @@ UINT UPDATE_CreateView( MSIDATABASE *db, MSIVIEW **, LPWSTR table,
UINT
DELETE_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
MSIVIEW
*
table
);
UINT
JOIN_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
left
,
LPCWSTR
right
,
struct
expr
*
cond
);
LPCWSTR
left
,
LPCWSTR
right
);
UINT
ALTER_CreateView
(
MSIDATABASE
*
db
,
MSIVIEW
**
view
,
LPCWSTR
name
,
int
hold
);
...
...
dlls/msi/sql.y
View file @
c6124db9
...
...
@@ -103,7 +103,7 @@ static struct expr * EXPR_wildcard( void *info );
%type <string> table id
%type <column_list> selcollist column column_and_type column_def table_def
%type <column_list> column_assignment update_assign_list constlist
%type <query> query
multifrom
from fromtable selectfrom unorderedsel
%type <query> query from fromtable selectfrom unorderedsel
%type <query> oneupdate onedelete oneselect onequery onecreate oneinsert onealter
%type <expr> expr val column_val const_val
%type <column_type> column_type data_type data_type_l data_count
...
...
@@ -384,7 +384,7 @@ unorderedsel:
;
selectfrom:
selcollist
multi
from
selcollist from
{
SQL_input* sql = (SQL_input*) info;
UINT r;
...
...
@@ -416,20 +416,6 @@ selcollist:
}
;
multifrom:
from
| TK_FROM table TK_COMMA table TK_WHERE expr
{
SQL_input* sql = (SQL_input*) info;
UINT r;
/* only support inner joins on two tables */
r = JOIN_CreateView( sql->db, &$$, $2, $4, $6 );
if( r != ERROR_SUCCESS )
YYABORT;
}
;
from:
fromtable
| fromtable TK_WHERE expr
...
...
@@ -458,6 +444,16 @@ fromtable:
if( r != ERROR_SUCCESS || !$$ )
YYABORT;
}
| TK_FROM table TK_COMMA table
{
SQL_input* sql = (SQL_input*) info;
UINT r;
/* only support inner joins on two tables */
r = JOIN_CreateView( sql->db, &$$, $2, $4 );
if( r != ERROR_SUCCESS )
YYABORT;
}
;
expr:
...
...
dlls/msi/tests/db.c
View file @
c6124db9
...
...
@@ -2221,7 +2221,6 @@ static void test_join(void)
}
ok
(
i
==
5
,
"Expected 5 rows, got %d
\n
"
,
i
);
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
MsiViewClose
(
hview
);
...
...
@@ -2231,16 +2230,10 @@ static void test_join(void)
"WHERE FeatureComponents.Component_=Component.Component "
"AND (Feature_='nasalis') ORDER BY Feature_"
;
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to open view: %d
\n
"
,
r
);
}
r
=
MsiViewExecute
(
hview
,
0
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to execute view: %d
\n
"
,
r
);
}
i
=
0
;
data_correct
=
TRUE
;
...
...
@@ -2267,15 +2260,8 @@ static void test_join(void)
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
todo_wine
{
ok
(
i
==
2
,
"Expected 2 rows, got %d
\n
"
,
i
);
}
todo_wine
{
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
}
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
...
...
@@ -2356,7 +2342,6 @@ static void test_join(void)
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
ok
(
i
==
1
,
"Expected 1 rows, got %d
\n
"
,
i
);
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
MsiViewClose
(
hview
);
...
...
@@ -2368,16 +2353,10 @@ static void test_join(void)
"AND `FeatureComponents`.`Component_` = 'maxilla' "
"ORDER BY `Feature_`"
;
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to open view: %d
\n
"
,
r
);
}
r
=
MsiViewExecute
(
hview
,
0
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to execute view: %d
\n
"
,
r
);
}
i
=
0
;
data_correct
=
TRUE
;
...
...
@@ -2401,17 +2380,10 @@ static void test_join(void)
i
++
;
MsiCloseHandle
(
hrec
);
}
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
todo_wine
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
todo_wine
{
ok
(
i
==
1
,
"Expected 1 rows, got %d
\n
"
,
i
);
}
todo_wine
{
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
}
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
...
...
@@ -2421,10 +2393,7 @@ static void test_join(void)
"WHERE `Component` = 'zygomatic' "
"ORDER BY `Feature_`"
;
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to open view: %d
\n
"
,
r
);
}
r
=
MsiViewExecute
(
hview
,
0
);
todo_wine
...
...
@@ -2460,11 +2429,7 @@ static void test_join(void)
{
ok
(
i
==
6
,
"Expected 6 rows, got %d
\n
"
,
i
);
}
todo_wine
{
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
}
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
...
...
@@ -2475,16 +2440,10 @@ static void test_join(void)
"AND `Feature_` = 'nasalis' "
"ORDER BY `Feature_`"
;
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to open view: %d
\n
"
,
r
);
}
r
=
MsiViewExecute
(
hview
,
0
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to execute view: %d
\n
"
,
r
);
}
i
=
0
;
data_correct
=
TRUE
;
...
...
@@ -2510,15 +2469,8 @@ static void test_join(void)
}
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
todo_wine
{
ok
(
i
==
3
,
"Expected 3 rows, got %d
\n
"
,
i
);
}
todo_wine
{
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
}
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
...
...
@@ -2526,16 +2478,10 @@ static void test_join(void)
query
=
"SELECT `StdDlls`.`File`, `Binary`.`Data` "
"FROM `StdDlls`, `Binary` "
;
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to open view: %d
\n
"
,
r
);
}
r
=
MsiViewExecute
(
hview
,
0
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to execute view: %d
\n
"
,
r
);
}
i
=
0
;
data_correct
=
TRUE
;
...
...
@@ -2560,28 +2506,19 @@ static void test_join(void)
MsiCloseHandle
(
hrec
);
}
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
todo_wine
{
todo_wine
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
ok
(
i
==
6
,
"Expected 6 rows, got %d
\n
"
,
i
);
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
}
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
query
=
"SELECT * FROM `StdDlls`, `Binary` "
;
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to open view: %d
\n
"
,
r
);
}
r
=
MsiViewExecute
(
hview
,
0
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"failed to execute view: %d
\n
"
,
r
);
}
i
=
0
;
data_correct
=
TRUE
;
...
...
@@ -2617,13 +2554,10 @@ static void test_join(void)
i
++
;
MsiCloseHandle
(
hrec
);
}
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
todo_wine
ok
(
data_correct
,
"data returned in the wrong order
\n
"
);
todo_wine
{
ok
(
i
==
6
,
"Expected 6 rows, got %d
\n
"
,
i
);
ok
(
r
==
ERROR_NO_MORE_ITEMS
,
"expected no more items: %d
\n
"
,
r
);
}
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
...
...
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