Modify ↓
Opened 5 years ago
Closed 5 years ago
#3811 closed Feature Request (Completed)
_SQLite_FetchData should correctly read column data according to its type
| Reported by: | Owned by: | J-Paul Mesnage | |
|---|---|---|---|
| Milestone: | 3.3.15.4 | Component: | Standard UDFs |
| Version: | Severity: | None | |
| Keywords: | Cc: |
Description
The main problem here is that _SQLite_FetchData is reading integer types as strings.
Here is an example code showing the problem (even when isDev column is set to 0, when read it becomes "0" and is interpreted as TRUE), and the solution (a corrected version of the function):
#NoTrayIcon
#include <Crypt.au3>
#include <SQLite.au3>
_SQLite_Startup()
_SQLite_Open()
_SQLite_Exec(-1, 'CREATE TABLE test (name TEXT, age INT, rdnFlt FLOAT, isDev BOOL, md5 BLOB);')
_SQLite_Exec(-1, 'INSERT INTO test VALUES ("person 01", 30, 0.5, 0, ' & _SQLite_Encode(_Crypt_HashData("person 01", $CALG_MD5)) & '), ("person 02", 35, 1.5, 1, ' & _SQLite_Encode(_Crypt_HashData("person 02", $CALG_MD5)) & ');')
Dim $aResult, $iRows, $iCols
_SQLite_GetTable2d(-1, 'SELECT * FROM test', $aResult, $iRows, $iCols)
For $i = 1 To $iRows
ConsoleWrite("Row " & $i & ": ")
For $j = 0 To $iCols - 1
ConsoleWrite($aResult[$i][$j] & " [" & VarGetType($aResult[$i][$j]) & "], ")
Next
ConsoleWrite("||| isDev: " & ($aResult[$i][3] ? "Yes" : "No") & @CRLF)
Next
; =============================
; now with a corrected function
ConsoleWrite(@CRLF & ">>> With the corrected function:" & @CRLF)
Dim $hQuery, $aRow, $i = 1
_SQLite_Query(-1, 'SELECT * FROM test', $hQuery)
While __mySqlite_FetchData($hQuery, $aRow) = $SQLITE_OK
ConsoleWrite("Row " & $i & ": ")
For $j = 0 To UBound($aRow) - 1
ConsoleWrite($aRow[$j] & " [" & VarGetType($aRow[$j]) & "], ")
Next
ConsoleWrite("||| isDev: " & ($aRow[3] ? "Yes" : "No") & @CRLF)
$i += 1
WEnd
; ==============================================================================
Func __mySqlite_FetchData($hQuery, ByRef $aRow, $bDoNotFinalize = False)
; step to the next row
Local $aRet = DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_step", "ptr", $hQuery)
If @error Then Return SetError(1, @error, $SQLITE_MISUSE) ; DllCall error
; check if we reached the end of the query
If $aRet[0] <> $SQLITE_ROW Then
If Not $bDoNotFinalize And $aRet[0] = $SQLITE_DONE Then _SQLite_QueryFinalize($hQuery)
Return SetError(-1, 0, $aRet[0])
EndIf
; count columns
Local $iColumns = DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_data_count", "ptr", $hQuery)
If @error Then Return SetError(2, @error, $SQLITE_MISUSE) ; DllCall error
If $iColumns[0] <= 0 Then Return SetError(-1, 0, $SQLITE_DONE)
$iColumns = $iColumns[0]
; read data according to column type
Dim $aRow[$iColumns]
Local $pBlob, $iBlobSize
For $i = 0 To $iColumns - 1
$aRet = DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_column_type", "ptr", $hQuery, "int", $i)
If @error Then Return SetError(4, @error, $SQLITE_MISUSE) ; DllCall error
Switch $aRet[0]
Case $SQLITE_TYPE_NULL
$aRow[$i] = Null
Case $SQLITE_TYPE_INTEGER
$aRet = DllCall($__g_hDll_SQLite, "int64:cdecl", "sqlite3_column_int64", "ptr", $hQuery, "int", $i)
If @error Then Return SetError(8, 0, $SQLITE_MISUSE) ; DllCall error
$aRow[$i] = $aRet[0]
Case $SQLITE_TYPE_FLOAT
$aRet = DllCall($__g_hDll_SQLite, "double:cdecl", "sqlite3_column_double", "ptr", $hQuery, "int", $i)
If @error Then Return SetError(9, 0, $SQLITE_MISUSE) ; DllCall error
$aRow[$i] = $aRet[0]
Case $SQLITE_TYPE_BLOB
$pBlob = DllCall($__g_hDll_SQLite, "ptr:cdecl", "sqlite3_column_blob", "ptr", $hQuery, "int", $i)
If @error Then Return SetError(6, @error, $SQLITE_MISUSE) ; DllCall error
$iBlobSize = DllCall($__g_hDll_SQLite, "int:cdecl", "sqlite3_column_bytes", "ptr", $hQuery, "int", $i)
If @error Then Return SetError(5, @error, $SQLITE_MISUSE) ; DllCall error
$aRow[$i] = Binary(DllStructGetData(DllStructCreate("byte[" & $iBlobSize[0] & "]", $pBlob[0]), 1))
Case $SQLITE_TYPE_TEXT
$aRet = DllCall($__g_hDll_SQLite, "wstr:cdecl", "sqlite3_column_text16", "ptr", $hQuery, "int", $i)
If @error Then Return SetError(3, @error, $SQLITE_MISUSE) ; DllCall error
$aRow[$i] = $aRet[0]
EndSwitch
Next
; done
Return $SQLITE_OK
EndFunc
Here is console output:
Row 1: person 01 [String], 30 [String], 0.5 [String], 0 [String], 0x8030B779B60EF1407533A8947D0EE209 [Binary], ||| isDev: Yes Row 2: person 02 [String], 35 [String], 1.5 [String], 1 [String], 0x87AEFAE13874D477BA336DE19B4FF16E [Binary], ||| isDev: Yes >>> With the corrected function: Row 1: person 01 [String], 30 [Int64], 0.5 [Double], 0 [Int64], 0x8030B779B60EF1407533A8947D0EE209 [Binary], ||| isDev: No Row 2: person 02 [String], 35 [Int64], 1.5 [Double], 1 [Int64], 0x87AEFAE13874D477BA336DE19B4FF16E [Binary], ||| isDev: Yes
Attachments (0)
Change History (5)
comment:1 by , 5 years ago
comment:2 by , 5 years ago
| Type: | Bug → Feature Request |
|---|
comment:3 by , 5 years ago
In fact I will use the parameter in _SQLite_Startup to force the whole script and If not possible the scripter will use a new parameter in _SQLite_FetchData() in the suitable places
comment:5 by , 5 years ago
| Milestone: | → 3.3.15.4 |
|---|---|
| Owner: | set to |
| Resolution: | → Completed |
| Status: | new → closed |
Added by revision [12497] in version: 3.3.15.4
Note:
See TracTickets
for help on using tickets.

Hi,
I don't thing it is a bug but more an improvement as a lot of script can be in error if we change as you suggest.
For the time being I am trying to add a new parameter to _SQLite_GetTable2D and _SQLite_FetchData so that the decision to do it or not will be a scrippt decision.
I will investigate if I can do it a the query or open time. it looks nmore difficult to implement.
another solution can be a startup easy to implement for the global script