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
f03889ae
Commit
f03889ae
authored
Oct 08, 2008
by
James Hawkins
Committed by
Alexandre Julliard
Oct 09, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
msi: Add initial implementation of MsiDatabaseMerge, with tests.
parent
c9ec69db
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1014 additions
and
5 deletions
+1014
-5
database.c
dlls/msi/database.c
+495
-2
msipriv.h
dlls/msi/msipriv.h
+2
-0
record.c
dlls/msi/record.c
+71
-0
db.c
dlls/msi/tests/db.c
+446
-3
No files found.
dlls/msi/database.c
View file @
f03889ae
...
...
@@ -35,6 +35,7 @@
#include "objidl.h"
#include "objbase.h"
#include "msiserver.h"
#include "query.h"
#include "initguid.h"
...
...
@@ -999,13 +1000,505 @@ UINT WINAPI MsiDatabaseMergeA(MSIHANDLE hDatabase, MSIHANDLE hDatabaseMerge,
return
r
;
}
typedef
struct
_tagMERGETABLE
{
struct
list
entry
;
struct
list
rows
;
LPWSTR
name
;
DWORD
numconflicts
;
}
MERGETABLE
;
typedef
struct
_tagMERGEROW
{
struct
list
entry
;
MSIRECORD
*
data
;
}
MERGEROW
;
typedef
struct
_tagMERGEDATA
{
MSIDATABASE
*
db
;
MSIDATABASE
*
merge
;
MERGETABLE
*
curtable
;
MSIQUERY
*
curview
;
struct
list
*
tabledata
;
}
MERGEDATA
;
static
UINT
merge_verify_colnames
(
MSIQUERY
*
dbview
,
MSIQUERY
*
mergeview
)
{
MSIRECORD
*
dbrec
,
*
mergerec
;
UINT
r
,
i
,
count
;
r
=
MSI_ViewGetColumnInfo
(
dbview
,
MSICOLINFO_NAMES
,
&
dbrec
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
MSI_ViewGetColumnInfo
(
mergeview
,
MSICOLINFO_NAMES
,
&
mergerec
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
count
=
MSI_RecordGetFieldCount
(
dbrec
);
for
(
i
=
1
;
i
<=
count
;
i
++
)
{
if
(
!
MSI_RecordGetString
(
mergerec
,
i
))
break
;
if
(
lstrcmpW
(
MSI_RecordGetString
(
dbrec
,
i
),
MSI_RecordGetString
(
mergerec
,
i
)))
{
r
=
ERROR_DATATYPE_MISMATCH
;
goto
done
;
}
}
msiobj_release
(
&
dbrec
->
hdr
);
msiobj_release
(
&
mergerec
->
hdr
);
dbrec
=
mergerec
=
NULL
;
r
=
MSI_ViewGetColumnInfo
(
dbview
,
MSICOLINFO_TYPES
,
&
dbrec
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
MSI_ViewGetColumnInfo
(
mergeview
,
MSICOLINFO_TYPES
,
&
mergerec
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
count
=
MSI_RecordGetFieldCount
(
dbrec
);
for
(
i
=
1
;
i
<=
count
;
i
++
)
{
if
(
!
MSI_RecordGetString
(
mergerec
,
i
))
break
;
if
(
lstrcmpW
(
MSI_RecordGetString
(
dbrec
,
i
),
MSI_RecordGetString
(
mergerec
,
i
)))
{
r
=
ERROR_DATATYPE_MISMATCH
;
break
;
}
}
done:
msiobj_release
(
&
dbrec
->
hdr
);
msiobj_release
(
&
mergerec
->
hdr
);
return
r
;
}
static
UINT
merge_verify_primary_keys
(
MSIDATABASE
*
db
,
MSIDATABASE
*
mergedb
,
LPCWSTR
table
)
{
MSIRECORD
*
dbrec
,
*
mergerec
=
NULL
;
UINT
r
,
i
,
count
;
r
=
MSI_DatabaseGetPrimaryKeys
(
db
,
table
,
&
dbrec
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
MSI_DatabaseGetPrimaryKeys
(
mergedb
,
table
,
&
mergerec
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
count
=
MSI_RecordGetFieldCount
(
dbrec
);
if
(
count
!=
MSI_RecordGetFieldCount
(
mergerec
))
{
r
=
ERROR_DATATYPE_MISMATCH
;
goto
done
;
}
for
(
i
=
1
;
i
<=
count
;
i
++
)
{
if
(
lstrcmpW
(
MSI_RecordGetString
(
dbrec
,
i
),
MSI_RecordGetString
(
mergerec
,
i
)))
{
r
=
ERROR_DATATYPE_MISMATCH
;
goto
done
;
}
}
done:
msiobj_release
(
&
dbrec
->
hdr
);
msiobj_release
(
&
mergerec
->
hdr
);
return
r
;
}
static
LPWSTR
get_key_value
(
MSIQUERY
*
view
,
LPCWSTR
key
,
MSIRECORD
*
rec
)
{
MSIRECORD
*
colnames
;
LPWSTR
str
;
UINT
r
,
i
=
0
;
int
cmp
;
r
=
MSI_ViewGetColumnInfo
(
view
,
MSICOLINFO_NAMES
,
&
colnames
);
if
(
r
!=
ERROR_SUCCESS
)
return
NULL
;
do
{
str
=
msi_dup_record_field
(
colnames
,
++
i
);
cmp
=
lstrcmpW
(
key
,
str
);
msi_free
(
str
);
}
while
(
cmp
);
msiobj_release
(
&
colnames
->
hdr
);
return
msi_dup_record_field
(
rec
,
i
);
}
static
LPWSTR
create_diff_row_query
(
MSIDATABASE
*
merge
,
MSIQUERY
*
view
,
LPWSTR
table
,
MSIRECORD
*
rec
)
{
LPWSTR
query
=
NULL
,
clause
=
NULL
;
LPWSTR
ptr
=
NULL
,
val
;
LPCWSTR
setptr
;
DWORD
size
=
1
,
oldsize
;
LPCWSTR
key
;
MSIRECORD
*
keys
;
UINT
r
,
i
,
count
;
static
const
WCHAR
keyset
[]
=
{
'`'
,
'%'
,
's'
,
'`'
,
' '
,
'='
,
' '
,
'%'
,
's'
,
' '
,
'A'
,
'N'
,
'D'
,
' '
,
0
};
static
const
WCHAR
lastkeyset
[]
=
{
'`'
,
'%'
,
's'
,
'`'
,
' '
,
'='
,
' '
,
'%'
,
's'
,
' '
,
0
};
static
const
WCHAR
fmt
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'%'
,
's'
,
'`'
,
' '
,
'W'
,
'H'
,
'E'
,
'R'
,
'E'
,
' '
,
'%'
,
's'
,
0
};
r
=
MSI_DatabaseGetPrimaryKeys
(
merge
,
table
,
&
keys
);
if
(
r
!=
ERROR_SUCCESS
)
return
NULL
;
clause
=
msi_alloc_zero
(
size
*
sizeof
(
WCHAR
));
if
(
!
clause
)
goto
done
;
ptr
=
clause
;
count
=
MSI_RecordGetFieldCount
(
keys
);
for
(
i
=
1
;
i
<=
count
;
i
++
)
{
key
=
MSI_RecordGetString
(
keys
,
i
);
val
=
get_key_value
(
view
,
key
,
rec
);
if
(
i
==
count
)
setptr
=
lastkeyset
;
else
setptr
=
keyset
;
oldsize
=
size
;
size
+=
lstrlenW
(
setptr
)
+
lstrlenW
(
key
)
+
lstrlenW
(
val
)
-
4
;
clause
=
msi_realloc
(
clause
,
size
*
sizeof
(
WCHAR
));
if
(
!
clause
)
{
msi_free
(
val
);
goto
done
;
}
ptr
=
clause
+
oldsize
-
1
;
sprintfW
(
ptr
,
setptr
,
key
,
val
);
msi_free
(
val
);
}
size
=
lstrlenW
(
fmt
)
+
lstrlenW
(
table
)
+
lstrlenW
(
clause
)
+
1
;
query
=
msi_alloc
(
size
*
sizeof
(
WCHAR
));
if
(
!
query
)
goto
done
;
sprintfW
(
query
,
fmt
,
table
,
clause
);
done:
msi_free
(
clause
);
msiobj_release
(
&
keys
->
hdr
);
return
query
;
}
static
UINT
merge_diff_row
(
MSIRECORD
*
rec
,
LPVOID
param
)
{
MERGEDATA
*
data
=
(
MERGEDATA
*
)
param
;
MERGETABLE
*
table
=
data
->
curtable
;
MERGEROW
*
mergerow
;
MSIQUERY
*
dbview
;
MSIRECORD
*
row
;
LPWSTR
query
;
UINT
r
;
query
=
create_diff_row_query
(
data
->
merge
,
data
->
curview
,
table
->
name
,
rec
);
if
(
!
query
)
return
ERROR_OUTOFMEMORY
;
r
=
MSI_DatabaseOpenViewW
(
data
->
db
,
query
,
&
dbview
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
r
=
MSI_ViewExecute
(
dbview
,
NULL
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
r
=
MSI_ViewFetch
(
dbview
,
&
row
);
if
(
r
==
ERROR_SUCCESS
&&
!
MSI_RecordsAreEqual
(
rec
,
row
))
{
table
->
numconflicts
++
;
goto
done
;
}
else
if
(
r
!=
ERROR_NO_MORE_ITEMS
)
goto
done
;
mergerow
=
msi_alloc
(
sizeof
(
MERGEROW
));
if
(
!
mergerow
)
{
r
=
ERROR_OUTOFMEMORY
;
goto
done
;
}
mergerow
->
data
=
MSI_CloneRecord
(
rec
);
if
(
!
mergerow
->
data
)
{
r
=
ERROR_OUTOFMEMORY
;
msi_free
(
mergerow
);
goto
done
;
}
list_add_tail
(
&
table
->
rows
,
&
mergerow
->
entry
);
done:
msi_free
(
query
);
msiobj_release
(
&
row
->
hdr
);
msiobj_release
(
&
dbview
->
hdr
);
return
r
;
}
static
UINT
merge_diff_tables
(
MSIRECORD
*
rec
,
LPVOID
param
)
{
MERGEDATA
*
data
=
(
MERGEDATA
*
)
param
;
MERGETABLE
*
table
;
MSIQUERY
*
dbview
=
NULL
;
MSIQUERY
*
mergeview
=
NULL
;
LPCWSTR
name
;
LPWSTR
query
;
DWORD
size
;
UINT
r
;
static
const
WCHAR
fmt
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'%'
,
's'
,
'`'
,
0
};
name
=
MSI_RecordGetString
(
rec
,
1
);
size
=
lstrlenW
(
fmt
)
+
lstrlenW
(
name
)
-
1
;
query
=
msi_alloc
(
size
*
sizeof
(
WCHAR
));
if
(
!
query
)
return
ERROR_OUTOFMEMORY
;
sprintfW
(
query
,
fmt
,
name
);
r
=
MSI_DatabaseOpenViewW
(
data
->
db
,
query
,
&
dbview
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
r
=
MSI_DatabaseOpenViewW
(
data
->
merge
,
query
,
&
mergeview
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
r
=
merge_verify_colnames
(
dbview
,
mergeview
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
r
=
merge_verify_primary_keys
(
data
->
db
,
data
->
merge
,
name
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
table
=
msi_alloc
(
sizeof
(
MERGETABLE
));
if
(
!
table
)
{
r
=
ERROR_OUTOFMEMORY
;
goto
done
;
}
list_init
(
&
table
->
rows
);
table
->
name
=
strdupW
(
name
);
table
->
numconflicts
=
0
;
data
->
curtable
=
table
;
data
->
curview
=
mergeview
;
r
=
MSI_IterateRecords
(
mergeview
,
NULL
,
merge_diff_row
,
data
);
if
(
r
!=
ERROR_SUCCESS
)
{
msi_free
(
table
->
name
);
msi_free
(
table
);
goto
done
;
}
list_add_tail
(
data
->
tabledata
,
&
table
->
entry
);
done:
msi_free
(
query
);
msiobj_release
(
&
dbview
->
hdr
);
msiobj_release
(
&
mergeview
->
hdr
);
return
r
;
}
static
UINT
gather_merge_data
(
MSIDATABASE
*
db
,
MSIDATABASE
*
merge
,
struct
list
*
tabledata
)
{
UINT
r
;
MSIQUERY
*
view
;
MERGEDATA
data
;
static
const
WCHAR
query
[]
=
{
'S'
,
'E'
,
'L'
,
'E'
,
'C'
,
'T'
,
' '
,
'*'
,
' '
,
'F'
,
'R'
,
'O'
,
'M'
,
' '
,
'`'
,
'_'
,
'T'
,
'a'
,
'b'
,
'l'
,
'e'
,
's'
,
'`'
,
0
};
r
=
MSI_DatabaseOpenViewW
(
merge
,
query
,
&
view
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
data
.
db
=
db
;
data
.
merge
=
merge
;
data
.
tabledata
=
tabledata
;
r
=
MSI_IterateRecords
(
view
,
NULL
,
merge_diff_tables
,
&
data
);
msiobj_release
(
&
view
->
hdr
);
return
r
;
}
static
UINT
merge_table
(
MSIDATABASE
*
db
,
MERGETABLE
*
table
)
{
UINT
r
;
MERGEROW
*
row
;
MSIVIEW
*
tv
;
LIST_FOR_EACH_ENTRY
(
row
,
&
table
->
rows
,
MERGEROW
,
entry
)
{
r
=
TABLE_CreateView
(
db
,
table
->
name
,
&
tv
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
tv
->
ops
->
insert_row
(
tv
,
row
->
data
,
FALSE
);
tv
->
ops
->
delete
(
tv
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
}
return
ERROR_SUCCESS
;
}
static
UINT
update_merge_errors
(
MSIDATABASE
*
db
,
LPCWSTR
error
,
LPWSTR
table
,
DWORD
numconflicts
)
{
UINT
r
;
MSIQUERY
*
view
;
static
const
WCHAR
create
[]
=
{
'C'
,
'R'
,
'E'
,
'A'
,
'T'
,
'E'
,
' '
,
'T'
,
'A'
,
'B'
,
'L'
,
'E'
,
' '
,
'`'
,
'%'
,
's'
,
'`'
,
' '
,
'('
,
'`'
,
'T'
,
'a'
,
'b'
,
'l'
,
'e'
,
'`'
,
' '
,
'C'
,
'H'
,
'A'
,
'R'
,
'('
,
'2'
,
'5'
,
'5'
,
')'
,
' '
,
'N'
,
'O'
,
'T'
,
' '
,
'N'
,
'U'
,
'L'
,
'L'
,
','
,
' '
,
'`'
,
'N'
,
'u'
,
'm'
,
'R'
,
'o'
,
'w'
,
'M'
,
'e'
,
'r'
,
'g'
,
'e'
,
'C'
,
'o'
,
'n'
,
'f'
,
'l'
,
'i'
,
'c'
,
't'
,
's'
,
'`'
,
' '
,
'S'
,
'H'
,
'O'
,
'R'
,
'T'
,
' '
,
'N'
,
'O'
,
'T'
,
' '
,
'N'
,
'U'
,
'L'
,
'L'
,
' '
,
'P'
,
'R'
,
'I'
,
'M'
,
'A'
,
'R'
,
'Y'
,
' '
,
'K'
,
'E'
,
'Y'
,
' '
,
'`'
,
'T'
,
'a'
,
'b'
,
'l'
,
'e'
,
'`'
,
')'
,
0
};
static
const
WCHAR
insert
[]
=
{
'I'
,
'N'
,
'S'
,
'E'
,
'R'
,
'T'
,
' '
,
'I'
,
'N'
,
'T'
,
'O'
,
' '
,
'`'
,
'%'
,
's'
,
'`'
,
' '
,
'('
,
'`'
,
'T'
,
'a'
,
'b'
,
'l'
,
'e'
,
'`'
,
','
,
' '
,
'`'
,
'N'
,
'u'
,
'm'
,
'R'
,
'o'
,
'w'
,
'M'
,
'e'
,
'r'
,
'g'
,
'e'
,
'C'
,
'o'
,
'n'
,
'f'
,
'l'
,
'i'
,
'c'
,
't'
,
's'
,
'`'
,
')'
,
' '
,
'V'
,
'A'
,
'L'
,
'U'
,
'E'
,
'S'
,
' '
,
'('
,
'\''
,
'%'
,
's'
,
'\''
,
','
,
' '
,
'%'
,
'd'
,
')'
,
0
};
if
(
!
TABLE_Exists
(
db
,
error
))
{
r
=
MSI_OpenQuery
(
db
,
&
view
,
create
,
error
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
MSI_ViewExecute
(
view
,
NULL
);
msiobj_release
(
&
view
->
hdr
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
}
r
=
MSI_OpenQuery
(
db
,
&
view
,
insert
,
error
,
table
,
numconflicts
);
if
(
r
!=
ERROR_SUCCESS
)
return
r
;
r
=
MSI_ViewExecute
(
view
,
NULL
);
msiobj_release
(
&
view
->
hdr
);
return
r
;
}
static
void
merge_free_rows
(
MERGETABLE
*
table
)
{
struct
list
*
item
,
*
cursor
;
LIST_FOR_EACH_SAFE
(
item
,
cursor
,
&
table
->
rows
)
{
MERGEROW
*
row
=
LIST_ENTRY
(
item
,
MERGEROW
,
entry
);
list_remove
(
&
row
->
entry
);
merge_free_rows
(
table
);
msiobj_release
(
&
row
->
data
->
hdr
);
msi_free
(
row
);
}
}
UINT
WINAPI
MsiDatabaseMergeW
(
MSIHANDLE
hDatabase
,
MSIHANDLE
hDatabaseMerge
,
LPCWSTR
szTableName
)
{
FIXME
(
"(%ld, %ld, %s): stub!
\n
"
,
hDatabase
,
hDatabaseMerge
,
struct
list
tabledata
=
LIST_INIT
(
tabledata
);
struct
list
*
item
,
*
cursor
;
MSIDATABASE
*
db
,
*
merge
;
MERGETABLE
*
table
;
BOOL
conflicts
;
UINT
r
;
TRACE
(
"(%ld, %ld, %s)
\n
"
,
hDatabase
,
hDatabaseMerge
,
debugstr_w
(
szTableName
));
return
ERROR_CALL_NOT_IMPLEMENTED
;
if
(
szTableName
&&
!*
szTableName
)
return
ERROR_INVALID_TABLE
;
db
=
msihandle2msiinfo
(
hDatabase
,
MSIHANDLETYPE_DATABASE
);
merge
=
msihandle2msiinfo
(
hDatabaseMerge
,
MSIHANDLETYPE_DATABASE
);
if
(
!
db
||
!
merge
)
{
r
=
ERROR_INVALID_HANDLE
;
goto
done
;
}
r
=
gather_merge_data
(
db
,
merge
,
&
tabledata
);
if
(
r
!=
ERROR_SUCCESS
)
goto
done
;
conflicts
=
FALSE
;
LIST_FOR_EACH_ENTRY
(
table
,
&
tabledata
,
MERGETABLE
,
entry
)
{
if
(
table
->
numconflicts
)
{
conflicts
=
TRUE
;
r
=
update_merge_errors
(
db
,
szTableName
,
table
->
name
,
table
->
numconflicts
);
if
(
r
!=
ERROR_SUCCESS
)
break
;
}
else
{
r
=
merge_table
(
db
,
table
);
if
(
r
!=
ERROR_SUCCESS
)
break
;
}
}
LIST_FOR_EACH_SAFE
(
item
,
cursor
,
&
tabledata
)
{
MERGETABLE
*
table
=
LIST_ENTRY
(
item
,
MERGETABLE
,
entry
);
list_remove
(
&
table
->
entry
);
merge_free_rows
(
table
);
msi_free
(
table
->
name
);
msi_free
(
table
);
}
if
(
conflicts
)
r
=
ERROR_FUNCTION_FAILED
;
done:
msiobj_release
(
&
db
->
hdr
);
msiobj_release
(
&
merge
->
hdr
);
return
r
;
}
MSIDBSTATE
WINAPI
MsiGetDatabaseState
(
MSIHANDLE
handle
)
...
...
dlls/msi/msipriv.h
View file @
f03889ae
...
...
@@ -703,6 +703,8 @@ extern UINT MSI_RecordSetStream( MSIRECORD *, UINT, IStream * );
extern
UINT
MSI_RecordDataSize
(
MSIRECORD
*
,
UINT
);
extern
UINT
MSI_RecordStreamToFile
(
MSIRECORD
*
,
UINT
,
LPCWSTR
);
extern
UINT
MSI_RecordCopyField
(
MSIRECORD
*
,
UINT
,
MSIRECORD
*
,
UINT
);
extern
MSIRECORD
*
MSI_CloneRecord
(
MSIRECORD
*
);
extern
BOOL
MSI_RecordsAreEqual
(
MSIRECORD
*
,
MSIRECORD
*
);
/* stream internals */
extern
UINT
get_raw_stream
(
MSIHANDLE
hdb
,
LPCWSTR
stname
,
IStream
**
stm
);
...
...
dlls/msi/record.c
View file @
f03889ae
...
...
@@ -903,3 +903,74 @@ UINT MSI_RecordStreamToFile( MSIRECORD *rec, UINT iField, LPCWSTR name )
return
r
;
}
MSIRECORD
*
MSI_CloneRecord
(
MSIRECORD
*
rec
)
{
MSIRECORD
*
clone
;
UINT
r
,
i
,
count
;
count
=
MSI_RecordGetFieldCount
(
rec
);
clone
=
MSI_CreateRecord
(
count
);
if
(
!
clone
)
return
NULL
;
for
(
i
=
0
;
i
<=
count
;
i
++
)
{
if
(
rec
->
fields
[
i
].
type
==
MSIFIELD_STREAM
)
{
if
(
FAILED
(
IStream_Clone
(
rec
->
fields
[
i
].
u
.
stream
,
&
clone
->
fields
[
i
].
u
.
stream
)))
{
msiobj_release
(
&
clone
->
hdr
);
return
NULL
;
}
}
else
{
r
=
MSI_RecordCopyField
(
rec
,
i
,
clone
,
i
);
if
(
r
!=
ERROR_SUCCESS
)
{
msiobj_release
(
&
clone
->
hdr
);
return
NULL
;
}
}
}
return
clone
;
}
BOOL
MSI_RecordsAreEqual
(
MSIRECORD
*
a
,
MSIRECORD
*
b
)
{
UINT
i
;
if
(
a
->
count
!=
b
->
count
)
return
FALSE
;
for
(
i
=
0
;
i
<=
a
->
count
;
i
++
)
{
if
(
a
->
fields
[
i
].
type
!=
b
->
fields
[
i
].
type
)
return
FALSE
;
switch
(
a
->
fields
[
i
].
type
)
{
case
MSIFIELD_NULL
:
break
;
case
MSIFIELD_INT
:
if
(
a
->
fields
[
i
].
u
.
iVal
!=
b
->
fields
[
i
].
u
.
iVal
)
return
FALSE
;
break
;
case
MSIFIELD_WSTR
:
if
(
lstrcmpW
(
a
->
fields
[
i
].
u
.
szwVal
,
b
->
fields
[
i
].
u
.
szwVal
))
return
FALSE
;
break
;
case
MSIFIELD_STREAM
:
default:
return
FALSE
;
}
}
return
TRUE
;
}
dlls/msi/tests/db.c
View file @
f03889ae
...
...
@@ -144,6 +144,9 @@ static UINT do_query(MSIHANDLE hdb, const char *query, MSIHANDLE *phrec)
MSIHANDLE
hview
=
0
;
UINT
r
,
ret
;
if
(
phrec
)
*
phrec
=
0
;
/* open a select query */
r
=
MsiDatabaseOpenView
(
hdb
,
query
,
&
hview
);
if
(
r
!=
ERROR_SUCCESS
)
...
...
@@ -1382,17 +1385,28 @@ static void test_longstrings(void)
DeleteFile
(
msifile
);
}
static
void
create_file
(
const
CHAR
*
nam
e
)
static
void
create_file
_data
(
LPCSTR
name
,
LPCSTR
data
,
DWORD
siz
e
)
{
HANDLE
file
;
DWORD
written
;
file
=
CreateFileA
(
name
,
GENERIC_WRITE
,
0
,
NULL
,
CREATE_ALWAYS
,
0
,
NULL
);
ok
(
file
!=
INVALID_HANDLE_VALUE
,
"Failure to open file %s
\n
"
,
name
);
WriteFile
(
file
,
name
,
strlen
(
name
),
&
written
,
NULL
);
if
(
file
==
INVALID_HANDLE_VALUE
)
return
;
WriteFile
(
file
,
data
,
strlen
(
data
),
&
written
,
NULL
);
WriteFile
(
file
,
"
\n
"
,
strlen
(
"
\n
"
),
&
written
,
NULL
);
if
(
size
)
{
SetFilePointer
(
file
,
size
,
NULL
,
FILE_BEGIN
);
SetEndOfFile
(
file
);
}
CloseHandle
(
file
);
}
#define create_file(name) create_file_data(name, name, 0)
static
void
test_streamtable
(
void
)
{
...
...
@@ -6532,6 +6546,434 @@ static void test_droptable(void)
DeleteFileA
(
msifile
);
}
static
void
test_dbmerge
(
void
)
{
MSIHANDLE
hdb
,
href
,
hview
,
hrec
;
CHAR
buf
[
MAX_PATH
];
LPCSTR
query
;
DWORD
size
;
UINT
r
;
r
=
MsiOpenDatabase
(
msifile
,
MSIDBOPEN_CREATE
,
&
hdb
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiOpenDatabase
(
"refdb.msi"
,
MSIDBOPEN_CREATE
,
&
href
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* hDatabase is invalid */
r
=
MsiDatabaseMergeA
(
0
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_INVALID_HANDLE
,
"Expected ERROR_INVALID_HANDLE, got %d
\n
"
,
r
);
/* hDatabaseMerge is invalid */
r
=
MsiDatabaseMergeA
(
hdb
,
0
,
"MergeErrors"
);
ok
(
r
==
ERROR_INVALID_HANDLE
,
"Expected ERROR_INVALID_HANDLE, got %d
\n
"
,
r
);
/* szTableName is NULL */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
NULL
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* szTableName is empty */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
""
);
ok
(
r
==
ERROR_INVALID_TABLE
,
"Expected ERROR_INVALID_TABLE, got %d
\n
"
,
r
);
/* both DBs empty, szTableName is valid */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
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
=
"CREATE TABLE `One` ( `A` CHAR(72) PRIMARY KEY `A` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* column types don't match */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_DATATYPE_MISMATCH
,
"Expected ERROR_DATATYPE_MISMATCH, got %d
\n
"
,
r
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, 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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `C` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* column names don't match */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_DATATYPE_MISMATCH
,
"Expected ERROR_DATATYPE_MISMATCH, got %d
\n
"
,
r
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, 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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `B` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* primary keys don't match */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_DATATYPE_MISMATCH
,
"Expected ERROR_DATATYPE_MISMATCH, got %d
\n
"
,
r
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, 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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A`, `B` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* number of primary keys doesn't match */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_DATATYPE_MISMATCH
,
"Expected ERROR_DATATYPE_MISMATCH, got %d
\n
"
,
r
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, 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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* number of columns doesn't match */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `One`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
1
);
ok
(
r
==
1
,
"Expected 1, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
2
);
ok
(
r
==
2
,
"Expected 2, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
3
);
ok
(
r
==
MSI_NULL_INTEGER
,
"Expected MSI_NULL_INTEGER, got %d
\n
"
,
r
);
MsiCloseHandle
(
hrec
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, 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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT, `C` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"INSERT INTO `One` ( `A`, `B`, `C` ) VALUES ( 1, 2, 3 )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* number of columns doesn't match */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `One`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
1
);
ok
(
r
==
1
,
"Expected 1, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
2
);
ok
(
r
==
2
,
"Expected 2, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
3
);
ok
(
r
==
MSI_NULL_INTEGER
,
"Expected MSI_NULL_INTEGER, got %d
\n
"
,
r
);
MsiCloseHandle
(
hrec
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, 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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 1 )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 2 )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` INT PRIMARY KEY `A` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 2 )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"INSERT INTO `One` ( `A`, `B` ) VALUES ( 2, 3 )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* primary keys match, rows do not */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_FUNCTION_FAILED
,
"Expected ERROR_FUNCTION_FAILED, got %d
\n
"
,
r
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
size
=
MAX_PATH
;
r
=
MsiRecordGetStringA
(
hrec
,
1
,
buf
,
&
size
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
ok
(
!
lstrcmpA
(
buf
,
"One"
),
"Expected
\"
One
\"
, got
\"
%s
\"\n
"
,
buf
);
r
=
MsiRecordGetInteger
(
hrec
,
2
);
ok
(
r
==
2
,
"Expected 2, got %d
\n
"
,
r
);
MsiCloseHandle
(
hrec
);
r
=
MsiDatabaseOpenViewA
(
hdb
,
"SELECT * FROM `MergeErrors`"
,
&
hview
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiViewGetColumnInfo
(
hview
,
MSICOLINFO_NAMES
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
size
=
MAX_PATH
;
r
=
MsiRecordGetString
(
hrec
,
1
,
buf
,
&
size
);
ok
(
!
lstrcmpA
(
buf
,
"Table"
),
"Expected
\"
Table
\"
, got
\"
%s
\"\n
"
,
buf
);
size
=
MAX_PATH
;
r
=
MsiRecordGetString
(
hrec
,
2
,
buf
,
&
size
);
ok
(
!
lstrcmpA
(
buf
,
"NumRowMergeConflicts"
),
"Expected
\"
NumRowMergeConflicts
\"
, got
\"
%s
\"\n
"
,
buf
);
MsiCloseHandle
(
hrec
);
r
=
MsiViewGetColumnInfo
(
hview
,
MSICOLINFO_TYPES
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
size
=
MAX_PATH
;
r
=
MsiRecordGetString
(
hrec
,
1
,
buf
,
&
size
);
ok
(
!
lstrcmpA
(
buf
,
"s255"
),
"Expected
\"
s255
\"
, got
\"
%s
\"\n
"
,
buf
);
size
=
MAX_PATH
;
r
=
MsiRecordGetString
(
hrec
,
2
,
buf
,
&
size
);
ok
(
!
lstrcmpA
(
buf
,
"i2"
),
"Expected
\"
i2
\"
, got
\"
%s
\"\n
"
,
buf
);
MsiCloseHandle
(
hrec
);
MsiViewClose
(
hview
);
MsiCloseHandle
(
hview
);
query
=
"DROP TABLE `MergeErrors`"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
create_file_data
(
"codepage.idt"
,
"
\r\n\r\n
28603
\t
_ForceCodepage
\r\n
"
,
0
);
GetCurrentDirectoryA
(
MAX_PATH
,
buf
);
r
=
MsiDatabaseImportA
(
hdb
,
buf
,
"codepage.idt"
);
todo_wine
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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( "
"`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( "
"`A` INT, `B` CHAR(72) LOCALIZABLE PRIMARY KEY `A` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, 'hi' )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
/* code page does not match */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `One`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
1
);
ok
(
r
==
1
,
"Expected 1, got %d
\n
"
,
r
);
size
=
MAX_PATH
;
r
=
MsiRecordGetStringA
(
hrec
,
2
,
buf
,
&
size
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
ok
(
!
lstrcmpA
(
buf
,
"hi"
),
"Expected
\"
hi
\"
, got
\"
%s
\"\n
"
,
buf
);
MsiCloseHandle
(
hrec
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, 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
=
"DROP TABLE `One`"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )"
;
r
=
run_query
(
hdb
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"CREATE TABLE `One` ( `A` INT, `B` OBJECT PRIMARY KEY `A` )"
;
r
=
run_query
(
href
,
0
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
create_file
(
"binary.dat"
);
hrec
=
MsiCreateRecord
(
1
);
MsiRecordSetStreamA
(
hrec
,
1
,
"binary.dat"
);
query
=
"INSERT INTO `One` ( `A`, `B` ) VALUES ( 1, ? )"
;
r
=
run_query
(
href
,
hrec
,
query
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
MsiCloseHandle
(
hrec
);
/* binary data to merge */
r
=
MsiDatabaseMergeA
(
hdb
,
href
,
"MergeErrors"
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
query
=
"SELECT * FROM `One`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
r
=
MsiRecordGetInteger
(
hrec
,
1
);
ok
(
r
==
1
,
"Expected 1, got %d
\n
"
,
r
);
size
=
MAX_PATH
;
ZeroMemory
(
buf
,
MAX_PATH
);
r
=
MsiRecordReadStream
(
hrec
,
2
,
buf
,
&
size
);
todo_wine
{
ok
(
r
==
ERROR_SUCCESS
,
"Expected ERROR_SUCCESS, got %d
\n
"
,
r
);
ok
(
!
lstrcmpA
(
buf
,
"binary.dat
\n
"
),
"Expected
\"
binary.dat
\\
n
\"
, got
\"
%s
\"\n
"
,
buf
);
}
MsiCloseHandle
(
hrec
);
/* nothing in MergeErrors */
query
=
"SELECT * FROM `MergeErrors`"
;
r
=
do_query
(
hdb
,
query
,
&
hrec
);
ok
(
r
==
ERROR_BAD_QUERY_SYNTAX
,
"Expected ERROR_BAD_QUERY_SYNTAX, got %d
\n
"
,
r
);
MsiCloseHandle
(
hdb
);
MsiCloseHandle
(
href
);
DeleteFileA
(
msifile
);
DeleteFileA
(
"refdb.msi"
);
DeleteFileA
(
"codepage.idt"
);
}
START_TEST
(
db
)
{
test_msidatabase
();
...
...
@@ -6572,4 +7014,5 @@ START_TEST(db)
test_storages_table
();
test_dbtopackage
();
test_droptable
();
test_dbmerge
();
}
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