wizards/source/scriptforge/python/scriptforge.py |    9 
 wizards/source/sfdatabases/SF_Database.xba       |  332 +++++++++++++++++++++--
 wizards/source/sfdatabases/SF_Dataset.xba        |   11 
 wizards/source/sfdatabases/SF_Register.xba       |    2 
 4 files changed, 337 insertions(+), 17 deletions(-)

New commits:
commit 9b5b313a2f2980f9a10295aabdd696f58af03302
Author:     Jean-Pierre Ledure <j...@ledure.be>
AuthorDate: Thu Nov 23 17:59:33 2023 +0100
Commit:     Jean-Pierre Ledure <j...@ledure.be>
CommitDate: Fri Nov 24 09:54:59 2023 +0100

    ScriptForge (SF_Database) manage transactions
    
    Transactions are managed by next UNO properties:
       XConnection.AutoCommit
       XConnection.TransactionIsolation
    (They seem very easy to use but, in practice,
    are not easy at all)
    
    Usually all transactions are in auto-commit mode,
    that means, a commit takes place after each
    single SQL command.
    
    Switching auto-commit off  means however that
    the connection needs to be of type "ISOLATED"
    and not of the default type "SHARED".
    
    => The usual shared connection must be closed.
       As a consequence, all rowsets/resultsets linked
       to the shared connection need to be closed as well.
    => Additionally the buffers must be emptied (flushed)
       to make committed data visible in the Base user
       interface.
    
    All above aspects and constraints are managed in the
       database.SetTransactionMode(transactionmode)
       database.Commit()
       database.Rollback()
    methods transparently for the user scripts.
    
    The [transactionmode] argument has as value one of
    the TransactionIsolation constants.
    Without argument, database.SetTransactionMode()
    restores the automatic mode.
    
    The manual transaction mode is available for both
    Basic and Python scripts.
    Its implementation will require an update of the
    documentation about the Database service.
    
    Change-Id: I214bd91a1744d6d24609bc5efc987152c6e946c9
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/159867
    Reviewed-by: Jean-Pierre Ledure <j...@ledure.be>
    Tested-by: Jenkins

diff --git a/wizards/source/scriptforge/python/scriptforge.py 
b/wizards/source/scriptforge/python/scriptforge.py
index 77e0119809da..998d57d066a8 100644
--- a/wizards/source/scriptforge/python/scriptforge.py
+++ b/wizards/source/scriptforge/python/scriptforge.py
@@ -1794,6 +1794,9 @@ class SFDatabases:
         def CloseDatabase(self):
             return self.ExecMethod(self.vbMethod, 'CloseDatabase')
 
+        def Commit(self):
+            return self.ExecMethod(self.vbMethod, 'Commit')
+
         def CreateDataset(self, sqlcommand, directsql = False, filter = '', 
orderby = ''):
             return self.ExecMethod(self.vbMethod, 'CreateDataset', sqlcommand, 
directsql, filter, orderby)
 
@@ -1831,9 +1834,15 @@ class SFDatabases:
         def OpenTable(self, tablename):
             return self.ExecMethod(self.vbMethod, 'OpenTable', tablename)
 
+        def Rollback(self):
+            return self.ExecMethod(self.vbMethod, 'Rollback')
+
         def RunSql(self, sqlcommand, directsql = False):
             return self.ExecMethod(self.vbMethod, 'RunSql', sqlcommand, 
directsql)
 
+        def SetTransactionMode(self, transactionmode = 0):
+            return self.ExecMethod(self.vbMethod, 'SetTransactionMode', 
transactionmode)
+
     # #########################################################################
     # SF_Dataset CLASS
     # #########################################################################
diff --git a/wizards/source/sfdatabases/SF_Database.xba 
b/wizards/source/sfdatabases/SF_Database.xba
index cf970ea980fc..141a5bade393 100644
--- a/wizards/source/sfdatabases/SF_Database.xba
+++ b/wizards/source/sfdatabases/SF_Database.xba
@@ -25,6 +25,12 @@ Option Explicit
 &apos;&apos;&apos;
 &apos;&apos;&apos;             The provided interfaces include simple tables, 
