Here's some code you can use to determine what PB is "seeing" from the ODBC (or any other) DB driver.
Replace the supplied SELECT statement assignment at the beginning with a SELECT statement that is valid for your DBMS:
Integer li_response
Long ll_rc, ll_row, ll_index
String ls_sqlstatement, ls_datatype, ls_value, ls_name, ls_msg
// Define the SQL SELECT statement.
// Note: The supplied SELECT statement is valid for SQL Server...
// Code a SELECT statement that is appropriate for your DBMS.
ls_sqlstatement = "Select 'Test Value' as field1, " + &
"cast('2022-11-01' as date) as field2, " + &
"cast('2022-11-01 09:36:00' as datetime) as field3, " + &
"cast(null as time) as field4, " + &
"cast(1.2345 as float) as field5 " + &
"From (Select a=1) t"
// Declare a cursor that will examine each row.
DECLARE c_values_cursor DYNAMIC CURSOR FOR SQLSA;
// Obtain information about the dynamic SQL statement.
PREPARE SQLSA FROM :ls_sqlstatement USING SQLCA;
DESCRIBE SQLSA INTO SQLDA;
// Execute the SELECT statement by opening the cursor.
OPEN DYNAMIC c_values_cursor USING DESCRIPTOR SQLDA;
// Fetch the first row of the result set.
FETCH c_values_cursor USING DESCRIPTOR SQLDA;
ll_rc = SQLCA.SQLCode
ll_row = 0
// Obtain the descriptor and value for each column in the result set.
Do While SQLCA.SQLCode = 0
ll_row ++
ls_msg = ""
For ll_index = 1 To SQLDA.NumOutputs
Choose Case SQLDA.OutParmType[ll_index]
Case TypeBoolean!
ls_datatype = "Boolean"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then
ls_value = "(null)"
ElseIf ls_value = "0" Then
ls_value = "False"
Else
ls_value = "True"
End If
Case TypeByte!
ls_datatype = "Byte"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeDate!
ls_datatype = "Date"
ls_value = String(GetDynamicDate(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeDateTime!
ls_datatype = "Datetime"
ls_value = String(GetDynamicDateTime(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeDecimal!
ls_datatype = "Decimal"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeDouble!
ls_datatype = "Double"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeInteger!
ls_datatype = "Integer"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeLong!
ls_datatype = "Long"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeLongLong!
ls_datatype = "LongLong"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeReal!
ls_datatype = "Real"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeString!
ls_datatype = "String"
ls_value = GetDynamicString(SQLDA,ll_index)
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeTime!
ls_datatype = "Time"
ls_value = String(GetDynamicTime(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeUInt!
ls_datatype = "UInt"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case TypeULong!
ls_datatype = "ULong"
ls_value = String(GetDynamicNumber(SQLDA,ll_index))
If IsNull(ls_value) Then ls_value = "(null)"
Case Else
ls_datatype = "Unknown"
ls_value = "????"
End Choose
If ls_msg <> "" Then ls_msg += "~r~n"
ls_msg += "Field #" + String(ll_index,"00") + ": Type = " + &
ls_datatype + "~tValue: " + ls_value
Next
ls_msg += "~r~n~r~nContinue with the next row?"
li_response = MessageBox("Row Number " + String(ll_row), &
ls_msg,Question!,YesNoCancel!,1)
If li_response = 1 Then
FETCH c_values_cursor USING DESCRIPTOR SQLDA;
ll_rc = SQLCA.SQLCode
Else
// Exit the Fetch loop.
SQLCA.SQLCode = 999
End If
Loop
// Close the cursor before leaving.
Close c_values_cursor;
Return ll_rc
We use PostGreSQL now. In addition to that we plan to support SQL Server and SQLite.