Page 1 of 1

[PB5.62] SQLite variable binding

Posted: Tue Aug 21, 2018 4:23 pm
by Yuri_D
Hello!

Maybe it is a bug in my head (again... :oops: ) or in SQLite itself.
Is it correct that the string variable binding works only with "=?" placeholders but it doesn't with just a "?", f.e.:

Code: Select all

    If GetGadgetState( licProductFamily) = 0 ; If < All > 
      
      SetGadgetState( licProductFamily, 0) ; deselect all
    Else
      _sString = "IN("
      For _i = 1 To CountGadgetItems( licProductFamily) -1 
        If GetGadgetItemState( licProductFamily, _i)
          
          SetGadgetItemState( licProductFamily, 0, 0)
          _sString + Str( GetGadgetItemData( licProductFamily, _i)) +","
        EndIf
      Next
      
      _sString = RTrim( _sString, ",") +")"
    EndIf

    SQLite_BindString(  0, _sString)
    SQLite_BindInteger( 1, GetGadgetItemData( cmbPB_Name, GetGadgetState( cmbPB_Name)))

_sSQL = "...
 WHERE [main].[tblProductFamilies].[ID] ? And [main].[tblPriceBooks].[ID] = ?
..."
Now I fored to use:

Code: Select all

    ;SQLite_BindString(  0, _sString)
    SQLite_BindInteger( 0, GetGadgetItemData( cmbPB_Name, GetGadgetState( cmbPB_Name)))

_sSQL = "...
WHERE [main].[tblProductFamilies].[ID] "+ _sString +" And [main].[tblPriceBooks].[ID] = ?
..."
so I can't offload this query to a data block

BRG
Yury

Re: [PB5.62] SQLite variable binding

Posted: Tue Aug 21, 2018 4:51 pm
by skywalk
Please do not post to BUGS if you are unsure. :idea:
You are mixing PB database commands and SQLite dll commands.
Read about SetDatabaseString() and queries like:
"SELECT ?1,?2 FROM Keywords ORDER BY Word,Item"

Re: [PB5.62] SQLite variable binding

Posted: Tue Aug 21, 2018 4:57 pm
by Marc56us
From what I understand, it works in all cases, however, the placeholder content is "evaluated/controlled" before integrating the SQL string, so a text like "IN(" will not work in this case since the system expects a variable and not an SQL statement

Based on the example
https://www.purebasic.com/documentation ... se.pb.html

Code: Select all

         ; OK
         ; SetDatabaseString(0, 0, "pear")  
         ; If DatabaseQuery(0, "SELECT * FROM food WHERE name=?")    
         
         ; KO
         SetDatabaseString(0, 0, "name=pear")  
         If DatabaseQuery(0, "SELECT * FROM food WHERE ?")    
             While NextDatabaseRow(0)
                 Debug GetDatabaseString(0, 0)
             Wend
         EndIf
But maybe I misunderstood.

So doesn't seem to be a bug. Can a moderator move this topic to 'Coding Question' ? Thank you :wink:

Re: [PB5.62] SQLite variable binding

Posted: Wed Aug 22, 2018 8:02 am
by Yuri_D
@skywalk
Ok, thanks, I'll go that way next time but I used only a PB documentation to create my code and according to PB help Example
"Bind variables with SQLite and ODBC
; SQLite and ODBC shares the same syntax for bind variables. It is indicated by the '?' character
..."

@Marc56us
Maybe, but my IMHO is: PB and SQLite shall not care about the string content and SQLite actually didn't because I can successfully enter "IN(1,2,3,4)" and any other query-like sentences into a DB with help of any database browser so I suspect a bug

Re: [PB5.62] SQLite variable binding

Posted: Wed Aug 22, 2018 8:56 am
by Fred
Moved back to bug for more investigation

Re: [PB5.62] SQLite variable binding

Posted: Wed Aug 22, 2018 9:26 am
by Marc56us
Small example for investigation (based on pb sample)
(hope this help)

