###############################################################################
#
# session.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################
package require Eagle
package require Eagle.Library
package require Eagle.Test
runTestPrologue
###############################################################################
package require System.Data.SQLite.Test
runSQLiteTestPrologue
###############################################################################
proc getSomeText { random count } {
set items [list \
Alpha Bravo Charlie Delta Echo Foxtrot Golf Hotel \
India Juliet Kilo Lima Mike November Oscar Papa \
Quebec Romeo Sierra Tango Uniform Victor Whiskey X-ray \
Yankee Zulu]
if {!$random} then {
variable some_text_index
if {![info exists some_text_index]} then {
set some_text_index 0
}
}
set length [llength $items]
set result [list]
for {set i 0} {$i < $count} {incr i} {
if {$random} then {
set item [lindex $items [expr {int(rand() * $length)}]]
} else {
set item [lindex $items $some_text_index]
incr some_text_index
if {$some_text_index >= $length} then {
set some_text_index 0
}
}
lappend result $item
}
return $result
}
###############################################################################
proc cleanupSomeText {} {
variable some_text_index
unset -nocomplain some_text_index
}
###############################################################################
proc forDisplay { object member } {
set isArray false
if {[isObjectHandle $object] && $object ne "null"} then {
set value [object invoke -create -- $object $member]
if {[isObjectHandle $value] && $value ne "null"} then {
set isArray [object invoke -- $value GetType.IsArray]
}
} else {
set value null
}
if {$isArray} then {
return [object invoke -flags +NonPublic \
-parametertypes Array System.Data.SQLite.HelperMethods \
ToDisplayString $value]
} else {
return [object invoke -flags +NonPublic \
System.Data.SQLite.HelperMethods ToDisplayString $value]
}
}
###############################################################################
proc changeSetToString { changeSet includeValues } {
set result [list]
object foreach -alias item $changeSet {
lappend result TableName [$item TableName]
lappend result NumberOfColumns [$item NumberOfColumns]
lappend result OperationCode [$item OperationCode]
lappend result Indirect [$item Indirect]
lappend result PrimaryKeyColumns \
[forDisplay $item PrimaryKeyColumns]
if {$includeValues} then {
set numberOfColumns [$item NumberOfColumns]
for {set index 0} {$index < $numberOfColumns} {incr index} {
set oldValue [$item GetOldValue $index]
lappend result OldValue $index \
[forDisplay $oldValue GetObject]
set newValue [$item GetNewValue $index]
lappend result NewValue $index \
[forDisplay $newValue GetObject]
set conflictValue [$item GetConflictValue $index]
lappend result ConflictValue $index \
[forDisplay $conflictValue GetObject]
}
}
}
return $result
}
###############################################################################
proc createTheSchema { db } {
sql execute $db {
CREATE TABLE t1(x INTEGER PRIMARY KEY, y TEXT);
}
}
###############################################################################
proc makeSomeChanges { db types random {count 5} } {
foreach type $types {
switch -nocase -- $type {
insert {
set text [appendArgs "inserted: " [getSomeText $random $count]]
sql execute $db {
INSERT INTO t1(y) VALUES(?);
} [list param1 String $text]
}
update {
set text [appendArgs "updated: " [getSomeText $random $count]]
sql execute $db {
UPDATE t1 SET y = ? WHERE x NOT IN (
(SELECT MIN(x) FROM t1), (SELECT MAX(x) FROM t1)
);
} [list param1 String $text]
}
delete {
sql execute $db {
DELETE FROM t1 WHERE x = (SELECT MIN(x) FROM t1);
}
}
}
}
}
###############################################################################
proc getChangeSetFileName { {suffix ""} } {
return [file join \
[getTemporaryDirectory] [appendArgs changes $suffix .bin]]
}
###############################################################################
proc arrayToList { varName } {
upvar 1 $varName array
if {![array exists array]} {
error [appendArgs \" $a "\" isn't an array"]
}
set result [list]
foreach name [lsort -integer [array names array]] {
lappend result $array($name)
}
return $result
}
###############################################################################
proc createByteArray { list } {
set length [llength $list]
set result [object create -alias System.Byte\[\] $length]
for {set index 0} {$index < $length} {incr index} {
set element [lindex $list $index]
set value [object invoke -create Byte Parse $element]
$result SetValue $value $index
}
return $result
}
###############################################################################
runTest {test session-1.1 {basic session extension usage} -setup {
setupDb [set fileName(0) session-1.1.db]
set fileName(1) [getChangeSetFileName 1]
set fileName(2) [getChangeSetFileName 2]
cleanupSomeText
} -body {
createTheSchema $db
makeSomeChanges $db [list insert] true
set connection [getDbConnection]
set session [$connection -alias CreateSession main]
$session AttachTable null
makeSomeChanges $db [list insert update delete] true
set byteArray null
set changeSet(1) [$session -alias CreateChangeSet byteArray]
set rawData [createByteArray [arrayToList byteArray]]
object removeref $rawData
set stream(1) [object create -alias \
System.IO.FileStream $fileName(1) Create Write]
$stream(1) Write $rawData 0 [$rawData Length]
$stream(1) Flush; $stream(1) Close
set stream(2) [object create -alias \
System.IO.FileStream $fileName(2) Create Write]
set changeSet(2) [$session -alias CreateChangeSet $stream(2)]
$stream(2) Flush; $stream(2) Close
list [expr {[file size $fileName(1)] > 0}] \
[string equal [readFile $fileName(1)] [readFile $fileName(2)]]
} -cleanup {
cleanupSomeText
unset -nocomplain changeSet stream rawData byteArray session
freeDbConnection
unset -nocomplain connection
cleanupFile $fileName(2)
cleanupFile $fileName(1)
cleanupDb $fileName(0)
unset -nocomplain db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite SQLiteInterop\
defineConstant.System.Data.SQLite.INTEROP_SESSION_EXTENSION} -result \
{True True}}
###############################################################################
runTest {test session-1.2 {session change set enumeration} -setup {
setupDb [set fileName session-1.2.db]
cleanupSomeText
} -body {
createTheSchema $db
makeSomeChanges $db [list insert insert insert] false
set connection [getDbConnection]
set session [$connection -alias CreateSession main]
$session AttachTable null
makeSomeChanges $db [list insert update delete] false
set byteArray null
set changeSet(1) [$session -alias CreateChangeSet byteArray]
set rawData [createByteArray [arrayToList byteArray]]
object removeref $rawData
set changeSet(2) [$connection -alias CreateChangeSet $rawData]
changeSetToString $changeSet(2) true
} -cleanup {
cleanupSomeText
unset -nocomplain oldValue newValue conflictValue
unset -nocomplain changeSet rawData byteArray session
freeDbConnection
unset -nocomplain connection
cleanupDb $fileName
unset -nocomplain db fileName
} -constraints {eagle command.object monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite SQLiteInterop\
defineConstant.System.Data.SQLite.INTEROP_SESSION_EXTENSION} -result {TableName\
t1 NumberOfColumns 2 OperationCode Delete Indirect False PrimaryKeyColumns\
{[True, False]} OldValue 0 1 NewValue 0 <nullObject> ConflictValue 0\
<nullObject> OldValue 1 {"inserted: Alpha Bravo Charlie Delta Echo"} NewValue 1\
<nullObject> ConflictValue 1 <nullObject> TableName t1 NumberOfColumns 2\
OperationCode Update Indirect False PrimaryKeyColumns {[True, False]} OldValue\
0 2 NewValue 0 <nullObject> ConflictValue 0 <nullObject> OldValue 1 {"inserted:\
Foxtrot Golf Hotel India Juliet"} NewValue 1 {"updated: Uniform Victor Whiskey\
X-ray Yankee"} ConflictValue 1 <nullObject> TableName t1 NumberOfColumns 2\
OperationCode Update Indirect False PrimaryKeyColumns {[True, False]} OldValue\
0 3 NewValue 0 <nullObject> ConflictValue 0 <nullObject> OldValue 1 {"inserted:\
Kilo Lima Mike November Oscar"} NewValue 1 {"updated: Uniform Victor Whiskey\
X-ray Yankee"} ConflictValue 1 <nullObject> TableName t1 NumberOfColumns 2\
OperationCode Insert Indirect False PrimaryKeyColumns {[True, False]} OldValue\
0 <nullObject> NewValue 0 4 ConflictValue 0 <nullObject> OldValue 1\
<nullObject> NewValue 1 {"inserted: Papa Quebec Romeo Sierra Tango"}\
ConflictValue 1 <nullObject>}}
###############################################################################
rename createByteArray ""
rename arrayToList ""
rename getChangeSetFileName ""
rename makeSomeChanges ""
rename createTheSchema ""
rename changeSetToString ""
rename forDisplay ""
rename cleanupSomeText ""
rename getSomeText ""
###############################################################################
runSQLiteTestEpilogue
runTestEpilogue