Skip to content
Trevor DeVore edited this page Oct 23, 2018 · 3 revisions

Error handling

SQL Yoga handlers will throw errors if the error is a development error or if it is a database connection error. A development error means that the error is caused because you have misconfigured something or are trying to use the API incorrectly.

Here is a list of error numbers that are thrown and the constant used in SQL Yoga which describes the error. The error number is the number used by LiveCode to report specific errors.

Error Number Description
422 kErrInvalidArray
452 kErrInvalidBoolean
453 kErrInvalidNumber
456 kErrPropDoesntExist
354 kErrInvalidInteger
355 kErrInvalidPoint
356 kErrInvalidRect
449 kErrReadOnlyProp
348 kErrInvalidProperty
619 kErrCantFindObject
487 kErrRenameErrorInDestination
132 kErrObjectNameTaken
238 kErrInvalidGroupObject
219 kErrErrorInFunction

In addition to the general LiveCode errors above, SQL Yoga will also throw errors specific to SQL Yoga. Errors have one of the following prefixes, followed by a ,, followed by the specific error message.

Error Prefix Description
sqlyoga_connection_err An error occurred while trying to connect to the database.
sqlyoga_executesql_err An error occurred while trying to execute a SQL statement.

Handling thrown errors

There are two ways to handle errors that are thrown. The first is to wrap all calls to handlers that execute SQL statements or connect to the database with a try/catch statement:

try
  dbconn_connect
catch e
  answer "An error occurred while connecting to the database:" && e
end try

Another approach is to define your own errorDialog handler somewhere in the message path (e.g. a library script). When your app is running in the IDE you can pass the errorDialog message and allow the IDE to report the error to you using the IDE error reporter.

When your app is running as a standalone you can define how you want to respond to errors at a global level. For example, if the database connection is invalid and a sqlyoga_connection_err error is thrown you may want to provide a custom error dialog explaining the problem.

# Card script
on openCard
  # No try/catch around handler that can throw an error
  ...
  dbconn_connect
  ...
end openCard

# library script (e.g. app.livecodescript in a Levure application)
on errorDialog pError
  # Let the IDE display the error in development
  if the environment is "development" then pass errorDialog

  switch item 1 of pError 
    case "sqlyoga_connection_err"
      # handle connection error here
      break
    case "sqlyoga_executesql_err"
      # handle sql execution error here
      break
  end switch
end errorDialog

Handling thrown errors within a transaction

When you call dbconn_beginTransaction in your code then no changes your code makes to the database will be saved until you call dbconn_commitTransaction. For example:

dbconn_beginTransaction

# Make multiple changes to the database that should only be saved if all changes are successful.
sqlrecord_update ...
sqlrecord_update ...
sqlrecord_update ...

# Save changes
dbconn_commitTransaction

What happens if one your database updates throws an error? If neither dbconn_commitTransaction or dbconn_rollbackTransaction are called then your database is left with an open transaction that needs to be closed before changes to the database will be saved.

If an error is thrown due to a connection issue (sqlyoga_connection_err,ERR) then you don't need to worry about the open transaction. Since the connnection is broken then you no longer have control over what happens to the transaction.

If you set an invalid property on a SQL Yoga object or a sqlyoga_executesql_err,ERR error is thrown then you are responsible for closing the transaction. These errors will (always?) be caused by a developer error (e.g. you didn't cleanse input or made a programming error while working on the application).

One approach is to wrap all of your code that makes updates in a try/catch statement. In the finally section (or just after the try control structure) you can rethrow any errors that occur after properly ending the transaction. Here is an example:

local tError

dbconn_beginTransaction

# Make multiple changes to the database that should only be saved if all changes are successful.
try
  sqlrecordUpdate ...
  sqlrecordUpdate ...
  sqlrecordUpdate ...
catch tError

finally
  # Save changes
  if tError is empty then
    dbconn_commitTransaction
  else
    dbconn_rollbackTransaction
    # Rethrow the error so that the errorDialog message can handle it.
    throw tError
  end if
end catch