Skip to content

Customize and Extend Core Databases Functionality

Have you ever debugged your Xojo database app and wondered about the SQL queries being executed and the parameters used? You are not alone. Whether you’re developing a desktop, web, or mobile app, having clear insight into your database interactions is crucial for effective debugging and ensuring your app functions correctly.

This article will show you how to automatically record queries and commands in any Xojo database class to help you debug and improve database operations by using method overriding. This will help you:

  • Debug SQL operations faster by seeing exactly what’s being executed.
  • Spot errors in your SQL queries or parameters before they become runtime issues.
  • Gain transparency into your app’s database behavior.

By the end of this tutorial, you’ll have a clear understanding of:

  • Method overriding: What it is and how you can use it to extend built-in Xojo classes.
  • Subclassing database classes: Learn how to develop a custom database class with added logging functionality to improve database management and tracking.
  • Logging SQL commands and parameters: Discover how to effectively capture and log database operations such as SELECT, INSERT, and DELETE to enhance visibility and improve database performance.

What is Method Overriding?

Method overriding, a fundamental concept in object-oriented programming (OOP), lets you customize how a subclass implements its superclass’s methods. In Xojo, this powerful feature allows you to enhance built-in classes without modifying their original code, ensuring you preserve core functionality while adding your own features.

How Method Overriding Works in Xojo

Let’s break it down step by step with a simple example. Imagine you’re working with the SQLiteDatabase class, and you want to modify the behavior of the ExecuteSQL method to log every SQL command executed.

  1. Create a Subclass:
    • Create a new class in Xojo and set its Super to SQLiteDatabase. This means your new class inherits all the properties and methods of SQLiteDatabase.
  2. Override the Method:
    • In your new subclass, define a method and from the Method Name picker, select ExecuteSQL.
    • Add your custom logic, like logging the SQL command to the Xojo debugger.
  3. Call the Original Method:
    • Use the Super keyword to call the original ExecuteSQL method in the superclass. This ensures the original behavior is preserved alongside your custom logic.

Extending Xojo’s SQLiteDatabase with Method Overriding

Let’s enhance Xojo’s SQLiteDatabase class by creating a subclass that automatically logs SELECT queries and their parameters. To make this process easier, use the built-in “Full-Text Searching 5” example project, which already includes various database operations.

1. Create the MySQLiteDatabase Subclass

  1. From the Insert menu, select Class.
  2. Name the new class MySQLiteDatabase.
  3. In the Inspector, set the Super field to SQLiteDatabase.

This tells Xojo that MySQLiteDatabase will inherit all the behavior of SQLiteDatabase, allowing you to override its methods.

2. Override the SelectSQL Method

Now, you’ll override the SelectSQL method in your MySQLiteDatabase class. This method is used for SELECT queries, so you’ll add logging to display the query and its parameters in the debugger.

Public Function SelectSQL(query As String, ParamArray values() As Variant) As RowSet
  // Log the SELECT query
  System.DebugLog("[DEBUG] SelectSQL called: " + query)
  
  // Log the parameters (if any)
  If values.LastIndex >= 0 Then
    Var stringValues() As String
    For Each v As Variant In values
      stringValues.Add(v.StringValue) // Convert Variant to String
    Next
    System.DebugLog("[DEBUG] Parameters: " + String.FromArray(stringValues, ", "))
  End If

  // Call the original SelectSQL method
  Try
    Return Super.SelectSQL(query, values)
  Catch error As DatabaseException
    // Log any errors
    System.DebugLog("[ERROR] DatabaseException: " + error.Message)
    Raise error // Re-raise the exception so the app can handle it
  End Try
End Function

3. Replace the Database Property

Now that you’ve created the MySQLiteDatabase subclass, you need to update the example project to use it.

  1. Open Window1 in the Project Browser.
  2. Locate the DB property in Window1. It is currently defined as DB As SQLiteDatabase:
  3. Change the type of DB from SQLiteDatabase to MySQLiteDatabase. To do this:
    • Select the DB property.
    • In the Inspector, update the Type field to MySQLiteDatabase.

Additionally, under the Opening event of Window1, change DB = New SQLiteDatabase to DB = New MySQLiteDatabase.

This replaces the original SQLiteDatabase with your custom subclass, ensuring all database operations now use your overridden SelectSQL method.


4. Test the Logging

With the subclass in place, run the project and test the logging functionality.

  1. Run the project.
  2. Perform a search in the app’s UI. Each search generates a SELECT query using the SelectSQL method.
  3. Check Xojo’s Messages Panel for output. You should see the SQL query and its parameters logged.

Example Output:

[DEBUG] SelectSQL called: SELECT highlight(ftstest, 0, '<', '>') FROM ftstest WHERE ftstest MATCH 'know' ORDER BY rank;

Additional Enhancements

Now that you’ve created a foundation for extending Xojo’s database classes by logging queries with your custom subclass, it’s time to think about how you can take this further. Below are several ideas for additional enhancements that will make your subclass more robust, versatile, and useful for debugging and performance monitoring.

Log Additional Methods

While you’ve started with the SelectSQL method, your app likely performs other database operations, such as INSERTUPDATEDELETE, or even transactions. You can override methods like ExecuteSQL to log these operations along with their parameters. Extending the logging functionality to these key methods ensures a complete picture of all database activity.

Additionally, logging transactional methods like BeginTransactionCommitTransaction, and RollbackTransaction can help you trace when database changes are grouped together and ensure data integrity.

Tip: You can incorporate the Log4Xojo project.

Support for Multiple Database Classes

If your app uses different database types, such as MySQLCommunityServer or PostgreSQLDatabase, you can generalize your logging functionality to work with all of them. This can be achieved by creating a base class for logging that inherits from Database and then extending it for specific database types. This approach ensures consistency and reusability across different database systems.

Monitor Query Performance

Tracking the time it takes for queries to execute can give you valuable insights into your application’s performance. By measuring the duration of each query, you can identify slow queries and optimize them for better efficiency. Additionally, you could log a warning if a query takes longer than a specified threshold, helping you catch performance issues early.

Automatically Retry Failed Queries

Sometimes, database operations fail due to transient errors, such as network interruptions or locked tables. Implementing retry logic for failed queries can make your app more resilient. For example, you could attempt a query up to three times before logging it as a failure. This is particularly useful for apps that rely on remote database servers, where connectivity issues are more likely.

Add Context-Specific Metadata

Including additional context in your logs can make them more meaningful. For example, you might log:

  • The name of the method or function that triggered the query.
  • The user ID or session ID (if applicable) for tracking user-specific database activity.
  • Tags or labels to group related queries or transactions.

This kind of metadata makes it easier to understand the “why” behind a query, not just the “what.”


Wrapping It All Up

Congratulations! You’ve taken a deep dive into one of the most powerful techniques in Xojo development: extending built-in classes, like SQLiteDatabase, to meet your specific needs. By following the steps in this tutorial, you’ve learned how to override methods, create a custom database subclass, and log SQL queries for better debugging and transparency.

What’s Next?

If you enjoyed this tutorial, we’d love to hear from you! Share your thoughts, your customizations, or any challenges you faced in the Xojo forums. If you’ve built something amazing using this technique, let us know—we’d love to feature your work in our community showcase.

Keep coding, keep innovating, and as always, happy developing! 🚀

Gabriel is a digital marketing enthusiast who loves coding with Xojo to create cool software tools for any platform. He is always eager to learn and share new ideas!