ryanfowler / SwiftData

Simple and Effective SQLite Handling in Swift
MIT License
517 stars 93 forks source link

Check return value of transaction closure #8

Open eriktelepovsky opened 9 years ago

eriktelepovsky commented 9 years ago

Hi,

public static func transaction(transactionClosure: ()->Bool) -> Int? returns an Int with the error code, or nil if there was no error committing or rolling back the transaction.

But is it possible to check somehow if the transaction was committed or rollbacked?

eriktelepovsky commented 9 years ago

Something like this:

/**
    Execute commands within a single exclusive transaction

    ...

    :returns:
        - Bool with true, if transaction was commited, false otherwise
        - An Int with the error code, or nil if there was no error committing or rolling back the transaction
*/
public static func betterTransaction(transactionClosure: ()->Bool) -> (Bool, Int?) {

    // create result variable
    var commited: Bool = false

    ...

    // execute the transaction closure
    if transactionClosure() {
        if let err = SQLiteDB.sharedInstance.commitTransaction() {
            error = err
        } else {
            commited = true
        }
    } else {
        if let err = SQLiteDB.sharedInstance.rollbackTransaction() {
            error = err
        }
    }

    ...

    return (commited, error)
}
ryanfowler commented 9 years ago

Thanks for the feedback; I see your point here.

The transactionClosure that you pass to SD.transaction returns true (to commit the transaction) or false (to rollback the transaction). Instead of adding complexity for most people by returning a tuple, I would suggest adding a variable in your program and changing it in your closure like so:

var transactionCommitted = false

let err = SD.transaction {
    // interact with database here

    if youWantToCommit {
        transactionCommitted = true
        return true
    } else {
        return false
    }
}

if err != nil {
    // there was an error 
    // transactionCommitted will tell you if you attempted to commit or rollback the transaction
}

After your call to SD.transaction, the transactionCommitted variable will indicate if the transaction attempted to commit or rollback.

Let me know if you disagree.

eriktelepovsky commented 9 years ago

Hi, thank you for your answer, but I think we misunderstand each other. Your SD.transaction function returns an Int with the error code, or nil if there was no error committing or rolling back the transaction. I need to know if the error code (if any) is from this part of code:

if let err = SQLiteDB.sharedInstance.commitTransaction() {
   error = err
}

or from this:

if let err = SQLiteDB.sharedInstance.rollbackTransaction() {
   error = err
}

Right now I only know if there was or wasn't any error during execution of SD.transaction(), but I don't know when was the error created.

hadasaOrit commented 9 years ago

Hi, if I have many rows in my database, how can I choose just the first row? or how can I make sure that I will have only one row? And one more thing- Where can I see the data base? Does it exist anywhere? Thank! Great job!

ryanfowler commented 9 years ago

@eriktelepovsky Ok, I understand what you mean now ...

I think the most appropriate way to deal with this is to have better error handling. I'm hoping to have an improved version of SwiftData out in a few weeks and will keep this in mind.

ryanfowler commented 9 years ago

@hadasaOrit For your first question, all queries will return an Array of SDRow objects. If you'd only like one row, you can just use the first item of the returned Array, or specify in your SQL query that you'd only like one row returned:

SELECT * FROM sample LIMIT 1

The database called 'SwiftData.sqlite' exists in the 'documents' directory of the device.