A strange behavior of if-condition



  • Hi all,

    Please take a look at this example:

    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
        property var db
    
        TextField {
            id: field
            placeholderText: qsTr("Enter Your Name")
            hoverEnabled: true
        }
    
        Button {
            id: srch
            text: "Search Name"
            anchors.top: field.bottom
            onClicked:  {
                if(seekName(field.displayText))
                    console.log("Found")
                else
                    console.log("Not Found")
            }
        }
    
        Button {
            text: "Store Name"
            anchors.left: srch.right
            anchors.leftMargin: 10
            anchors.top: field.bottom
            onClicked: storeData(field.displayText)
        }
    
        Component.onCompleted: initDatabase()
    
        function initDatabase() {
            db = LocalStorage.openDatabaseSync("data", "1.0", "Save Usernames", 1000000)
            db.transaction( function(tx)
            { tx.executeSql('CREATE TABLE IF NOT EXISTS data(name TEXT)') })
        }
    
        function storeData(username) {
            if(!db) return
    
            db.transaction( function(tx) {
                tx.executeSql('INSERT INTO data VALUES (?)',[username])
            })
        }
    
        function seekName(username) {
            db.transaction( function(tx) {
    
                var result = tx.executeSql('SELECT * from data');
                for (var i=0; i<result.rows.length; ++i)
                    if(result.rows.item(i).name === username)
                        return true
                return false
            })
        }
    }
    

    If I put the name "Jack" and store it using the Store Name button, it'll be saved in the database. Then if the name is searched by the Search Name button, although the seekName function finds it and returns true, the code in the if part of: if(seekName(field.displayText)) won't be executed and the else part will be accomplished! I don't know why?


  • Lifetime Qt Champion

    Hi,

    From the Qt Quick Local Storage QML Types, transaction is not a synchronous operation so you can't do what you want the way you are trying to do it. You should refactor your code to the operation you want in the callback where you execute your SQL statement. Or call another function from there.



  • @SGaist
    Thank you for your answer.

    From the Qt Quick Local Storage QML Types, transaction is not a synchronous operation so you can't do what you want the way you are trying to do it.

    What do you mean by that, please? Does it mean the way I've learnt programming can't be valid when I'm dealing with SQL/databases?

    You should refactor your code to the operation you want in the callback where you execute your SQL statement.

    What callback do you mean? I didn't see a clear function in the link to be symbolized as callback, I suppose.

    Or call another function from there.

    From where, please? Inside the for loop in the seekName function?


  • Lifetime Qt Champion

    It has nothing to do with SQL programming but with how it's implemented in JavaScript.

    The function you wrote containing the for loop is the callback.

    You can either do it in the for loop, or after it. That's up to you.



  • @SGaist

    You can either do it in the for loop, or after it. That's up to you.

    1- I still don't know the reason why the true value returned by the function is not gotten and applied by that if. It must be to some extent related to SQL, because in a normal JavaScript code, the returned value is gotten and applied properly by the caller a function.

    2- Apparently, based on a hidden reason, I can't use the method in the code above to return true for that if condition, and have two alternatives as below.

    a) Embedding:

    function seekName(username) {
            db.transaction( function(tx) {
    
                var result = tx.executeSql('SELECT * from data');
                for (var i=0; i<result.rows.length; ++i)
                    if(result.rows.item(i).name === username)  {
                        console.log("Found")
                        return 
                     }
                console.log("Not Found")
               return false
            })
        }
    

    b) Or using another function to write the result.

    Right?


  • Lifetime Qt Champion

    As already written, db.transaction takes a callback. Your function is called at some point in time (even if very quickly).

    WARNING Note that this won't work as you can't pass username to the callback, it's only for example purpose.

    Written a bit differently:

    function doSeek(tx) {
        var result = tx.executeSql('SELECT * from data');
        for (var i=0; i<result.rows.length; ++i)
            if(result.rows.item(i).name === username)  {
                console.log("Found");
                return true;
           }
        console.log("Not Found");
        return false;
    }
    
    function seekName(username) {
            db.transaction(doSeek);
        }
    

    Do you see now why you can't get the true/false result ?

    [edit: Added some precision on the code content SGaist]



  • @SGaist

    Do you see now why you can't get the true/false result ?

    No, not yet, sadly! :|

    The first paradox:
    You said: "transaction is not a synchronous operation so you can't...", apparently the reason for not returning a true/false value from the for loop is related to SQL.
    Here, "It has nothing to do with SQL programming but with how it's implemented in JavaScript", seemingly the reason is not SQL, but JavaScript!

    The second paradox:
    In the above code you sent, username is not defined and if we use function doSeek(username) ... then tx won't be defined!



  • My other question is about the Qt Quick Local Storage reference. Docs explain it too briefly leaving many questions for the reader if they’re new in that.
    For example, I cannot find the exact command to modify the content of a specific row in the table. And there might be more questions.

    What reference do you use to work with Qt Quick Local Storage for QML apps, please?


  • Lifetime Qt Champion

    I've added the missing warning about the working state of the code. I wrote it so to show you how the logic is working not how to make it work the way you want as you can't have it anyway.

    Before going further: Do you know what a callback is and how it works ?

    Maybe this answer on stack overflow might be clearer.

    You're use a SQLite database, so you write SQL statement to read and write to your database. You have tutorials all over the web. See for example here.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.