queries and fields lists, and access to database metadata.
 &apos;&apos;&apos;
+&apos;&apos;&apos;             Tranaction handling
+&apos;&apos;&apos;                     Changes to data remain reversible until 
the moment the running script instructs the database to commit them.
+&apos;&apos;&apos;                     The implicit (default) behaviour is 
that commit takes place after the execution of every single SQL statement.
+&apos;&apos;&apos;                     The choice can be made 
(SetTranactionMode()) to take commitments manually.
+&apos;&apos;&apos;                     The Commit() and Rollback() statements 
delimit transactions.
+&apos;&apos;&apos;
 &apos;&apos;&apos;             Service invocation and usage:
 &apos;&apos;&apos;             1) To access any database at anytime
 &apos;&apos;&apos;                             Dim myDatabase As Object
@@ -67,6 +73,9 @@ Private       _URL                                    As 
String               &apos; Text on status bar
 Private _Location                              As String               &apos; 
File name
 Private _ReadOnly                              As Boolean
 Private        _MetaData                               As Object               
&apos; com.sun.star.sdbc.XDatabaseMetaData
+Private _User                                  As String               &apos; 
Connection parameters to enable a reconnection
+Private _Password                              As String
+Private _Datasets                              As Variant              &apos; 
Array of open datasets
 
 REM ============================================================ MODULE 
CONSTANTS
 
@@ -86,6 +95,9 @@ Private Sub Class_Initialize()
        _Location = &quot;&quot;
        _ReadOnly = True
        Set _MetaData = Nothing
+       _User = &quot;&quot;
+       _Password = &quot;&quot;
+       _Datasets = Array()
 End Sub                &apos;  SFDatabases.SF_Database Constructor
 
 REM 
-----------------------------------------------------------------------------
@@ -139,20 +151,57 @@ Const cstSubArgs = &quot;&quot;
 Check:
        ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
 
+Try:
+       _CloseConnection()
+       Dispose()
+
+Finally:
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Sub
+End Sub                        &apos;  SFDatabases.SF_Database.CloseDatabase
+
+REM 
-----------------------------------------------------------------------------
+Public Sub Commit()
+&apos;&apos;&apos;     Commit all updates done since the previous Commit or 
Rollback
+&apos;&apos;&apos;     The statement is ignored if the commits are done 
automatically after each SQL statement.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             DBREADONLYERROR                 The method is 
not applicable on a read-only database
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             db.SetTransactionMode(4)                &apos;  
Highest transaction level
+&apos;&apos;&apos;             db.RunSql(&quot;UPDATE ...&quot;)
+&apos;&apos;&apos;             db.Commit()
+&apos;&apos;&apos;             db.RunSql(DELETE ...&quot;)
+&apos;&apos;&apos;             If ...something happened... Then db.Rollback() 
Else db.Commit()
+&apos;&apos;&apos;             db.SetTransactionMode()                 &apos;  
Back to the automatic mode
+
+Const cstThisSub = &quot;SFDatabases.Database.Commit&quot;
+Const cstSubArgs = &quot;&quot;
+
+       On Local Error GoTo Finally
+
+Check:
+       ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+       If _ReadOnly Then GoTo Catch_ReadOnly
+
 Try:
        With _Connection
-               If Not IsNull(_Connection) Then
-                       If ScriptForge.SF_Session.HasUnoMethod(_Connection, 
&quot;flush&quot;) Then .flush()
-                       .close()
-                       .dispose()
+               If Not .AutoCommit Then
+                       .commit()
+                       &apos;  To make updates potentially visible in the user 
interface ...
+                       _FlushConnection()
                End If
-               Dispose()
        End With
 
 Finally:
+       On Local Error GoTo 0
        ScriptForge.SF_Utils._ExitFunction(cstThisSub)
        Exit Sub
-End Sub
+Catch_ReadOnly:
+       ScriptForge.SF_Exception.RaiseFatal(DBREADONLYERROR)
+       GoTo Finally
+End Sub                        &apos;  SFDatabases.SF_Database.Commit
 
 REM 
