Opened 4 years ago
Closed 4 years ago
#3811 closed Feature Request (Completed)
_SQLite_FetchData should correctly read column data according to its type
Reported by: | matwachich@… | Owned by: | Jpm |
---|---|---|---|
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 Changed 4 years ago by Jpm
comment:2 Changed 4 years ago by Jpm
- Type changed from Bug to Feature Request
comment:3 Changed 4 years ago by Jpm
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 Changed 4 years ago by Jpm
- Milestone set to 3.3.15.4
- Owner set to Jpm
- Resolution set to Completed
- Status changed from new to closed
Added by revision [12497] in version: 3.3.15.4
Guidelines for posting comments:
- You cannot re-open a ticket but you may still leave a comment if you have additional information to add.
- In-depth discussions should take place on the forum.
For more information see the full version of the ticket guidelines here.
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