Code: Select all

; ------------------------------------------------------------
;
;   PureBasic - Database example file
;
;    (c) Fantaisie Software
;
; ------------------------------------------------------------
;

UseSQLiteDatabase()

Procedure CheckDatabaseUpdate(Database, Query$)
    Result = DatabaseUpdate(Database, Query$)
    If Result = 0
        Debug DatabaseError()
    EndIf
    
    ProcedureReturn Result
EndProcedure

DatabaseFile$ = GetTemporaryDirectory() + "Database.sqlite"

If CreateFile(0, DatabaseFile$)
    CloseFile(0)
    
    If OpenDatabase(0, DatabaseFile$, "", "")
        
        CheckDatabaseUpdate(0, "CREATE TABLE food (name CHAR(50), weight INT)")
        
        CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('apple', '10')")
        CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('pear', '5')")
        CheckDatabaseUpdate(0, "INSERT INTO food (name, weight) VALUES ('banana', '20')")     
        
        Debug ~"\n--- String set by SetDatabaseString"
        SetDatabaseString(0, 0, "IN(10)")  
        If DatabaseQuery(0, "SELECT * FROM food WHERE weight ?")    
            While NextDatabaseRow(0)
                Debug "Found: " + GetDatabaseString(0, 0)
            Wend
        Else
            Debug "(Nothing)"
        EndIf
        FinishDatabaseQuery(0)
        
        Debug ~"\n--- String direct in SQL query"
        If DatabaseQuery(0, "SELECT * FROM food WHERE weight IN(10,5)")    
            While NextDatabaseRow(0)
                Debug "Found: " + GetDatabaseString(0, 0)
            Wend
        Else
            Debug "(Nothing)"
        EndIf
        FinishDatabaseQuery(0)
        
        CloseDatabase(0)
    Else
        Debug "Can't open database !"
    EndIf
Else
    Debug "Can't create the database file !"
EndIf

Code: Select all

--- String set by SetDatabaseString
(Nothing)

--- String direct in SQL query
Found: apple
Found: pear
So SetDatabaseString does not replace '?' by string 'IN(10,5)'


:idea: Would it be possible to display the string received by the system when using SetDataBase... ?
DataBaseError() displays it well, but only in case of error
I think not, because it seems that replacement is only done at the time of execution of the request

Code: Select all

        SetDatabaseString(0, 0, "IN(10)")
        SQL$ = "SELECT * FROM food WHERE weight ?"
        Debug "SQL: " + SQL$

Code: Select all

--- String set by SetDatabaseString
SQL: SELECT * FROM food WHERE weight ?

Re: [PB5.62] SQLite variable binding

Posted: Wed Aug 22, 2018 10:50 am
by Yuri_D
@Marc56us
When I'm using "?" for "IN(....)", DataBaseError() returns "Database Error: near "?": syntax error"

Re: [PB5.62] SQLite variable binding

Posted: Wed Aug 22, 2018 8:07 pm
by freak
You cannot place SQL syntax elements (like a "=") inside a placeholder like this. This is the whole point of using variable binding: It prevents SQL injection attacks.

If you do this:

Code: Select all

        SetDatabaseString(0, 0, "IN(10)") 
        If DatabaseQuery(0, "SELECT * FROM food WHERE weight ?")   
You are actually executing this query:

Code: Select all

        If DatabaseQuery(0, "SELECT * FROM food WHERE weight 'IN(10)'")
It is interesting that SQLite accepts this as valid syntax, but that is an SQLite problem not a PB one.

Re: [PB5.62] SQLite variable binding

Posted: Thu Aug 23, 2018 10:23 am
by Yuri_D
@Freak
Thank you for the explanation!
Does it mean that it is not possible to use placeholders for queries morphing?
The strings I need to insert don't contain "=" symbol. I tried:
_sString = "[main].[tblProductFamilies].[ID] IN("+ ... +") And"
_sString = "IN("+ ... +")"
but both variants don't work(