-----------------------------------------------------------------------------
 Public Function CreateDataset(Optional ByVal SQLCommand As Variant _
@@ -497,6 +546,7 @@ Public Function Methods() As Variant
 
        Methods = Array( _
                                        &quot;CloseDatabase&quot; _
+                                       , &quot;Commit&quot; _
                                        , &quot;CreateDataset&quot; _
                                        , &quot;DAvg&quot; _
                                        , &quot;DCount&quot; _
@@ -509,7 +559,9 @@ Public Function Methods() As Variant
                                        , &quot;OpenQuery&quot; _
                                        , &quot;OpenSql&quot; _
                                        , &quot;OpenTable&quot; _
+                                       , &quot;Rollback&quot; _
                                        , &quot;RunSql&quot; _
+                                       , &quot;SetTransactionMode&quot; _
                                        )
 
 End Function   &apos;  SFDatabases.SF_Database.Methods
@@ -602,7 +654,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SFDocuments.SF_Base.OpenQuery
+End Function   &apos;SFDatabases.SF_Database.OpenQuery
 
 REM 
-----------------------------------------------------------------------------
 Public Function OpenSql(Optional ByRef Sql As Variant _
@@ -642,7 +694,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SFDocuments.SF_Base.OpenSql
+End Function   &apos;  SFDatabases.SF_Database.OpenSql
 
 REM 
-----------------------------------------------------------------------------
 Public Function OpenTable(Optional ByVal TableName As Variant) As Object
@@ -678,7 +730,7 @@ Finally:
        Exit Function
 Catch:
        GoTo Finally
-End Function   &apos;  SFDocuments.SF_Base.OpenTable
+End Function   &apos;  SFDatabases.SF_Database.OpenTable
 
 REM 
-----------------------------------------------------------------------------
 Public Function Properties() As Variant
@@ -693,6 +745,45 @@ Public Function Properties() As Variant
 
 End Function   &apos;  SFDatabases.SF_Database.Properties
 
+REM 
-----------------------------------------------------------------------------
+Public Sub Rollback()
+&apos;&apos;&apos;     Cancel all updates done since the previous Commit or 
Rollback
+&apos;&apos;&apos;     The statement is ignored if the commits are done 
automatically after each SQL statement.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             DBREADONLYERROR                 The method is 
not applicable on a read-only database
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             db.SetTransactionMode(4)                &apos;  
Highest transaction level
+&apos;&apos;&apos;             db.RunSql(&quot;UPDATE ...&quot;)
+&apos;&apos;&apos;             db.Commit()
+&apos;&apos;&apos;             db.RunSql(DELETE ...&quot;)
+&apos;&apos;&apos;             If ...something happened... Then db.Rollback() 
Else db.Commit()
+&apos;&apos;&apos;             db.SetTransactionMode()                 &apos;  
Back to the automatic mode
+
+Const cstThisSub = &quot;SFDatabases.Database.Rollback&quot;
+Const cstSubArgs = &quot;&quot;
+
+       On Local Error GoTo Finally
+
+Check:
+       ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs)
+       If _ReadOnly Then GoTo Catch_ReadOnly
+
+Try:
+       With _Connection
+               If Not .AutoCommit Then .rollback()
+       End With
+
+Finally:
+       On Local Error GoTo 0
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Sub
+Catch_ReadOnly:
+       ScriptForge.SF_Exception.RaiseFatal(DBREADONLYERROR)
+       GoTo Finally
+End Sub                        &apos;  SFDatabases.SF_Database.Rollback
+
 REM 
-----------------------------------------------------------------------------
 Public Function RunSql(Optional ByVal SQLCommand As Variant _
                                                        , Optional ByVal 
DirectSQL As Variant _
@@ -788,8 +879,187 @@ Catch:
        GoTo Finally
 End Function   &apos;  SFDatabases.SF_Database.SetProperty
 
+REM 
-----------------------------------------------------------------------------
+Public Function SetTransactionMode(Optional ByVal TransactionMode As Variant) 
As Boolean
+&apos;&apos;&apos;     Configure the handling of transactions.
+&apos;&apos;&apos;     Usually all transactions are in auto-commit mode, that 
means, a commit takes place
+&apos;&apos;&apos;     after each single SQL command. Therefore to control a 
transaction manually, implies to switch auto-commit off.
+&apos;&apos;&apos;     The first SQL command starts a transaction that is 
active until the corresponding
+&apos;&apos;&apos;     methods have been committed or rolled back.
+&apos;&apos;&apos;
+&apos;&apos;&apos;     The transaction mode remains valid until the next call 
of the method with a different value,
+&apos;&apos;&apos;     or until the closure of the actual Database instance,
+&apos;&apos;&apos;     or until a call to SetTransactionMode() without 
argument, which cancels the manual transaction mode.
+&apos;&apos;&apos;
+&apos;&apos;&apos;     The method may close and replace the actual  
connection. This means that all open datasets
+&apos;&apos;&apos;     are first closed. Open datasheets might see their 
content changed or vanish.
+&apos;&apos;&apos;     The easiest is to set the transaction mode immediately 
after the creation of the Database instance.
+&apos;&apos;&apos;
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             TransactionMode: one of the 
com.sun.star.sdbc.TransactionIsolation constants:
+&apos;&apos;&apos;                     (0)     NONE                            
Indicates that transactions are not supported. Default: cancel the transaction 
mode.
+&apos;&apos;&apos;                     (1) READ_UNCOMMITTED    Dirty reads, 
non-repeatable reads and phantom reads can occur.
+&apos;&apos;&apos;                                                             
        This level allows a row changed by one transaction to be read by 
another transaction
+&apos;&apos;&apos;                                                             
        before any changes in that row have been committed (a &quot;dirty 
read&quot;).
+&apos;&apos;&apos;                                                             
        If any of the changes are rolled back, the second transaction will have 
retrieved an invalid row. 
+&apos;&apos;&apos;                     (2) READ_COMMITTED              Dirty 
reads are prevented; non-repeatable reads and phantom reads can occur.
+&apos;&apos;&apos;                                                             
        This level only prohibits a transaction from reading a row with 
uncommitted changes in it.
+&apos;&apos;&apos;                     (4)     REPEATABLE_READ         Dirty 
reads and non-repeatable reads are prevented; phantom reads can occur.
+&apos;&apos;&apos;                                                             
        This level prohibits a transaction from reading a row with uncommitted 
changes in it,
+&apos;&apos;&apos;                                                             
        and it also prohibits the situation where one transaction reads a row,
+&apos;&apos;&apos;                                                             
        a second transaction alters the row, and the first transaction rereads 
the row,
+&apos;&apos;&apos;                                                             
        getting different values the second time (a &quot;non-repeatable 
read&quot;).
+&apos;&apos;&apos;                     (8) SERIALIZABLE                Dirty 
reads, non-repeatable reads and phantom reads are prevented.
+&apos;&apos;&apos;                                                             
        This level includes the prohibitions in REPEATABLE_READ and further 
prohibits
+&apos;&apos;&apos;                                                             
        the situation where one transaction reads all rows that satisfy a WHERE 
condition,
+&apos;&apos;&apos;                                                             
        a second transaction inserts a row that satisfies that WHERE condition,
+&apos;&apos;&apos;                                                             
        and the first transaction rereads for the same condition, retrieving
+&apos;&apos;&apos;                                                             
        the additional &quot;phantom&quot; row in the second read. 
+&apos;&apos;&apos;     Returns:
+&apos;&apos;&apos;             True when successful.
+&apos;&apos;&apos;     Exceptions:
+&apos;&apos;&apos;             DBREADONLYERROR                 The method is 
not applicable on a read-only database
+&apos;&apos;&apos;     Example:
+&apos;&apos;&apos;             
oDb.SetTransactionMode(com.sun.star.sdbc.TransactionIsolation.SERIALIZABLE)     
        &apos;  8
+
+Dim bSet As Boolean                            &apos;  Return value
+Dim bCommit As Boolean                 &apos;  To compare with AutoCommit
+Const cstThisSub = &quot;SFDatabases.Database.SetTransactionMode&quot;
+Const cstSubArgs = &quot;TransactionMode=0|1|2|4|8&quot;
+
+       If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error GoTo Catch
+       bSet = False
+
+Check:
+       If IsMissing(TransactionMode) Or IsEmpty(TransactionMode) Then 
TransactionMode = 0
+       If ScriptForge.SF_Utils._EnterFunction(cstThisSub, cstSubArgs) Then
+               If Not ScriptForge.SF_Utils._Validate(TransactionMode, 
&quot;TransactionMode&quot;, ScriptForge.V_NUMERIC, Array(0, 1, 2, 4, 8)) Then 
GoTo Finally
+       End If
+       If _ReadOnly Then GoTo Catch_ReadOnly
+
+Try:
+       With _Connection
+               bCommit = ( TransactionMode &gt; 
com.sun.star.sdbc.TransactionIsolation.NONE )
+               &apos;  Replace the existing connection
+               If Not IsNull(_Connection) Then
+                       If .AutoCommit And bCommit Then
+                               _CloseConnection()
+                               Set _Connection = 
_DataSource.getIsolatedConnection(_User, _Password)
+                       ElseIf Not .AutoCommit And Not bCommit Then
+                               _CloseConnection()
+                               Set _Connection = 
_DataSource.getConnection(_User, _Password)
+                       End If
+               End If
+
+               &apos;  Set the transaction mode
+               If bCommit Then
+                       .SetTransactionIsolation(CLng(TransactionMode))
+                       .setAutoCommit(Not bCommit)
+               End If
+       End With
+
+       bSet = True
+
+Finally:
+       SetTransactionMode = bSet
+       ScriptForge.SF_Utils._ExitFunction(cstThisSub)
+       Exit Function
+Catch:
+       GoTo Finally
+Catch_ReadOnly:
+       ScriptForge.SF_Exception.RaiseFatal(DBREADONLYERROR)
+       GoTo Finally
+End Function   &apos;  SFDatabases.SF_Database.SetTransactionMode
+
 REM =========================================================== PRIVATE 
FUNCTIONS
 
+REM 
-----------------------------------------------------------------------------
+Public Function _AddToDatasets(ByRef poDataset As Object) As Long
+&apos;&apos;&apos;     Insert a newly created Dataset instance in the open 
datasets array
+&apos;&apos;&apos;     and return the index of the used entry.
+&apos;&apos;&apos;     Empty space is reused.
+&apos;&apos;&apos;     Args:
+&apos;&apos;&apos;             poDataset: the dataset instance to insert
+
+Dim lIndex As Long                     &apos;  Return value
+Dim lSize As Long                      &apos;  UBound of the _datasets array
+Dim i As Long
+
+Check:
+       lIndex = -1
+       If IsNull(poDataset) Then Exit Function
+       On Local Error GoTo Finally
+       lSize = UBound(_Datasets)
+
+Try:
+       &apos;  Can an empty entry be reused ?
+       For i = 0 To lSize
+               If IsNull(_Datasets(i)) Then
+                       lIndex = i
+                       Exit For
+               End If
+       Next i
+
+       &apos;  Resize _Datasets if no empty space
+       If lIndex &lt; 0 Then
+               lSize = lSize + 1
+               If lSize &gt; 0 Then
+                       ReDim Preserve _Datasets(0 To lSize)
+               Else
+                       ReDim _Datasets (0 To 0)
+               End If
+               lIndex = lSize
+       End If
+
+       &apos;  Insert new object
+       Set _Datasets(lIndex) = poDataset
+
+Finally:
+       _AddToDatasets = lIndex
+       Exit Function
+End Function   &apos;  SFDatabases.SF_Database._AddToDatasets
+
+REM 
-----------------------------------------------------------------------------
+Private Sub _CloseConnection()
+&apos;&apos;&apos;     Close the actual connection
+&apos;&apos;&apos;     To enable transaction modes, it is necessary to 
reinitialize the connection to the datasource.
+&apos;&apos;&apos;     The reinit includes
+&apos;&apos;&apos;             - the closure of all open datasets
+&apos;&apos;&apos;             - flushing the buffered and committed updates
+&apos;&apos;&apos;             - the effective closure
+&apos;&apos;&apos;     Otherwise the experience showed undesired side-effects.
+
+Dim oParent As Object                  &apos;  Parent of actual connection
+Dim oDataset As Object                 &apos;  Single dataset in the _Datasets 
array
+Dim oSession As Object                 :       Set oSession = 
ScriptForge.SF_Session
+Dim i As Long
+
+       On Local Error GoTo Finally             &apos;  Never abort
+
+Check:
+       If IsNull(_Connection) Then Exit Sub
+
+Try:
+       &apos;  Close datasets
+       For i = 0 To UBound(_Datasets)
+               Set oDataset = _Datasets(i)
+               If Not IsNull(oDataset) Then oDataset.CloseDataset()
+               Set _Datasets(i) = Nothing
+       Next i
+       _Datasets = Array()
+
+       &apos;  Flush buffers
+       _FlushConnection()
+
+       &apos;  Close the connection
+       _Connection.close()
+       _Connection.dispose()
+
+Finally:
+       On Local Error GoTo 0
+       Exit Sub
+End Sub                        &apos;  SFDatabases.SF_Database._CloseConnection
+
 REM 
-----------------------------------------------------------------------------
 Private Function _CollectFormDocuments(ByRef poContainer As Object) As String
 &apos;&apos;&apos;     Returns a token-separated string of all hierarchical 
formdocument names
@@ -826,7 +1096,7 @@ Finally:
                _CollectFormDocuments = &quot;&quot;
        End If
        Exit Function
-End Function   &apos;  SFDocuments.SF_Base._CollectFormDocuments
+End Function   &apos;  SFDatabases.SF_Database._CollectFormDocuments
 
 REM 
-----------------------------------------------------------------------------------------------------------------------
 Private Function _DFunction(ByVal psFunction As String _
@@ -967,6 +1237,34 @@ Catch:
        GoTo Finally
 End Function   &apos;  SFDatabases.SF_Database._ExecuteSql
 
+REM 
-----------------------------------------------------------------------------
+Private Sub _FlushConnection()
+&apos;&apos;&apos;     Empties the buffers of the actual connection
+&apos;&apos;&apos;     Sub called after each commit and at connection closure..
+
+Dim oParent As Object                  &apos;  Parent of actual connection
+Dim oSession As Object                 :       Set oSession = 
ScriptForge.SF_Session
+
+       On Local Error GoTo Finally             &apos;  Never abort
+
+Check:
+       If IsNull(_Connection) Then Exit Sub
+
+Try:
+       &apos;  Flush buffers
+       With oSession
+               If .HasUnoMethod(_Connection, &quot;getParent&quot;) Then
+                       Set oParent = _Connection.getParent()
+                       If .HasUnoMethod(oParent, &quot;flush&quot;) Then 
oParent.flush()
+               ElseIf .HasUnoMethod(_Connection, &quot;flush&quot;) Then
+                       _Connection.flush()
+               End If
+       End With
+
+Finally:
+       Exit Sub
+End Sub                        &apos;  SFDatabases.SF_Database._FlushConnection
+
 REM 
-----------------------------------------------------------------------------
 Private Function _GetColumnValue(ByRef poResultSet As Object _
                                                                        , ByVal 
plColIndex As Long _
@@ -1003,13 +1301,17 @@ Const cstMaxBinlength = 2 * 65535
                        Case .ARRAY                                             
:       vValue = poResultSet.getArray(plColIndex)
                        Case .BINARY, .VARBINARY, .LONGVARBINARY, .BLOB
                                Set oStream = 
poResultSet.getBinaryStream(plColIndex)
-                               If bNullable Then
-                                       If Not poResultSet.wasNull() Then lSize 
= CLng(oStream.getLength()) Else lSize = 0
+                               If IsNull(oStream) Then
+                                       lSize = 0
                                Else
-                                       lSize = CLng(oStream.getLength())
+                                       If bNullable Then
+                                               If Not poResultSet.wasNull() 
Then lSize = CLng(oStream.getLength()) Else lSize = 0
+                                       Else
+                                               lSize = 
CLng(oStream.getLength())
+                                       End If
+                                       oStream.closeInput()
                                End If
                                vValue = lSize  &apos;  Return length of field, 
not content
-                               If Not IsNull(oStream) Then oStream.closeInput()
                        Case .BIT, .BOOLEAN                             :       
vValue = poResultSet.getBoolean(plColIndex)
                        Case .DATE
                                vDateTime = poResultSet.getDate(plColIndex)
@@ -1170,4 +1472,4 @@ Private Function _Repr() As String
 End Function   &apos;  SFDatabases.SF_Database._Repr
 
 REM ============================================ END OF SFDATABASES.SF_DATABASE
-</script:module>
+</script:module>
\ No newline at end of file
diff --git a/wizards/source/sfdatabases/SF_Dataset.xba 
b/wizards/source/sfdatabases/SF_Dataset.xba
index 28091d9368b8..e9eb050d93f0 100644
--- a/wizards/source/sfdatabases/SF_Dataset.xba
+++ b/wizards/source/sfdatabases/SF_Dataset.xba
@@ -106,6 +106,8 @@ Private _UpdatableFields    As Variant              &apos; 
Array of updatable field names
 Private _DefaultValues         As Variant              &apos; Array of field 
default values // _Fields
 Private _AutoValue                     As Long                 &apos; Index of 
AutoValue field. None = -1
 
+Private _DatasetIndex          As Long                 &apos; Index of the 
dataset in the _Datasets array of the parent database
+
 REM ============================================================ MODULE 
CONSTANTS
 
 REM ====================================================== 
CONSTRUCTOR/DESTRUCTOR
@@ -127,6 +129,7 @@ Private Sub Class_Initialize()
        _UpdatableFields = Array()
        _DefaultValues = Array()
        _AutoValue = -1
+       _DatasetIndex = -1
 End Sub                &apos;  SFDatabases.SF_Dataset Constructor
 
 REM 
-----------------------------------------------------------------------------
@@ -280,6 +283,7 @@ Try:
                        .close()
                        .dispose()
                End With
+               If _DatasetIndex &gt;= 0 Then Set 
_ParentDatabase._Datasets(_DatasetIndex) = Nothing
                Dispose()
                bClose = True
        End If
@@ -1350,8 +1354,11 @@ Try:
                        If Len(sUpdatableFields) &lt;= 1 Then _UpdatableFields 
= Array() Else _UpdatableFields = Split(Mid(sUpdatableFields, 2), &quot;,&quot;)
                End With
        End With
+       
+       &apos;  Insert the instance in the _Datasets array of the parent 
database
+       _DatasetIndex = _ParentDatabase._AddToDatasets([Me])
 
-       bDataset = True
+       bDataset = ( _DatasetIndex &gt;= 0 )
 
 Finally:
        _Initialize = bDataset
@@ -1661,4 +1668,4 @@ CatchError:
 End Function   &apos;  SFDatabases.SF_Dataset._SetColumnValue
 
 REM ============================================ END OF SFDATABASES.SF_DATASET
-</script:module>
+</script:module>
\ No newline at end of file
diff --git a/wizards/source/sfdatabases/SF_Register.xba 
b/wizards/source/sfdatabases/SF_Register.xba
index cee09f94f3f3..e1b752f7f107 100644
--- a/wizards/source/sfdatabases/SF_Register.xba
+++ b/wizards/source/sfdatabases/SF_Register.xba
@@ -121,6 +121,8 @@ Try:
                If ScriptForge.SF_Utils._ErrorHandling() Then On Local Error 
GoTo CatchConnect
                Set ._Connection = ._DataSource.getConnection(vUser, vPassword)
                If IsNull(._Connection) Then GoTo CatchConnect
+               ._User = vUser
+               ._Password = vPassword
                ._ReadOnly = vReadOnly
                Set ._MetaData = ._Connection.MetaData
                ._URL = ._MetaData.URL

Reply via email to