SQLExpress Change Log
Ver 3.3.13 (2022.02.12)
- fix: SQLDataSet:RefreshRow() incorrectly marked record for deletion in datasource when it does not match :CustomFilter condition.
- changed: optimization/speed improvement in SQLDataSet refresh when using SQL parameters.
Ver 3.3.10 (2021.01.14)
- fix: rollback change allowing NIL value for binary type column via SQL statement params. To make a binary column NULL in a parameterized query, use SQLValue, eg:
oConn:execute("insert into Test (BinaryField) values (?)", { SQLValue():new(nil, SQL_BINARY) })
Ver 3.3.09 (2021.01.08)
- fix: unable to pass a NULL value to an SQL binary type column when using SQL statement parameters (?).
- new: SQLSelect:FastFieldGet() method.
- new: method :fget() executes :FastFieldGet() in SQLSelect and SQLDataSet classes
- new: method :get() executes :FieldGet() in SQLSelect and SQLDataSet classes.
- new: method :put() executes :FieldPut() in SQLSelect and SQLDataSet classes.
Ver 3.3.08 (2020.12.12)
- fix: Newer MS SQLServer ODBC drivers changed the way VARBINARY(max) columns are identified, resulting in failed cursor commits.
- fix: SQLSelect:isNull() was incorrect for column values with a zero-length string.
Ver 3.3.05 (2019.01.01)
- fix: SQLConnection:Reconnect unable to establish db connection following a failed initial :DriverConnect or :BrowseConnect
- fix: SQLDataSet:isTruncated did not indicate a partial (truncated) dataset due to error while fetching the cursor from dbms. In some rare circumstances, an error such as a deadlock may occur while skipping through a cursor, resulting in a truncated dataset.
- new: SQLStatement:SetConnection() & SQLDataSet:SetConnection() methods allow changing the underlying object's database connection
- changed: READONLY attribute removed from SQLDataSet:Connection and SQLDataSet:Cursor ivars
Ver 3.3.00 (2016.11.08)
- fix: SQLConnection:ErrorMessage() raised error and failed to return appropriate information for a null connection handle.
- fix: SQLStatement:ErrorMessage() raised error and failed to return appropriate information for a null statement handle.
- fix: Setting SQLDataSet:LastIDSyntax to NIL failed to update the LastIDSyntax property value in the underlying cursor.
- fix: SQLDataSet:commit() cannot update a database row after an initial failed update of the same row.
- changed: Reduce interval for database reconnection attempts after a comm link failure.
- changed: Refactored documentation.
Ver 3.2.19 (2015.01.22)
- fix: SQLStatement:ExecuteScript() returned .T. even though the script failed to execute successfully.
Ver 3.2.18 (2014.10.03)
- new: Read-only dataset which results in a 50% reduction in the client-side memory footprint when compared to an updatable SQLDataSet instance.
- new: SQLDataSet:isReadOnly property controls if the dataset will be read-only or updatable.
- new: lReadOnly parameter has been added to the SQLDataSet init method.
- new: SQLConnection:RDataSet method generates a read-only SQLDataSet.
- new: automatically generate a read-only SQLDataSet whenever parent SQLConnection is also defined as read-only.
- fix: SQLConnection:Execute() failed to complete if multiple results were pending such as from a stored procedure or database triggers.
Ver 3.2.15 (2013.09.19)
- new: SQLConnection:AutoReconnect property controls whether an auto-reconnect is attempted after a dropped connection due to communications link failure.
- new: LastIDSyntax property added to SQLConnection, SQLSelect and SQLDataSet classes. This property allows programmer to specify the SQL SELECT syntax for retrieving the last DBMS inserted identity value.
- new: SQLSelect cursors containing an auto-unique column will now automatically be updated with the DBMS generated identity value after appending a new row.
To disable this functionality set SQLConnection:LastIDSyntax to NIL.
- fix: SQLDataSet:commit() raised error when the dataset contained virtual columns (changes to virtual columns are not saved in the source database).
- fix: SQLDataSet:commit() raised error when the dataset contained an auto-unique field.
- fix: SQLDataSet:Locate() moved row pointer to end of dataset when :BrowseFilter is active and search condition not found.
- fix: PostgreSQL TEXT columns were truncated to 8190 bytes.
Ver 3.2.08 (2010.11.27)
- fix: logical bit values were incorrectly translated for MySQL.
Ver 3.2.07 (2009.04.23)
- new: SQLStatement:ExecuteScript and SQLConnection:ExecuteScript methods.
- new: parameter nMaxSize added to SQLErrorLog function. Defaults to 1000000 bytes.
- fix: unable to read MySQL longtext data types.
- fix: SQLConnection:Reconnect() popped up driver connection dialog even though a full connection string was available.
- fix: SQLConnection:Disconnect() sometimes triggered bogus error "connection not open".
- fix: error was raised if connection object not passed to SQLSelect():new()
Ver 3.2.01 (2008.03.29)
- new: improved SQLDataSet fetch data performance by 10-20%.
- new: SQLDataSet:isNull method indicates if field contains a NULL value.
- new: SQLDataSet:ExecuteAsync method allows fetching data in background (see demo in SQLBRO.PRG - test with large dataset).
- new: SQLDataSet:isFinished property signals when background data fetch is completed.
- new: SQLDataSet:AsyncPriority method to get or set background thread priority.
- new: SQLDataSet:CancelUpdate method.
- new: added additional parameter nRow to SQLDataSet methods: FieldGet, FastFieldGet and FieldPut.
This enables direct, multi-threaded row access of data.
- new: SQLConnection:GetActiveConnections method returns array of all active connections.
- new: SQLConnection:GetActiveStatements method returns array of all active statements on current connection.
- fix: unable to save a DBF memo field to an SQL table.
- fix: SQLDataSet:ErrorMessage raised bogus error message if called after data has been fetched.
Ver 3.1.24 (2006.05.29)
- new: reduce server utilization and improve performance for forward-only cursors.
Ver 3.1.23 (2006.01.02)
- new: re-execute SQLSelect:UpdateRow() using a searched update/delete when an 'invalid cursor name' (SQLState 34000) error is returned by DBMS.
- fix: when reading SQL_LONGVARBINARY data, last byte was assumed to be a null byte and was removed.
- fix: SQLConnection:TransactionIsolation failed to set specified transaction isolation.
- fix: SQLConnection:ConnectionTimeout failed to set specified connection timeout.
Ver 3.1.20 (2005.08.28)
- new: SQLDataSet:BrowseFilter property allows filtering of client-side dataset.
- new: added lAppend parameter to SQLErrorLog function.
- fix: SQLSelect:RecNo incorrectly set to 0 when only one row in result set and row pointer is moved up/down several times
- fix: SQLDataSet now checks if SELECT statement was executed successfully.
Ver 3.1.17 (2004.12.14)
- fix: when using Xbase++ 1.3 compiler, calling SQLDataSet:ErrorMessage resulted in runtime error: "Access to member-variable not allowed in this context".
- default to non-scrollable cursor for ODBC drivers not supporting SQL_ATTR_CURSOR_TYPE attribute.
- default to read-only cursor for ODBC drivers not supporting SQL_ATTR_CONCURRENCY attribute.
- report SQLExpress version # in error:subsystem.
- log additional info in error:description and error:operation when parameter binding fails.
- raise error when connection or statement handle is NULL.
- the sqlxpp.dll can now be loaded and unloaded dynamically at runtime.
Ver 3.1.13 (2003.12.12)
- fix: Ver 3.1.12 sometimes returned non-character fields as a character type.
Ver 3.1.12 (2003.11.26)
- new: There is now only one SQLXPP.DLL for all versions (demo, lite and pro). Mode of operation is determined by license key. Invalid license defaults to demo mode. See: SQLXKEY.PRG
- new: Enhanced documentation. Added descriptions of cursor types, cursor concurrency and transaction isolation levels. A few new examples have also been added, including one showing how to implement transactions within Xbase++.
- new: SQLConnection():DestroyContext() method kills all connections created in current thread.
By default DestroyContext() is assigned to the current thread's :atEnd ivar if the ivar is empty.
- new: SQLConnection:RetryDeadlockVictim ivar to specify whether statements that failed due to a deadlock will be automatically re-executed (default is .T.).
- new: SQLErrorHandler() function logs errors to a log file + automatically reconnects if there is a communications link failure.
The error handler is assigned to the SQLConnection:onError ivar when a new SQLConnection object is instantiated.
To disable set :onError to NIL or assign your own error block.
- new: SQLConnection:ErrorLogFile ivar used to specify file name where error info will be saved, default is SQLERROR.LOG. Used by SQLErrorHandler function.
- new: SQLConnection:TransactionIsolation property to get/set the default transaction isolation level for a connection.
- new: SQLColumn:isAutoUnique property indicates if a column contains auto generated unique values.
- new: If an auto unique column is available but no primary key has been specified, then SQLSelect and SQLDataSet classes will use that as the primary key in searched update and delete statements.
- fix: SQLDataSet:Delete() on last row did not set :Eof flag to true
- fix: Fallback to searched updates if positioned statement fails.
- fix: Eliminated MS-SQLServer warning "fetch type out of range" when doing a :Skip() on last row of result set returned by a stored procedure.
- fix: Exact DECIMAL and NUMERIC types (not including integer and floating point numerics) were sometimes retrieved incorrectly when ODBC driver translated values into regional settings.
Ver 3.0.03 (2003.03.10)
- big performance increase for fetching data: SQLSelect is now 200-300% faster, SQLDataSet is 300% faster.
- oCursor:FieldGet("FieldName") with field name supplied as a string is now 200% faster.
- optimized SQLSelect:Skipper to fetch data more efficiently resulting in faster rendering of data with smoother scrolling.
- new method SQLDataSet:GetColumnData returns an entire column of data as an array.
- new method SQLSelect:isNull indicates if a field contains a NULL value.
- fix for SQLDataSet:Seek when resultset contains only one row.
- zero length strings were previously saved as NULLs, they are now saved as a zero length string.
- SQLSelect now uses the delimited table name in automatically generated UPDATE & DELETE statements.
In previous versions, an error occured if table name contained spaces.
Ver 2.0.22 (2002.10.01)
- Exact DECIMAL and NUMERIC numbers are retrieved with the number of decimal places intact (as in versions prior to 2.0.20).
- Reduced potential of getting "statement is busy with results from another hstmt" error when using
MS-SQL Server with stored procedure triggers.
Ver 2.0.20 (2002.09.14)
- fix to SQLDataSet:Commit() to eliminate potential of duplicate GUID values.
- fix for MS-SQL Server to allow writing > 8000 characters to a TEXT field.
- modified some internal classes so that an SQLDataSet object may be transmitted using Xb2.NET SOAP.
- fix for floating point numbers. Floating point number support is now improved when using Xbase++ ver. 1.5 and higher.
- reading and writing of double byte unicode strings is now more consistent.
- Oracle error codes may not have been dealt with correctly in past versions due to differences in the way Oracle returns
this information, this is now handled better.
Ver 2.0.13 (2002.03.15)
- fix to SQLDataSources, this was a typo bug introduced in ver 2.0.12
Ver 2.0.12 (2002.03.12)
- workaround for bug in MS-SQL Server ODBC driver, a SQLSelect:Destroy() did not always close a cursor.
- check cursor concurrency after SQLSelect:execute() to make sure positioned updates/deletes are still supported.
Cursor type / concurrency may have changed based on SELECT statement.
- SQLStatement:DisplayErrors now inherits SQLConnection:DisplayErrors setting when instantiated
- :DisplayErrors ivar now controls whether user's :onError codeblock will be fired. If .F., then :onError will not be evaluated nor a console error displayed.
- :ErrorMessage is now an access method, it will retrieve the most recent driver error.
- SQL replication feature in AceWrappers now supports dbZap().
Ver 2.0.10 (2002.01.21)
- SQLDataSet now allows creating empty datasets that can be populated ad-hoc by the programmer
- new sample program SQLTest4.prg, demonstrating how to create, populate and browse a un-connected SQLDataSet object
- raise error if invalid field is specified in :FieldGet/:FieldPut method
- SQLSelect:FieldName() and SQLDataSet:FieldName() now return column name in default case (previously it was returned in upper case)
- bug fix to SQLConnection:GetDrivers(), previously this method was returning data sources instead of drivers and attributes
- added SQLStatement:ParamList property to save parameter values during a reconnect
- enhanced MySQLErrorHandler function in sample SQLTest3.prg program
- added SQLSelect:SortOrder and SQLDataSet:SortOrder properties
- SQLDataSet:Sort now accepts array of fields to sort dataset by
- SQLSelect:Seek and SQLDataSet:Seek now accept array of values and array of fields to seek
- SQLSelect:Locate and SQLDataSet:Locate now accepts array of values and array of fields to search for
- SQLDataSet:Locate method now uses the simple equals operator (=) for string comparisons.
This is consistent with SQLSelect:Locate and previously published documentation
- workaround for Val("99") bug in Xbase++ compiler (added to SQLExpress and ACE Wrappers). Note: This workaround may effect display of some numeric fields when
viewed in a TBrowse or XbpBrowse screen. To eliminate this potential problem, always use a picture string to format numeric field values.
Ver 2.0.04 (2001.09.04)
- SQLStatement:Execute() now returns SQL_XPP_WARNING when statement is executed successfully but with warnings or messages
- SQLStatement:Reset() method now preserves current statement's attributes
- allow real or aliased column name to be specified in :SetPrimaryKey (the base column name can only be used if it is returned by the driver)
- SQLColumn:Name is now set to the 'base' column name if the base column name is returned by the driver
- bug fix to SQLDataSet to prevent writing to readonly columns when inserting new rows
- parse out semicolon from table name when using internally generated update statements
Ver 2.0.00 (2001.03.30)
- added new SQLDataSet class for managing static client-side cursors (provides a fast scrollable cursor for all data sources).
- added SQLSelect:Seek and SQLSelect:Locate methods
- added SQLSelect:RecordGet and SQLSelect:RecordPut methods
- added SQLSelect:OrderBy property
- added SQLConnection:DateTimeAsDate property
- added SQLConnection:DataSet method
- modified SQLConnection:isConnected to check if the connection to the server is dead
- modified SQLConnection:Reconnect() method to allow a dropped connection to be re-established and continue as
if the connection was never lost. Note, this method no longer automatically disconnects from the data source.
To keep previous functionality replace :Reconnect() with :Disconnect() + :Connect()
- improved skip methods in SQLSelect class
- implemented workaround for bug in MySQL when attempting to skip prior to first row in result set
- improved detection of deleted rows in SQLSelect class
- bug fix for saving integers outside of range: -2147483648 to +2147483647
- bug fix to error handler which occasionally caused app to terminate when retrieving multiple errors from ODBC driver / data source
- many changes to ACE Wrappers including improved support for NTX indexes and ADT/ADI tables
- added new sample programs and improved existing samples
Ver 1.2.28 (2000.09.12)
- added SQLConnection:ThreadID property
- added SQLConnection:MaxActiveConnections property
- added SQLConnection:ConnectionTimeout property
- added SQLConnection:ConnectString property to store the final connection string when using :DriverConnect() or :BrowseConnect() to establish a connection
- added SQLConnection():FindConnection() class method to find an existing connection on current thread
- added SQLColumn:isUpdatable property
- if an SQLConnection object is not specified when creating a new SQLStatement object, an existing connection (if one exists) will now be used
- it is now possible to create a new cursor simply by assigning a new SELECT string to the SQLSelect:SQLString property of an existing object (no need to destroy and create a new object)
- removed READONLY attribute from SQLConnection:IdentifierQuoteChar in order to allow programmer the option of overriding this property since some ODBC drivers may report a wrong value
- added new SQLConnection:IdentifierCase property to determine if identifiers are case sensitive
- case of SQL identifiers is no longer modified, column names are now used exactly as returned by the driver (prior versions converted column and table names to upper case)
- bug fix to SQLSelect:Refresh(). In prior versions, :Refresh() would clear all primary key columns that were defined by the programmer with the SQLSelect:SetPrimaryKey() method
- added new TBrowse sample program
Ver 1.2.25 (2000.06.11)
- bug fix to SQLSelect:destroy(). In build 1.2.23, the destroy() method did not always clean up properly resulting in open ODBC statement handles
- the ACE Wrappers are now packaged as an external DLL (full source code is provided)
- added additional functions to the ACE Wrappers for improved support of 3P libraries like eXPress++ and TopDown
- added new ACE Wrapper sample program using XbpBrowse
Ver 1.2.23 (2000.05.15)
- added new SQLError class
- added SQLConnection:onError property
- added SQLStatement:onError property
- eliminated need for BAP.DLL
- fixed bug that resulted in some drivers raising an "Invalid precision value" error when saving strings longer than the maximum supported CHAR length
- bug fix to SQLSelect:FieldPos() (returned value was dependent on setting of SET EXACT)
- added latest ACE (Advantage Client Engine) wrappers with many new enhancements including seamless SQL replication (an excellent example of advanced use of SQLExpress)
Full source code is included (click here for more info)
Ver 1.1.19 (2000.03.08)
- modified SQLStatement:Execute() so that it does not modify the array of parameters passed to it (the same array of data can now be resubmitted for execution).
Ver 1.1.18 (2000.03.06)
- added SQLConnection:BrowseConnect() method
- added SQLConnection:GetDrivers() method
- added SQLStatement:Reset() method
- added SQLSelect:DateTimeAsDate property
- improved support for NULL values
- improved support for DATETIME datatypes
- optimized update statements generated by SQLSelect cursors
- bug fix to handle situation when a single non-array parameter is passed to :Execute() method
- added new sample program
Ver 1.1.14 (2000.02.07)
- fix to correctly parse SELECT statements that contain table names with spaces
- added additional options to SQLConnection:driverConnect() method (it is now possible to connect to a datasource without an ODBC DSN)
- enabled preparing statements with parameters. This was previously turned off due to possible performance degradation (see SQLStatement:Prepare())
- improved support for executing stored procedures with multiple result sets and batched SQL statements.
- added SQLConnection:MultipleResults property
- added SQLStatement:MoreResults() method
- added new SQLValue class
Ver 1.1.10 (1999.11.15)
- added the following catalog query classes:
SQLCatalogQuery
SQLListColumnPrivileges
SQLListColumns
SQLListForeignKeys
SQLListPrimaryKeys
SQLListProcedureColumns
SQLListProcedures
SQLListSpecialColumns
SQLListStatistics
SQLListTablePrivileges
SQLListTables
SQLListTypeInfo
- enhanced XbpBrowse sample program to view results from new catalog query classes
- modified DLL exit procedure to protect against error recursion
Ver 1.0.9 (1999.10.17)
- improved method for saving SQL datetime, timestamp and time values from a cursor
- improved support for unicode, binary and long data fields.
- fix to SQLSelect:CursorName() that resulted in failed positioned updates and deletes
Ver 1.0.8 (1999.10.14)
- cursor row count is now obtained directly from the driver if supported
- added the following properties to SQLSelect class
:UsePositionDelete
:UsePositionUpdate
Ver 1.0.7 (1999.10.07)
- added SQLSelect:skipper method for use with XbpBrowse and TBrowse
- added new sample program using XbpBrowse to browse an SQL cursor
- removed phantom row when skipping past last row in result set (this proved to be more trouble than it was worth)
- added SQLConnection:BufferSize property to allow user the ability to specify the maximum default column buffer size per connection
- corrected problem with drivers that require cursor columns to be read in sequence
- added following properties to SQLConnection class
:DatabaseName
:DbmsName
:DbmsVersion
:CollationSequence
- added support for OMF linkers like Blinker
- other minor changes
Ver 0.1.5 (1999.09.16)
- Updated manual, uploaded to homepage, no significant changes to source code
Ver 0.1.4 (1999.09.08)
- Restricted size of column buffer to a max of 65536 bytes
- SQLColumn:defValue is now set to a null string for character and binary datatypes other than SQL_CHAR
Ver 0.1.3 (1999.08.30)
Ver 0.1.2 (1999.07.15)
- many changes to error handling
- changes to the way prepared statements with parameters are handled
Ver 0.1.1 (1999.07.05)
- first public beta release