Search code examples
sqlsqlitegdscript

Passing a string variable in SQLite with GDScript


I have a question about SQLite in GDScript.

I wanted to print one query result to debug but I cannot find the way to do it.

In my code I have:

var tableName = "users"
db.query("SELECT username, email FROM " + tableName + " WHERE username=?;" + (username))

I cannot pass the username as "username", what is the correct way to do it?

I also try this:

var tableName = "users"
db.query("SELECT username, email FROM " + tableName + " WHERE username= " + username + ";")

And this:

var tableName = "users"
db.query("SELECT username, email FROM " + tableName + " WHERE username = " + 'username' + ";")

By the way, im getting the username from this:

var username = $NinePatchRect/VBoxContainer/username.get_text()

I've printed and the variable username is fine.

Thank you all!


Solution

  • What to do

    The proper way to do this, is with prepared statements and argument bindings. You need to find a way to do that with whatever solution you are using.


    If you are using this solution: 2shady4u/godot-sqlite (Which is available from the Godot Asset Library, here). Do the following:

    var query = "SELECT username, email FROM " + tableName + " WHERE username=?;"
    db.query_with_bindings(query, [username])
    

    Which should use prepared statements and argument bindings behind the scenes. Source.


    If you are using this solution: godot-extended-libraries/godot-sqlite (towards which the Godot Core developers contributed). Do the following:

    var query = "SELECT username, email FROM " + tableName + " WHERE username=?;"
    db.query_with_args(query, [username])
    

    Which should use prepared statements and argument bindings behind the scenes. Source.


    If you are using this solution: khairul169/gdsqlite-native (which is an older project). Do the following:

    var query = "SELECT username, email FROM " + tableName + " WHERE username=?;"
    db.query_with_args(query, PoolStringArray([username]))
    

    Which should use prepared statements and argument bindings behind the scenes. Source.


    If you are using another solution, please figure out how to use prepared statements with it. And if there is no way to do it, please switch to a solution that supports them, such as the ones linked above.


    What NOT to do, and why

    SQLite needs the strings between quotation marks.

    A common way to put quotation marks in Godot is by writing your string between ' instead of ".

    For example:

    print('Hello "World"')
    

    Should print Hello "World".

    Alternatively, you can use escape sequences:

    print("Hello \"World\"")
    

    Which should also print Hello "World".


    Thus, you can - please don't - make your query like this:

    db.query("SELECT username, email FROM " + tableName + " WHERE username= \"" + username + "\";")
    

    Then if the user typed:

    peter
    

    The query would be built like this (And let us say tableName is users):

    SELECT username, email FROM users WHERE username= "peter";
    

    And you would have a SQL injection vulnerability. If the user writes a quotation mark, then the rest of the string will be considered part of the query.

    For example if the user writes

    " or "" = "
    

    The query will be built like this:

    SELECT username, email FROM users WHERE username= "" or "" = "";
    

    And that will return all users. And that is just an example of what they could write, because remember they would be writing SQL.

    Prepared statements avoids the vulnerability. And not by string tricks, but by proper support. And without the hassle. Please use prepared statements.