<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>SQL &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/tag/sql/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Mon, 18 Aug 2025 20:40:26 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>
	<item>
		<title>Introduction to PocketBase: A Backend Alternative for Xojo Developers</title>
		<link>https://blog.xojo.com/2025/02/19/introduction-to-pocketbase-a-backend-alternative-for-xojo-developers/</link>
		
		<dc:creator><![CDATA[Ezekiel Burke]]></dc:creator>
		<pubDate>Wed, 19 Feb 2025 16:02:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PocketBase]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14488</guid>

					<description><![CDATA[Introduction When developing applications with Xojo, choosing the right backend is crucial for managing data efficiently. Traditionally, Xojo developers rely on SQL databases such as&#8230;]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>When developing applications with Xojo, choosing the right backend is crucial for managing data efficiently. Traditionally, Xojo developers rely on SQL databases such as SQLite, MySQL, or PostgreSQL for their desktop, web, and mobile applications. However, there is an alternative that provides a more flexible and modern approach to backend development: <a href="https://pocketbase.io/" target="_blank" rel="noreferrer noopener">PocketBase</a>.</p>



<p>PocketBase is an open-source backend perfect for your multi-platform Xojo application. It offers a simple-to-use API and a built-in admin panel to manage the data from any web browser. No other tool such as MySQL, Workbench, or SQL Studio is needed. In this post, I will explain how it compares to traditional SQL databases and demonstrate how to integrate it into a Xojo project.</p>



<h3 class="wp-block-heading">Why Choose PocketBase for Your Xojo App Backend?</h3>



<p>PocketBase is a lightweight, self-hosted backend designed for simplicity and flexibility. Unlike traditional SQL databases that require a separate backend service or API layer, PocketBase is an all-in-one solution that combines the database and API.</p>



<h3 class="wp-block-heading">Key Features:</h3>



<p>Embedded Database – Powered by SQLite, eliminating the need for a separate database server.</p>



<p>Built-in User Authentication – Supports email/password logins, OAuth2 sign-ups, and one-time password (OTP) with minimal setup.</p>



<p>File Storage – Store and retrieve files locally or via S3.</p>



<p>Cross-Platform Compatibility – Runs on macOS, Windows, and Linux. Can communicate via URLConnection making it ideal for Xojo’s desktop, web, and mobile platforms.</p>



<p>Easy Deployment – A single binary file that can be self-hosted or deployed anywhere with minimal configuration.</p>



<h2 class="wp-block-heading">Setting Up PocketBase for a Xojo App</h2>



<p>To get started, I have simplified some steps below. If you get stuck or want more in-depth instructions take a look at the <a href="https://pocketbase.io/docs/" target="_blank" rel="noreferrer noopener">documentation</a>.</p>



<ul class="wp-block-list">
<li>Download PocketBase
<ul class="wp-block-list">
<li>Visit <a href="https://pocketbase.io/" target="_blank" rel="noreferrer noopener">PocketBase</a> and download the latest release for your operating system.</li>



<li>Extract the files to your project directory.</li>
</ul>
</li>



<li>Run PocketBase
<ul class="wp-block-list">
<li>Start the PocketBase server by navigating to the extracted folder in the command prompt/terminal.</li>



<li>Run the command: <code>./pocketbase serve</code> to start the server.</li>
</ul>
</li>



<li>Access the Admin Panel
<ul class="wp-block-list">
<li>Open <code>http://127.0.0.1:8090/_/</code> in a web browser and set up an admin account.</li>
</ul>
</li>



<li>Add a User
<ul class="wp-block-list">
<li>In the PocketBase admin panel, create a new record in the users collection. (Collections are the equivalent of a table in SQL.)</li>
</ul>
</li>
</ul>



<h2 class="wp-block-heading">Connect Xojo to PocketBase</h2>



<p>Now that your PocketBase server is running, integrate authentication into your Xojo desktop app. In this example, we will handle authentication in the open event of the main window. This will demonstrate how Xojo interacts with PocketBase’s authentication API.</p>



<h3 class="wp-block-heading">Implement the Login Request</h3>



<p>Add the following code to the open event of your main window:</p>



<pre class="wp-block-code"><code>Var userEmail As String = "email@email.com"
Var userPassword As String = "MyPassword!"
Var loginURL As String = "http://127.0.0.1:8090" + "/api/collections/users/auth-with-password"
Var conn As New URLConnection
conn.RequestHeader("Content-Type") = "application/json"
 
Var loginPayload As New JSONItem
loginPayload.Value("identity" ) = userEmail
loginPayload.Value("password") = userPassword
conn.SetRequestContent(loginPayload.ToString, "application/json")
 
Var loginResponse As String = conn.SendSync("POST", loginURL)
Var jsonResponse As New JSONItem(loginResponse)
Var userInfo As JSONItem = jsonResponse.Lookup("record", New JSONItem)
Var userID As String = userInfo.Lookup("id", "")
Var authToken As String = jsonResponse.Lookup("token", "")
 
If authToken.Length > 0 Then
  MessageBox("Login successful! Welcome, User ID: " + userID)
Else
  MessageBox("Login failed. Please check your credentials.")
End If</code></pre>



<h3 class="wp-block-heading">Update Your Credentials and URL</h3>



<p>Replace userEmail and userPassword with the credentials you used to create a user in PocketBase. Also, ensure the loginURL matches your PocketBase instance (without <code>/_/</code> at the end).</p>



<h3 class="wp-block-heading">Run The App</h3>



<p>Launch your Xojo app. If authentication is successful, a message box will display the user&#8217;s ID. Otherwise, you will see an error message indicating that the credentials are incorrect.</p>



<h3 class="wp-block-heading">Wrapping Up</h3>



<p>In this article, you have successfully set up a PocketBase server, created a record, and integrated authentication into your Xojo app. PocketBase simplifies backend development by handling authentication and data storage—all without the need for a traditional SQL database.</p>



<p>With PocketBase, there is no need to set up complex user tables, hash passwords, or build a custom API. Collections can be easily managed directly from the web via the admin panel. This means you can spend less time managing infrastructure and more time focusing on bringing your app to market.</p>



<p>To help you get started, I’ve created a collection of example projects, which you can find here:</p>



<p><a href="https://github.com/Iron-Elephant-Solutions/Xojo-Pocketbase-Examples">Xojo-Pocketbase-Examples</a></p>



<p>If you’d like to discuss how Iron Elephant Solutions has used Xojo and PocketBase in real-world applications, feel free to reach out through our <a href="https://ironelephantsolutions.com/">website</a> or add me on <a href="https://www.linkedin.com/in/ezekiel-zeke-burke/">LinkedIn</a>.</p>



<p><a href="https://www.linkedin.com/in/ezekiel-zeke-burke/overlay/about-this-profile/" target="_blank" rel="noreferrer noopener">Ezekiel Burke</a><em> is the founder of <a href="https://ironelephantsolutions.com/" target="_blank" rel="noreferrer noopener">Iron Elephant Solutions</a>. He focuses on building custom, scalable, and affordable software that helps businesses work smarter. With 15+ years of experience, he specializes in full-stack development, process automation and systems integration, creating solutions that simplify complex workflows.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Customize and Extend Core Databases Functionality</title>
		<link>https://blog.xojo.com/2025/02/05/customize-and-extend-core-databases-functionality/</link>
		
		<dc:creator><![CDATA[Gabriel Ludosanu]]></dc:creator>
		<pubDate>Wed, 05 Feb 2025 19:00:33 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Method Overriding]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Subclassing]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14396</guid>

					<description><![CDATA[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&#8230;]]></description>
										<content:encoded><![CDATA[
<p>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.</p>



<p>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:</p>



<ul class="wp-block-list">
<li>Debug SQL operations faster by seeing exactly what’s being executed.</li>



<li>Spot errors in your SQL queries or parameters before they become runtime issues.</li>



<li>Gain transparency into your app’s database behavior.</li>
</ul>



<p>By the end of this tutorial, you’ll have a clear understanding of:</p>



<ul class="wp-block-list">
<li><strong>Method overriding</strong>: What it is and how you can use it to extend built-in Xojo classes.</li>



<li><strong>Subclassing database classes:</strong>&nbsp;Learn how to develop a custom database class with added logging functionality to improve database management and tracking.</li>



<li><strong>Logging SQL commands and parameters:</strong>&nbsp;Discover how to effectively capture and log database operations such as SELECT, INSERT, and DELETE to enhance visibility and improve database performance.</li>
</ul>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="what-is-method-overriding"><strong>What is Method Overriding?</strong></h3>



<p>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.</p>



<h4 class="wp-block-heading" id="how-method-overriding-works-in-xojo"><strong>How Method Overriding Works in Xojo</strong></h4>



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



<ol class="wp-block-list">
<li><strong>Create a Subclass</strong>:
<ul class="wp-block-list">
<li>Create a new class in Xojo and set its Super to&nbsp;<code>SQLiteDatabase</code>. This means your new class inherits all the properties and methods of&nbsp;<code>SQLiteDatabase</code>.</li>
</ul>
</li>



<li><strong>Override the Method</strong>:
<ul class="wp-block-list">
<li>In your new subclass, define a method and from the Method Name picker, select&nbsp;<code>ExecuteSQL</code>.</li>



<li>Add your custom logic, like logging the SQL command to the Xojo debugger.</li>
</ul>
</li>



<li><strong>Call the Original Method</strong>:
<ul class="wp-block-list">
<li>Use the&nbsp;<code>Super</code>&nbsp;keyword to call the original&nbsp;<code>ExecuteSQL</code>&nbsp;method in the superclass. This ensures the original behavior is preserved alongside your custom logic.</li>
</ul>
</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="extending-xojo’s-sqlitedatabase-with-method-overriding"><strong>Extending Xojo’s SQLiteDatabase with Method Overriding</strong></h3>



<p>Let’s enhance Xojo’s <code>SQLiteDatabase</code> class by creating a subclass that automatically logs <code>SELECT</code> 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.</p>


<div class="wp-block-image">
<figure class="aligncenter size-medium"><img fetchpriority="high" decoding="async" width="300" height="294" src="https://blog.xojo.com/wp-content/uploads/2025/01/xojo-full-search-database-example-300x294.webp" alt="" class="wp-image-14399" srcset="https://blog.xojo.com/wp-content/uploads/2025/01/xojo-full-search-database-example-300x294.webp 300w, https://blog.xojo.com/wp-content/uploads/2025/01/xojo-full-search-database-example-768x753.webp 768w, https://blog.xojo.com/wp-content/uploads/2025/01/xojo-full-search-database-example.webp 1006w" sizes="(max-width: 300px) 100vw, 300px" /></figure>
</div>


<h4 class="wp-block-heading" id="create-the-mysqlitedatabase-subclass"><strong>1. Create the</strong>&nbsp;<code>MySQLiteDatabase</code>&nbsp;<strong>Subclass</strong></h4>



<ol class="wp-block-list">
<li>From the Insert menu, select Class.</li>



<li>Name the new class&nbsp;<code>MySQLiteDatabase</code>.</li>



<li>In the Inspector, set the Super field to <code>SQLiteDatabase</code>.</li>
</ol>



<p>This tells Xojo that&nbsp;<code>MySQLiteDatabase</code>&nbsp;will inherit all the behavior of&nbsp;<code>SQLiteDatabase</code>, allowing you to override its methods.</p>



<h4 class="wp-block-heading" id="override-the-selectsql-method"><strong>2. Override the</strong>&nbsp;<code>SelectSQL</code>&nbsp;<strong>Method</strong></h4>



<p>Now, you’ll override the&nbsp;<code>SelectSQL</code>&nbsp;method in your&nbsp;<code>MySQLiteDatabase</code>&nbsp;class. This method is used for&nbsp;<code>SELECT</code>&nbsp;queries, so you’ll add logging to display the query and its parameters in the debugger.</p>



<pre class="wp-block-code"><code>Public Function SelectSQL(query As String, ParamArray values() As Variant) As RowSet
  // Log the SELECT query
  System.DebugLog("&#91;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("&#91;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("&#91;ERROR] DatabaseException: " + error.Message)
    Raise error // Re-raise the exception so the app can handle it
  End Try
End Function</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading" id="replace-the-database-property"><strong>3. Replace the Database Property</strong></h4>



<p>Now that you’ve created the&nbsp;<code>MySQLiteDatabase</code>&nbsp;subclass, you need to update the example project to use it.</p>



<ol class="wp-block-list">
<li>Open <code>Window1</code> in the Project Browser.</li>



<li>Locate the&nbsp;<code>DB</code>&nbsp;property in&nbsp;<code>Window1</code>. It is currently defined as&nbsp;<code>DB As SQLiteDatabase</code>:</li>



<li>Change the type of&nbsp;<code>DB</code>&nbsp;from&nbsp;<code>SQLiteDatabase</code>&nbsp;to&nbsp;<code>MySQLiteDatabase</code>. To do this:
<ul class="wp-block-list">
<li>Select the&nbsp;<code>DB</code>&nbsp;property.</li>



<li>In the Inspector, update the Type field to <code>MySQLiteDatabase</code>.</li>
</ul>
</li>
</ol>



<p>Additionally, under the Opening event of Window1, change&nbsp;<code>DB = New SQLiteDatabase</code>&nbsp;to&nbsp;<code>DB = New MySQLiteDatabase</code>.</p>



<p>This replaces the original&nbsp;<code>SQLiteDatabase</code>&nbsp;with your custom subclass, ensuring all database operations now use your overridden&nbsp;<code>SelectSQL</code>&nbsp;method.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h4 class="wp-block-heading" id="test-the-logging"><strong>4. Test the Logging</strong></h4>



<p>With the subclass in place, run the project and test the logging functionality.</p>



<ol class="wp-block-list">
<li>Run the project.</li>



<li>Perform a search in the app’s UI. Each search generates a&nbsp;<code>SELECT</code>&nbsp;query using the&nbsp;<code>SelectSQL</code>&nbsp;method.</li>



<li>Check Xojo’s Messages Panel for output. You should see the SQL query and its parameters logged.</li>
</ol>



<p>Example Output:</p>



<pre class="wp-block-code"><code>&#91;DEBUG] SelectSQL called: SELECT highlight(ftstest, 0, '&lt;', '>') FROM ftstest WHERE ftstest MATCH 'know' ORDER BY rank;</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="additional-enhancements"><strong>Additional Enhancements</strong></h3>



<p>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.</p>



<h4 class="wp-block-heading" id="log-additional-methods"><strong>Log Additional Methods</strong></h4>



<p>While you’ve started with the&nbsp;<code>SelectSQL</code>&nbsp;method, your app likely performs other database operations, such as&nbsp;<code>INSERT</code>,&nbsp;<code>UPDATE</code>,&nbsp;<code>DELETE</code>, or even transactions. You can override methods like&nbsp;<code>ExecuteSQL</code>&nbsp;to log these operations along with their parameters. Extending the logging functionality to these key methods ensures a complete picture of all database activity.</p>



<p>Additionally, logging transactional methods like&nbsp;<code>BeginTransaction</code>,&nbsp;<code>CommitTransaction</code>, and&nbsp;<code>RollbackTransaction</code>&nbsp;can help you trace when database changes are grouped together and ensure data integrity.</p>



<p>Tip: You can incorporate the&nbsp;<a href="https://blog.xojo.com/2024/11/26/log4xojo-a-more-powerful-way-to-manage-your-app-logging/" target="_blank" rel="noreferrer noopener">Log4Xojo project</a>.</p>



<h4 class="wp-block-heading" id="support-for-multiple-database-classes"><strong>Support for Multiple Database Classes</strong></h4>



<p>If your app uses different database types, such as&nbsp;<code>MySQLCommunityServer</code>&nbsp;or&nbsp;<code>PostgreSQLDatabase</code>, 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&nbsp;<code>Database</code>&nbsp;and then extending it for specific database types. This approach ensures consistency and reusability across different database systems.</p>



<h4 class="wp-block-heading" id="monitor-query-performance"><strong>Monitor Query Performance</strong></h4>



<p>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.</p>



<h4 class="wp-block-heading" id="automatically-retry-failed-queries"><strong>Automatically Retry Failed Queries</strong></h4>



<p>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.</p>



<h4 class="wp-block-heading" id="add-context-specific-metadata"><strong>Add Context-Specific Metadata</strong></h4>



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



<ul class="wp-block-list">
<li>The name of the method or function that triggered the query.</li>



<li>The user ID or session ID (if applicable) for tracking user-specific database activity.</li>



<li>Tags or labels to group related queries or transactions.</li>
</ul>



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



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading" id="wrapping-it-all-up"><strong>Wrapping It All Up</strong></h3>



<p>Congratulations! You’ve taken a deep dive into one of the most powerful techniques in Xojo development: extending built-in classes, like&nbsp;<code>SQLiteDatabase</code>, 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.</p>



<h3 class="wp-block-heading"><strong>What’s Next?</strong></h3>



<p>If you enjoyed this tutorial, we’d love to hear from you! Share your thoughts, your customizations, or any challenges you faced in the&nbsp;<a href="https://forum.xojo.com/" target="_blank" rel="noreferrer noopener">Xojo forums</a>. If you’ve built something amazing using this technique, let us know—we’d love to feature your work in our community showcase.</p>



<p>Keep coding, keep innovating, and as always, happy developing! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f680.png" alt="🚀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p><em>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!</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>The Power of Transactions in SQLite with Xojo</title>
		<link>https://blog.xojo.com/2024/06/12/the-power-of-transactions-in-sqlite-with-xojo/</link>
		
		<dc:creator><![CDATA[Martin T.]]></dc:creator>
		<pubDate>Wed, 12 Jun 2024 16:06:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13056</guid>

					<description><![CDATA[SQLite is a powerful, serverless database engine widely used in various applications. Transactions in SQLite play a crucial role in ensuring data integrity and consistency.&#8230;]]></description>
										<content:encoded><![CDATA[
<p>SQLite is a powerful, serverless database engine widely used in various applications. Transactions in SQLite play a crucial role in ensuring data integrity and consistency. In Xojo, SQLiteDatabase.BeginTransaction, SQLiteDatabase.CommitTransaction, and SQLiteDatabase.RollbackTransaction provide easy ways to manage transactions.</p>



<h2 class="wp-block-heading">What are Transactions?</h2>



<p>A transaction is a sequence of SQL commands executed as a single unit, adhering to the <a href="https://en.wikipedia.org/wiki/ACID">ACID</a> properties:</p>



<ul class="wp-block-list">
<li>Atomicity: All or none of the changes are applied.</li>



<li>Consistency: The database remains in a valid state.</li>



<li>Isolation: Concurrent transactions do not interfere with each other. </li>



<li>Durability: Once committed, changes are permanent.</li>
</ul>



<h2 class="wp-block-heading">Basic Transaction Commands</h2>



<p>SQLite supports three main commands for transactions:</p>



<ul class="wp-block-list">
<li>BEGIN TRANSACTION: Starts a new transaction.</li>



<li>COMMIT: Finalizes changes and makes them permanent.</li>



<li>ROLLBACK: Reverts changes made since the last BEGIN TRANSACTION. </li>
</ul>



<h3 class="wp-block-heading">Sample in Xojo</h3>



<p>Let’s consider a banking application where money is transferred between accounts. Without transactions, inconsistencies might occur. For example, if the first update (deducting money from one account) succeeds but the second update (adding money to another account) fails, the database will be left in an inconsistent state, reflecting a transfer that didn’t fully happen. Using transactions ensures that both updates either succeed or fail together, maintaining consistency. </p>



<pre id="xojo" class="wp-block-code"><code>Var db As New SQLiteDatabase
db.DatabaseFile = FolderItem.ShowOpenFileDialog("bank.db")
If db.Connect Then
  Try
    db.BeginTransaction
    db.ExecuteSQL("UPDATE accounts SET balance=balance-100 WHERE account_number=123")
    db.ExecuteSQL("UPDATE accounts SET balance=balance+100 WHERE account_number=456")
    db.CommitTransaction
  Catch e As DatabaseException
    db.RollbackTransaction
    MessageBox("Transaction failed: " + e.Message)
  End Try
Else
  MessageBox("Failed to connect to the database")
End If</code></pre>



<p>In this example, BeginTransaction starts the transaction. The UPDATE commands perform the transfer. If successful, CommitTransaction finalizes the changes. If an error occurs, RollbackTransaction reverts all changes.</p>



<h2 class="wp-block-heading">Advanced Transaction Control</h2>



<p>SQLite also offers advanced transaction modes: DEFERRED, IMMEDIATE, and EXCLUSIVE.</p>



<ul class="wp-block-list">
<li>DEFERRED: Default mode, acquires a write lock only when the first write operation occurs.</li>



<li>IMMEDIATE: Acquires a write lock immediately upon transaction start. </li>



<li>EXCLUSIVE: Prevents all other read and write operations during the transaction.</li>
</ul>



<p>Choosing the transaction type depends on the application’s specific requirements. DEFERRED balances concurrency and consistency, while IMMEDIATE and EXCLUSIVE provide higher isolation at the cost of concurrency.</p>



<h3 class="wp-block-heading">Example of Advanced Transaction</h3>



<pre id="xojo" class="wp-block-code"><code>If db.Connect Then
  Try
    db.ExecuteSQL("BEGIN IMMEDIATE TRANSACTION")

    ' Perform read and write operations here

    db.CommitTransaction
  Catch e As DatabaseException
    db.RollbackTransaction
    MessageBox("Transaction failed: " + e.Message)
  End Try
Else
  MessageBox("Failed to connect to the database")
End If</code></pre>



<p>In this example, an IMMEDIATE transaction ensures exclusive access from the start.</p>



<h2 class="wp-block-heading">Transaction Speed Considerations</h2>



<p>The speed of transactions in SQLite can be influenced by various factors:</p>



<ul class="wp-block-list">
<li>Batching Operations: Grouping multiple operations in a single transaction can significantly improve performance.</li>



<li>Disk I/O: The underlying storage medium and its I/O performance impact transaction speed.</li>



<li>Transaction Type: IMMEDIATE and EXCLUSIVE transactions might be slower due to locking mechanisms but provide higher isolation.</li>
</ul>



<p>Batching multiple operations into a single transaction reduces the overhead of repeatedly acquiring and releasing locks, leading to faster execution.</p>



<h2 class="wp-block-heading">Benefits of Using Transactions</h2>



<p>Using transactions offers numerous benefits:</p>



<ol class="wp-block-list">
<li>Atomicity: Prevents the database from being left in an inconsistent state due to partial updates.</li>



<li>Consistency: Ensures the integrity of the database by transitioning only to valid states.</li>



<li>Isolation: Prevents interference between concurrent transactions. </li>



<li>Durability: Ensures that committed changes are permanent, even in the event of a system failure.</li>
</ol>



<p>By understanding and applying transactions, developers can create robust applications that handle data modifications seamlessly, minimizing the risk of errors and inconsistencies.</p>



<p>Based on the <a href="https://ducklet.app/blog/2024/01/17/the-power-of-transactions-in-sqlite/">Ducklet Blog</a> article. Happy coding!</p>



<p><em>Martin T. is a Xojo MVP and has been very involved in testing Android support.</em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Docker, Database Servers and Xojo</title>
		<link>https://blog.xojo.com/2024/06/03/docker-database-servers-and-xojo/</link>
		
		<dc:creator><![CDATA[Jürg Otter]]></dc:creator>
		<pubDate>Mon, 03 Jun 2024 16:15:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[cubeSQL]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12939</guid>

					<description><![CDATA[There are many ways to develop with Xojo and use Database Servers. You might be working on a multi user Desktop Application that stores data in a Database. Or you're creating a multi user Xojo Web Application that needed to be scaled up to a couple of running instances - and use a Database for data storage. Or maybe you've written a mobile application that connects to a Backend REST API - again possibly written in Xojo (e.g. with the open source Express, or with Xojo Web).]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Xojo and Database Servers</h2>



<p>There are many ways to develop with Xojo and use database servers. You might be working on a multi-user desktop application that stores data in a database. Or you&#8217;re creating a multi-user Xojo Web application that needed to be scaled up to a couple of running instances &#8211; and use a database for data storage. Or maybe you&#8217;ve written a mobile application that connects to a Backend REST API &#8211; again possibly written in Xojo (e.g. with the open source <a href="https://github.com/sworteu/Express">Express</a>, or with <a href="https://xojo.com/products/web.php">Xojo Web</a>).</p>



<h3 class="wp-block-heading">As a Developer</h3>



<p>When working on such projects, you&#8217;re facing quite some challenges with the various database servers available.</p>



<ul class="wp-block-list">
<li>You need to have a local development environment running the database server(s).</li>



<li>You want to test your application against a newer version of a database server.</li>



<li>A customer reports an issue occurring with a database server version that you don&#8217;t have installed.</li>
</ul>



<h3 class="wp-block-heading">Developer Machine</h3>



<p>I like to have a development machine that&#8217;s as cleaned up as possible. So I don&#8217;t like the idea of installing various servers just for some tests. It&#8217;s so tedious to clean up, update to other versions, and remove all remnants of an installation when no longer required. And I don&#8217;t want to have various services running on my machine that I don&#8217;t need all the time, as they&#8217;re just eating precious memory and slowing down the machine.</p>



<p>Wouldn&#8217;t it be cool if there was an easy way to spin up various database servers when needed without all the hassle? Well there is &#8211; let&#8217;s have a look at Docker and Docker Compose.</p>



<h2 class="wp-block-heading">Docker Compose and Database Servers</h2>



<p>With Docker, it&#8217;s a breeze to develop with and for various database servers.</p>



<h3 class="wp-block-heading">What is Docker?</h3>



<p>If you haven&#8217;t heard of Docker, go ahead and read their excellent Documentation: <a href="https://docs.docker.com/get-started/overview/">Docker &#8211; Overview</a>. Or read my previous Guest Blog Post: <a href="https://blog.xojo.com/2021/05/17/running-xojo-web-applications-in-docker/">Running Xojo Web Applications in Docker</a>. I&#8217;m just going to repeat and quote some basics from the Overview to get a very brief introduction:</p>



<p><em><a href="https://www.docker.com/">Docker</a> is an open platform for developing, shipping, and running applications. It provides the ability to package and run an application in a loosely isolated environment called a container. The isolation and security allow you to run many containers simultaneously on a given host. Containers are lightweight and contain everything needed to run the application, so you do not need to rely on what is currently installed on the host.</em></p>



<p><em>A <a href="https://docs.docker.com/guides/docker-concepts/the-basics/what-is-a-container/">Docker Container</a> is a runnable instance of an image. You can create, start, stop, move, or delete a container. By default, a container is relatively well-isolated from other containers and its host machine. You can control how isolated a container’s network, storage, or other underlying subsystems are from other containers or from the host machine. A container is defined by its image as well as any configuration options you provide to it when you create or start it.</em></p>



<p><em><a href="https://docs.docker.com/compose/">Docker Compose</a> is a tool for defining and running multi-container applications. It is the key to unlocking a streamlined and efficient development and deployment experience. Compose simplifies the control of your entire application stack, making it easy to manage services, networks, and volumes in a single, comprehensible YAML configuration file. Then, with a single command, you create and start all the services from your configuration file.</em></p>



<h3 class="wp-block-heading">Docker Compose for Database Server and Administration</h3>



<p>This sounds great. Just write a YAML configuration file, and run a database server on the host (meaning: your developer machine). And be able to start, stop, delete at any time &#8211; without messing with Preferences, Launch Daemons.</p>



<p>But why Docker Compose for &#8220;multi container applications&#8221;? Well, the database server is one part: one application, one running docker container. And as a developer you most likely want to have some database administration tool running, too &#8211; which again is running as an own isolated container. And in order to have both available with a single command (or by simply pressing &#8220;run&#8221; or &#8220;stop&#8221;) we&#8217;re going to &#8220;compose&#8221; these two parts so that they fit and work together.</p>



<h2 class="wp-block-heading">How to Run a Database Server and Administration Tool with Docker Compose</h2>



<p>Let&#8217;s do that and install and configure three database servers which we then can use to develop an application in Xojo to connect to:</p>



<ul class="wp-block-list">
<li>PostgreSQL &amp; pgAdmin</li>



<li>cubeSQL &amp; cubeSQL Web Admin</li>



<li>MariaDB &amp; phpMyAdmin</li>
</ul>



<p>Note: All the following configuration files are available on GitHub: <a href="https://github.com/jo-tools/docker">jo-tools/docker</a>.</p>



<h3 class="wp-block-heading">Requirements</h3>



<p>Obviously we need to have Docker installed. And since we&#8217;re talking about being a Developer and doing this on our own development machine we&#8217;re going to install <a href="https://www.docker.com/products/docker-desktop/">Docker Desktop</a>. With Docker Desktop you can later easily start, stop and delete the Containers we&#8217;re going to create. When it&#8217;s empty (no containers installed), it looks like this:</p>



<figure class="wp-block-image size-large is-style-default"><img decoding="async" width="1024" height="589" src="https://blog.xojo.com/wp-content/uploads/2024/05/1_Docker-Desktop-1024x589.png" alt="" class="wp-image-12969" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/1_Docker-Desktop-1024x589.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/1_Docker-Desktop-300x172.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/1_Docker-Desktop-768x441.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/1_Docker-Desktop-1536x883.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/1_Docker-Desktop-2048x1177.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>We&#8217;re now ready to get started…! But wait &#8211; there is one thing we should talk about before.</p>



<h3 class="wp-block-heading">Data Storage</h3>



<p>Where are the database servers going to store their data(bases)?</p>



<p>If you want to know all the details, head over to the Docker Documentation: <a href="https://docs.docker.com/storage/">Manage data in Docker</a>. What we need to know is this:</p>



<p>Docker has two options for containers to store files on the host machine, so that the files are persisted even after the container stops: <a href="https://docs.docker.com/storage/volumes/">Volumes</a>, and <a href="https://docs.docker.com/storage/bind-mounts/">Bind Mounts</a>.</p>



<p>Why is this important to know? Well, let&#8217;s assume we create and start a Container &#8220;PostgreSQL Server&#8221;. Think of that Container as a &#8220;virtual machine&#8221; or a bag. It can save data in there just fine. But once we delete that container or throw away that bag, then all it&#8217;s data is gone, too.</p>



<p>That might well be intended…! For example if you just wish to play with some tool and don&#8217;t care to keep the data you&#8217;re creating with it. However, if you&#8217;d like to easily back up that data, or update a Container from &#8220;v.15&#8221; to &#8220;v.16&#8221; and keep the previous data &#8211; then that&#8217;s when Volumes and Bind Mounts are needed.</p>



<p>Quoted from the docs:</p>



<p><strong>Volumes</strong><br><em>Volumes are the preferred mechanism for persisting data generated by and used by Docker containers. They are completely managed by Docker.</em></p>



<p><strong>Bind Mounts</strong><br><em>Data is stored in a directory on the host machine, which is mounted into the container.</em></p>



<p>Okay &#8211; two options, so what&#8217;s the difference?</p>



<p>The Bind Mounts are a folder on the host (your developer machine). So you can easily see them, view/edit/backup the data. It might be an option if you need easy access to these files.</p>



<p>The Volumes are the preferred way, since they are managed within Docker. Using Docker Desktop you can view the contents &#8211; but it&#8217;s not that simple to view/edit files in there as you can&#8217;t mount it as a volume or folder on your developer machine. Of course there are some more advanced ways, which I&#8217;m not going to explain here. So definitely the best option when you don&#8217;t need to work with and open these files with other tools, too. The other reason we don&#8217;t need Bind Mounts for our database servers is that we can just use their administration tools to import/export data such as database dumps.</p>



<p>Alright &#8211; now let&#8217;s start and set up some database servers.</p>



<h3 class="wp-block-heading">PostgreSQL Server &amp; pgAdmin</h3>



<p>Let&#8217;s use the example setup with Volumes for Data Storage from here: <a href="https://github.com/jo-tools/docker/tree/main/local-postgres-volumes">GitHub: jo-tools/docker &#8211; local-postgres-volumes</a>.</p>



<p>Download the <code>docker-compose.yml</code> file from my <a href="https://github.com/jo-tools/docker">GitHub Repository</a> and place it in a folder on your machine.</p>



<p>I&#8217;m going to save it in: <code>~/Docker/local-postgres-volumes</code></p>



<figure class="wp-block-image size-large is-style-default"><img decoding="async" width="1024" height="282" src="https://blog.xojo.com/wp-content/uploads/2024/05/2_Local-Folder-1024x282.png" alt="" class="wp-image-12970" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/2_Local-Folder-1024x282.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/2_Local-Folder-300x83.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/2_Local-Folder-768x211.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/2_Local-Folder.png 1170w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong>YAML file: <strong><code>docker-compose.yml</code></strong></strong><br>A word of precaution when writing and editing YAML files:</p>



<ul class="wp-block-list">
<li>Indentation is done by spaces (not by tabs!)</li>



<li>Indentation has to be exact (use always 2 spaces), or expect to get syntax errors</li>
</ul>



<p>Let&#8217;s look at the content of this <code>docker-compose.yml.</code></p>



<pre class="wp-block-code"><code>x-common-timezone: &amp;services-timezone Etc/UTC

name: local_postgresql
services:
  postgres-server:
    container_name: postgresql
    hostname: postgresql
    image: postgres:16-alpine
    volumes:
      - postgresql_data:/var/lib/postgresql/data
    environment:
      TZ: *services-timezone
      PGTZ: *services-timezone
      POSTGRES_PASSWORD: postgres
      POSTGRES_USER: postgres
      POSTGRES_DB: postgres
    networks:
      - local_postgresql_net
    ports:
      - 5432:5432
    restart: unless-stopped

  pgadmin:
    container_name: pgadmin4
    hostname: pgadmin4
    image: dpage/pgadmin4:8
    environment:
      TZ: *services-timezone
      PGADMIN_DEFAULT_EMAIL: admin@postgres.sql
      PGADMIN_DEFAULT_PASSWORD: admin
      PGADMIN_CONFIG_UPGRADE_CHECK_ENABLED: "False"
      PGADMIN_CONFIG_SERVER_MODE: "False"
      PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED: "False"
    networks:
      - local_postgresql_net
    volumes:
      - pgadmin4_data:/var/lib/pgadmin
    ports:
      - 5433:80
    restart: unless-stopped
    depends_on:
      - postgres-server

volumes:
  postgresql_data:
    driver: local
    name: postgresql_data
  pgadmin4_data:
    driver: local
    name: pgadmin4_data

networks:
  local_postgresql_net:
    name: local_postgresql</code></pre>



<p>In the first hierarchy there are:</p>



<p>• <code>x-common-timezone: &amp;services-timezone Etc/UTC</code> <br>In this extension we define a scalar value for the timezone, which will be used for the environment variables in both services. The template uses UTC (which is also the default for Docker). You can change it to your timezone, e.g.: Europe/Zurich. This might be desired if you&#8217;re going to select the current date/time from the database server later.<br> • <code>name: local_postgresql </code><br>That&#8217;s the name of this &#8220;setup&#8221;. We&#8217;ll later see this in Docker Desktop&#8217;s Containers. There we can also start/stop/delete this setup at any time.<br>• <code>services:</code> <br>There are two services in this setup: <code>postgres-server</code> and <code>pgadmin</code><br>• <code>volumes:</code><br>And two volumes: one for the database server, and one for the administration tool.<br>• <code>networks: </code><br>Both these two containers will be in the same network.</p>



<p>When we look at the two services <code>postgres-server</code> and <code>pgadmin4</code>:<br>• <code>container_name:</code> <br>The name of the Container. We&#8217;ll later see this as a sub-element of this docker-compose setup named <code>local_postgresql</code> <br>• <code>hostname: </code><br>Think of a container as a virtual machine. Every one has its hostname. And the two containers in this setup we have placed in the same network. So they can talk to each other via hostname. <br> •<code>image:</code> <br> That&#8217;s basically the content of the container. We&#8217;re going to install: <br> • <code>postgres:16-alpine</code> <br> PostgreSQL Server in Version 16.x, running on Linux Alpine (a very lightweight one).<br> • <code>dpage/pgadmin4:8 </code><br> pgAdmin 4 in Version 8.x as the administration tool.<br>• <code>environment:</code> <br>Here the environment variables of the containers are being defined. TZ defines the Timezone, and uses the value we have defined in the extension on the very top. The other Environment Variables contain the defaults and standards &#8211; here used when the containers are being started the first time to define the default logins, users and passwords. Our PostgreSQL server will have a default login with both username and password: <code>postgres</code>. pgAdmin we have configured to auto-login without authentication required, and disabled update checks. <br>• <code>networks:</code> <br>Remember &#8211; both in the same one (defined below) <br>• <code>volumes:</code> <br>The format here is: <code>volume_name:/mount/in/folder</code> <br>We&#8217;re going to see these volumes later in Docker Desktop. They&#8217;ll contain the data. Usually the documentation of the Docker Images explain which folders are being used to save data, so they can be mounted here to either a Volume (or a Bind Mount). <br>• <code>ports</code>:<br> The format here is: <code>host-port:container-port</code> <br>For PostgreSQL Server we&#8217;re using 5432:5432, meaning that we can connect on our developer machine to Port 5432 (and this will be forwarded to the container running PostgreSQL Server, listening on Port 5432 inside the Container). pgAdmin is running on Port 80 within the Container, but we connect to it from our developer machine via Port 5433. <br>• <code>restart: unless-stopped </code><br>This basically means: if you have this setup running and reboot your host (developer machine), then this setup gets restarted automatically. If you&#8217;re going to stop this setup (because you don&#8217;t need it at the time), then it&#8217;ll be stopped after a reboot, too.</p>



<h2 class="wp-block-heading">Start Docker Compose Setup</h2>



<p>As we can&#8217;t use Docker Desktop to start a Docker Compose setup (maybe this feature will be added in the future) we have to use Terminal. Change Directory to where the <code>docker-compose.yml</code> file is and type: <code>docker-compose up -d</code></p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="289" src="https://blog.xojo.com/wp-content/uploads/2024/05/3_docker-compose-up-1024x289.png" alt="" class="wp-image-12976" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/3_docker-compose-up-1024x289.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/3_docker-compose-up-300x85.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/3_docker-compose-up-768x217.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/3_docker-compose-up.png 1140w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The referenced Images will be pulled, the defined network created and the Containers started.</p>



<p>Open the Dashboard in Docker Desktop and look at the Containers &#8211; you&#8217;ll find our setup named <code>local_postgresql</code> with the two Containers <code>postgresql</code> and <code>pgadmin4</code>:</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="444" src="https://blog.xojo.com/wp-content/uploads/2024/05/4_DockerDesktop-Containers-1024x444.png" alt="" class="wp-image-12977" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/4_DockerDesktop-Containers-1024x444.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/4_DockerDesktop-Containers-300x130.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/4_DockerDesktop-Containers-768x333.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/4_DockerDesktop-Containers-1536x666.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/4_DockerDesktop-Containers-2048x889.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>They are currently up and running.<br>If you want to stop this setup simply press the button under &#8220;Actions&#8221;. It then will be stopped even after a reboot. And should you need to run the setup again later, just hit the button &#8220;Run&#8221; here.</p>



<p>Under Volumes we see the created ones:</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="444" src="https://blog.xojo.com/wp-content/uploads/2024/05/5_DockerDesktop-Volumes-1024x444.png" alt="" class="wp-image-12978" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/5_DockerDesktop-Volumes-1024x444.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/5_DockerDesktop-Volumes-300x130.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/5_DockerDesktop-Volumes-768x333.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/5_DockerDesktop-Volumes-1536x666.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/5_DockerDesktop-Volumes-2048x889.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You can click on one to see it&#8217;s contents &#8211; here the data of postgresql:</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="444" src="https://blog.xojo.com/wp-content/uploads/2024/05/6_DockerDesktop-Volume-Content-1024x444.png" alt="" class="wp-image-12979" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/6_DockerDesktop-Volume-Content-1024x444.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/6_DockerDesktop-Volume-Content-300x130.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/6_DockerDesktop-Volume-Content-768x333.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/6_DockerDesktop-Volume-Content-1536x666.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/6_DockerDesktop-Volume-Content-2048x889.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong><strong>Connect With PGADMIN4</strong></strong><br>Either switch again to &#8220;Containers&#8221; and click the link &#8220;5433:80&#8221; in the column &#8220;Port&#8221; of the Container &#8220;pgadmin4&#8221; in Docker Desktop, or open a browser and go to  <code>http://localhost:5433</code>.</p>



<p>Since this is the first launch of pgAdmin4 we need to add a server &#8211; I have given it the name &#8220;Docker&#8221;:</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="541" src="https://blog.xojo.com/wp-content/uploads/2024/05/7_pgadmin-launch-1024x541.png" alt="" class="wp-image-12980" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/7_pgadmin-launch-1024x541.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/7_pgadmin-launch-300x158.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/7_pgadmin-launch-768x406.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/7_pgadmin-launch-1536x811.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/7_pgadmin-launch-2048x1082.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>In the register &#8220;Connection&#8221; we have to enter the connection data:</p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="541" src="https://blog.xojo.com/wp-content/uploads/2024/05/8_pgadmin-add-server-1024x541.png" alt="" class="wp-image-12981" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/8_pgadmin-add-server-1024x541.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/8_pgadmin-add-server-300x158.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/8_pgadmin-add-server-768x406.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/8_pgadmin-add-server-1536x811.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/8_pgadmin-add-server-2048x1082.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Username and password are the default ones (remember the environment variables?). And for this local developer setup I have chosen to save the password.</p>



<p>The most interesting part is the hostname.</p>



<ul class="wp-block-list">
<li><strong>You can&#8217;t use localhost here! <br></strong>The reason is simple: pgAdmin is running in a Container (think of it again as a virtual machine), so it&#8217;s &#8220;localhost&#8221; is the Container running pgadmin4. Not your developer machine, and not the Container where postgres is running.</li>



<li>I have entered: <code>host.docker.internal </code><br>This is explained in the <a href="https://docs.docker.com/desktop/networking/">Docker Documentation: networking:</a> The host has a changing IP address, or none if you have no network access. We recommend that you connect to the special DNS name host.docker.internal, which resolves to the internal IP address used by the host.</li>



<li>Another option would be to just use the hostname: <code>postgresql</code> <br>And why does this work? Well &#8211; we have configured these two containers to be in the same network, and the server is running in the host named &#8220;postgresql&#8221;.</li>
</ul>



<p>And here we go: Let&#8217;s expand the entries of the just added server &#8220;Docker&#8221;, click on the main database &#8220;postgres&#8221; and execute a query: <code>SELECT version();</code></p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="541" src="https://blog.xojo.com/wp-content/uploads/2024/05/9_pgadmin-connect-1024x541.png" alt="" class="wp-image-12982" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/9_pgadmin-connect-1024x541.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/9_pgadmin-connect-300x158.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/9_pgadmin-connect-768x406.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/9_pgadmin-connect-1536x811.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/9_pgadmin-connect-2048x1082.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong>Connect with Xojo</strong><br>We&#8217;re ready to use Xojo now and work on applications using our local PostgreSQL Server.<br>Let&#8217;s connect to our local development server running in Docker. As a simple test I have placed the following code in the Opening event of a Label:</p>



<pre class="wp-block-code"><code>Var db As New PostgreSQLDatabase
db.Host = "localhost"
db.UserName = "postgres"
db.Password = "postgres"
db.Port = 5432

Call db.Connect

Var rs As RowSet = db.SelectSQL("SELECT version();")
Me.Text = rs.Column("version").StringValue</code></pre>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="573" src="https://blog.xojo.com/wp-content/uploads/2024/05/10_Xojo-connect-1024x573.png" alt="" class="wp-image-13046" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/10_Xojo-connect-1024x573.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/10_Xojo-connect-300x168.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/10_Xojo-connect-768x429.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/10_Xojo-connect-1536x859.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/10_Xojo-connect-2048x1145.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">Additional Information</h3>



<p>You&#8217;ve seen how to easily spin up PostgreSQL with Docker Compose and connect to it with pgAdmin4 and Xojo. What else do we need to know?</p>



<p><strong>Images</strong><br>You&#8217;ll find available Images on <a href="https://hub.docker.com">Docker Hub</a>. In the above setup we have used <a href="https://hub.docker.com/_/postgres">postgres</a> and <a href="https://hub.docker.com/r/dpage/pgadmin4">pgAdmin4</a>. If you look at them on Docker Hub you&#8217;ll see that they provides many images. One can select them by Tag. The used Tag &#8220;postgres:16-alpine&#8221; here means that we get the latest version 16 (e.g. 16.2, and some month later maybe 16.3 or 16.4). If for some reason we want to get exactly version 16.1, then we can use the corresponding Tag, e.g. &#8220;postgres:16.1-alpine&#8221;.</p>



<p><strong>A Setup using Bind Mounts</strong><br>If you&#8217;re going to try the <code>docker-compose.yml</code> with Bind Mounts from here: <a href="https://github.com/jo-tools/docker/tree/main/local-postgres-bind-mounts">GitHub: jo-tools/docker &#8211; local-postgres-bindmounts</a>, then you&#8217;ll notice the difference in the configuration here:</p>



<pre class="wp-block-code"><code>volumes:
  - ./postgresql_data:/var/lib/postgresql/data</code></pre>



<p>You won&#8217;t get a Volume in Docker, but instead this will create a folder named <code>postgresql_data</code> in the folder where you&#8217;ve placed <code>docker-compose.yml</code> and launched the setup with <code>docker-compose up -d</code>.</p>



<p><strong>Docker Compose Commands</strong><br>We&#8217;ve already mentioned that the first launch of a Docker Compose setup will require Terminal. The following commands are to be executed in the same directory containing the yaml file, too:</p>



<p><code>docker-compose up -d</code><br>This looks for the file <code>docker-compose.yml</code>, pull the images, do all the setup and launch the containers. You can also use this command to restart this setup, should you have stopped it.</p>



<p><code>docker-compose stop</code><br>Stops all services in this setup. Or do it using the buttons in Register &#8220;Containers&#8221; in Docker Desktop.</p>



<p><code>docker-compose down -v</code><br>This removes all services and volumes from this setup. Use this to get rid of all Containers, Volumes AND data. Haven&#8217;t we mentioned that &#8211; it&#8217;s super easy to clean up <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /><br>You could also click the Delete buttons in Docker Desktop in both &#8220;Containers&#8221; and &#8220;Volumes&#8221; (and optionally &#8220;Images&#8221;).<br>If you omit the option &#8220;-v&#8221;, it will leave the Volumes in place. This might be of interest if you intend to keep the data, in case you&#8217;re going to spin up this setup again some time later.</p>



<p><code>docker-compose down</code><br><code>docker-compose pull</code> <br><code>docker-compose up -d</code><br>These 3 commands will first tear down the existing containers (leaving volumes and data in place), then pull the latest versions from Docker Hub and set everything up again. Remember that we have used the Image &#8220;postgres:16-alpine&#8221;, and currently got PostgreSQL 16.2? Once PostgreSQL 16.3 is available we can execute these commands and get the latest version. Again super easy to update, isn&#8217;t it?</p>



<h2 class="wp-block-heading">cubeSQL &amp; cubeSQL Web Admin</h2>



<p>Another popular database server for Xojo is <a href="https://sqlabs.com/cubesql">cubeSQL</a>. It basically adds multi-user handling (including groups, privileges, und much more) on top of SQLite.</p>



<p><em>cubeSQL is a fully-featured and high-performance relational database management system built on top of the SQLite database engine.</em></p>



<p><em>It is the ideal database server for both developers who want to convert a single user database solution to a multi-user project and for companies looking for an affordable, easy to use and easy to maintain database management system.</em></p>



<p>You&#8217;ll find an example setup for Docker Compose here: <a href="https://github.com/jo-tools/docker/tree/main/local-cubesql-volumes">GitHub: jo-tools/docker &#8211; local-cubesql-volumes.</a> To connect with Xojo you need a plugin, which can be downloaded from <a href="https://github.com/cubesql/cubeSQLAdmin">GitHub: cubesql/cubeSQLAdmin</a></p>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="753" src="https://blog.xojo.com/wp-content/uploads/2024/05/11_cubesql-webadmin-1-1024x753.png" alt="" class="wp-image-12983" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/11_cubesql-webadmin-1-1024x753.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/11_cubesql-webadmin-1-300x221.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/11_cubesql-webadmin-1-768x565.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/11_cubesql-webadmin-1-1536x1129.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/11_cubesql-webadmin-1.png 1638w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">cubeSQL Web Admin &#8211; Written with Xojo Web</h3>



<p>cubeSQL has a desktop application for administration, which you&#8217;ll find in the above GitHub <a href="https://github.com/cubesql/cubeSQLAdmin">Repository</a>, too. As you can guess a desktop based application is not quite convenient when it comes to an easy docker compose setup.</p>



<p>While I&#8217;m using Xojo for desktop and console applications for quite some time, I&#8217;ve never really used Xojo Web before. That&#8217;s why I took this opportunity and gave it a try. And behold &#8211; in very short time (most functionality in just a weekend&#8217;s leisure time) I&#8217;ve written &#8220;<a href="https://github.com/cubesql/webadmin">Xojo Web Admin</a>&#8220;. It&#8217;s been a pleasure to create something more than just some simple examples &#8211; I like the idea of creating something useful even while learning something new. And I&#8217;ll be honest &#8211; I&#8217;ve found a couple of bugs in Xojo&#8217;s Web Framework while writing <a href="https://github.com/cubesql/webadmin">cubeSQL Web Admin</a>, but most of them are already fixed and implemented for the next Xojo version. And finishing and polishing the project to make it available to the public also took an additional couple of evenings.</p>



<p><a href="https://github.com/cubesql/webadmin">cubeSQL Web Admin is Open Source</a> &#8211; so go ahead and have a look at the source (or even better: contribute to it by adding more features, find bugs and fix them). There might be some things of interest, such as:</p>



<ul class="wp-block-list">
<li>How to use Xojo Web to build an app that runs in a Docker container.  See also this Guest Blog Post: <a href="https://blog.xojo.com/2021/05/17/running-xojo-web-applications-in-docker/">Running Xojo Web Applications in Docker</a>
<ul class="wp-block-list">
<li>A new feature added while developing <a href="https://github.com/cubesql/webadmin">GitHub: cubeSQL Web Admin:</a> The Post Build Script builds a &#8220;Multi Architecture&#8221; Docker Image (<code>linux/amd64</code> &amp; <code>linux/arm64v8</code>) by building the Xojo Web App for BuildTargets Linux x86 64-bit and Linux ARM 64-bit. This allows to support running the Docker Image natively on Macs with both Intel and Apple processors.</li>
</ul>
</li>



<li>How to use Launch Arguments and Environment Variables for configuration. This allowed us to configure the Environment Variables in our Docker setup to preconfigure the connection data.</li>



<li>The approach with subclassed WebContainer&#8217;s that implement the WebDataSource Interface. The quite generic base class cntDatasourceBase can be configured to:
<ul class="wp-block-list">
<li>be searchable (Main Window shows/hides the WebSearchField if the subclassed Container defines to (not) be searchable).</li>



<li>define which Fields of a RowSet should be displayed (cubeSQL uses special custom commands for administration, so we can&#8217;t select distinct columns ourselves, and there&#8217;s no paging within these custom commands).</li>



<li>define virtual Fields, which will be shown in the WebListbox, but aren&#8217;t part of a RowSet. Internally the base class uses a Dictionary Array which gets built from the RowSet, so one could use it with other external DataSources, too.</li>



<li>show the Fields in the WebListBox, while allowing each Container to override the default behaviour (see for example the Databases, which use a WebListboxImageRenderer for a virtual field &#8211; depending on a couple of Columns in the RowSet an appropriate Status Icon is being displayed).</li>
</ul>
</li>
</ul>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="546" src="https://blog.xojo.com/wp-content/uploads/2024/05/12_cubesql-webadmin-2-1024x546.png" alt="" class="wp-image-12984" srcset="https://blog.xojo.com/wp-content/uploads/2024/05/12_cubesql-webadmin-2-1024x546.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/05/12_cubesql-webadmin-2-300x160.png 300w, https://blog.xojo.com/wp-content/uploads/2024/05/12_cubesql-webadmin-2-768x410.png 768w, https://blog.xojo.com/wp-content/uploads/2024/05/12_cubesql-webadmin-2-1536x819.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/05/12_cubesql-webadmin-2-2048x1092.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>To connect to this cubeSQL setup with Xojo I have placed the following code in the Opening event of a Label:</p>



<pre class="wp-block-code"><code>Var db As New CubeSQLServer
db.Host = "localhost"
db.UserName = "admin"
db.Password = "admin"
db.Port = 4430

Call db.Connect

Var rs As RowSet = db.SelectSQL("SHOW INFO FOR KEY server_version")
Me.Text = rs.Column("value").StringValue</code></pre>



<h2 class="wp-block-heading">MariaDB &amp; phpMyAdmin</h2>



<p><em>MariaDB Server is a high performing open source relational database, forked from MySQL.</em></p>



<p>You&#8217;ll find an example setup for Docker Compose here: <a href="https://github.com/jo-tools/docker/tree/main/local-mariadb-volumes">GitHub: jo-tools/docker &#8211; local-mariadb-volumes.</a></p>



<p>I&#8217;m not going to explain much more here about MariaDB (MySQL) or phpMyAdmin here &#8211; I think you should figure out easily how to launch the Administration tool and connect to the server when looking at the contents of this <code>docker-compose.yml.</code> But, since it&#8217;s a widely used and well-known database server, I wanted to provide a setup for this combo, too.</p>



<p>As a simple test for this setup I have placed the following code in the Opening event of a Label:</p>



<pre class="wp-block-code"><code>Var db As New MySQLCommunityServer
db.Host = "127.0.0.1"
db.UserName = "root"
db.Password = "mariadb"
db.Port = 3306

Call db.Connect

Var rs As RowSet = db.SelectSQL("SELECT version() AS version;")
Me.Text = rs.Column("version").StringValue</code></pre>



<p>For some reason the connection needs an IP Address or a Hostname (and doesn&#8217;t work with <code>localhost</code>).</p>



<h2 class="wp-block-heading">A Word of Caution</h2>



<p>The above setups are only intended as a local test setup &#8211; don&#8217;t use them like this for production. Even on a local developer machine you shouldn&#8217;t run the services with these simple initial login credentials, so go ahead and change them.</p>



<p>The purpose is to explain how Docker Compose works, and how it can help developers to easily setup up local environments to work on database applications. And of course these examples might well be a head start to those that haven&#8217;t used Docker before.</p>



<h2 class="wp-block-heading">That&#8217;s All Folks!</h2>



<p>I hope this brief introduction of how to use Docker and Database servers for and with Xojo has been helpful to some, food for thought to others.</p>



<p><em><em>Jürg Otter is a long term user of Xojo and working for </em><a href="https://www.cmiag.ch/"><em>CM Informatik AG</em></a><em>. Their Application </em><a href="https://cmi-bildung.ch/"><em>CMI LehrerOffice</em></a><em> is a Xojo Design Award Winner 2018. In his leisure time Jürg provides some </em><a href="https://www.jo-tools.ch/xojo/"><em>bits and pieces for Xojo Developers</em></a><em>.</em></em></p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQL 50th Anniversary</title>
		<link>https://blog.xojo.com/2024/04/15/sql-50th-anniversary/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Mon, 15 Apr 2024 15:19:40 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[IBM]]></category>
		<category><![CDATA[MS SQL Server]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12874</guid>

					<description><![CDATA[SQL is 50 years old! It was first introduced in a 1974 paper titled “SEQUEL: A STRUCTURED ENGLISH QUERY LANGUAGE” by Donald Chamberlin and Raymond&#8230;]]></description>
										<content:encoded><![CDATA[
<p><a href="https://en.wikipedia.org/wiki/SQL">SQL</a> is 50 years old! It was first introduced in a 1974 paper titled “<a href="https://s3.us.cloud-object-storage.appdomain.cloud/res-files/2705-sequel-1974.pdf">SEQUEL: A STRUCTURED ENGLISH QUERY LANGUAGE</a>” by Donald Chamberlin and Raymond Boyce who were part of the IBM Research Laboratory in San Jose California.</p>



<p>This paper probably explains the biggest issue regarding SQL that persists to this day: its pronunciation.</p>



<p>I always flip between saying “sequel” and “ess cue ell” depending on context. The authors used SEQUEL as an <a href="https://www.merriam-webster.com/dictionary/acronym">acronym</a> of <strong>S</strong>tructured <strong>E</strong>nglish <strong>QUE</strong>ry <strong>L</strong>anguage. Over time this was referred to as Structured Query Language and the <a href="https://www.merriam-webster.com/dictionary/initialism">initialism</a> of SQL took hold. Still, the pronunciation of sequel seems to have also stuck. Anyway, pronounce it how you want — I won’t judge.</p>



<p>I&#8217;ve sometimes seen people claim that SQL stands for Standard Query Language. As the above clearly shows, that is not true. And if you&#8217;ve used SQL at all with more than one database, you also have empirical evidence that there is not much standard about it beyond the main keywords.</p>



<p>The <a href="https://s3.us.cloud-object-storage.appdomain.cloud/res-files/2705-sequel-1974.pdf">paper itself</a> is only about 15 pages, so not long at all. I found this surprising as I expected it to be some lengthy and detailed specification written for academics.</p>



<p>But it’s not.</p>



<p>It starts by talking about the relational model of data, a somewhat new concept at the time (first <a href="https://en.wikipedia.org/wiki/Relational_model">described in 1969</a>), and the predicate calculus, introducing a sublanguage called SQUARE, which strikes me a somewhat functional way of querying relational data. Math nerds do love their functional languages.</p>



<p>The authors then go on to introduce SEQUEL as a substitute for SQUARE and it’s here where we see the first syntax that you might recognize:</p>



<pre class="wp-block-code"><code>SELECT NAME
FROM   EMP
WHERE  DEPT = ’TOY’</code></pre>



<p>Boolean expressions in the WHERE clause are also covered along with functions in the SELECT clause. These are all things still being used to this day.</p>



<p>The main justification the authors use for SEQUEL is that the concepts of predicate calculus and SQUARE require &#8220;too much sophistication for the ordinary user&#8221;. I won’t argue with that!</p>



<p>They drive that point home by showing how to get data results using some example queries, first by using SQUARE and then comparing to the SEQUEL equivalents. Their first query is this:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Find the names of managers who manage more than ten employees.</p>
</blockquote>



<p>Note that for this example, there is a previously defined database with one of the tables as follows:</p>



<p>EMP (NAME, DEPT, MGR, SAL, COMM)</p>



<p>The SQUARE example looks like this:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="122" src="https://blog.xojo.com/wp-content/uploads/2024/04/Pasted-Graphic-1024x122.png" alt="" class="wp-image-12878" srcset="https://blog.xojo.com/wp-content/uploads/2024/04/Pasted-Graphic-1024x122.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/04/Pasted-Graphic-300x36.png 300w, https://blog.xojo.com/wp-content/uploads/2024/04/Pasted-Graphic-768x92.png 768w, https://blog.xojo.com/wp-content/uploads/2024/04/Pasted-Graphic-1536x184.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/04/Pasted-Graphic.png 1672w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>I’m not going to even try to explain this. Read the paper if you’re curious.</p>



<p>Here&#8217;s the SEQUEL version:</p>



<pre class="wp-block-code"><code>SELECT   MGR
FROM     EMP
GROUP BY MGR
WHERE    COUNT (NAME) &gt; 10</code></pre>



<p>Well, now. That certainly makes more sense to me. I&#8217;ll bet that everyone reading this knows exactly how to parse out the SEQUEL command. It would actually work as-is in a database such as SQLite today!</p>



<p>There are other examples in the paper as well. Like I said, it’s somewhat short so you might find it to be an interesting read.</p>



<p>Happy 50th Birthday, SEQUEL (SQL)!!</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Simplicity and Security, Xojo Cloud is Ideal Hosting for Xojo Web Apps</title>
		<link>https://blog.xojo.com/2023/10/30/simplicity-and-security-xojo-cloud-is-ideal-hosting-for-xojo-web-apps/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Mon, 30 Oct 2023 16:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Security]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[App Hosting]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Security-Enhanced Linux]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[SSL]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11553</guid>

					<description><![CDATA[Xojo Cloud is the premier hosting solution for developers looking for a reliable, secure and high-performance hosting environment for Xojo web applications. Xojo Cloud is developed specifically for Xojo web applications and offers a range of benefits for you and your applications that make it worth the investment.]]></description>
										<content:encoded><![CDATA[
<p>Xojo Cloud is the premier hosting solution for developers looking for a reliable, secure and high-performance hosting environment for Xojo web applications. Xojo Cloud is developed specifically for Xojo web applications and offers a range of benefits for you and your applications that make it worth the investment.</p>



<p>Xojo Cloud is <strong>optimized for Xojo applications</strong>. It is specifically designed to provide the best possible performance and stability for Xojo web applications. We optimize Xojo Cloud for performance, so your web apps will run smoothly and seamlessly. You can even monitor server stats from within the Xojo IDE.</p>



<p>Xojo Cloud is <strong>focused on simplicity and ease of use</strong> and requires zero configuration. Designed with the Xojo developer in mind, Xojo Cloud&#8217;s Control Panel makes it easy to deploy and manage web applications. Purchase a server, open a web project in Xojo and click Deploy to upload and install to Xojo Cloud. Not just for web apps, Xojo Cloud includes Apple Push Notification server (APNs) support for your iOS apps. Set up SSL, PostrgeSQL, MySQL, SFTP and a SSH Tunnel with a click in the Xojo Cloud Control Panel (the Control Panel itself is a Xojo web app). The administration of a web server is a significant and constant task; Xojo Cloud allows you to leave that behind and focus on your projects.</p>



<figure class="wp-block-gallery has-nested-images columns-default is-cropped wp-block-gallery-1 is-layout-flex wp-block-gallery-is-layout-flex">
<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="386" data-id="12082" src="https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Apps-Tab-1024x386.png" alt="Xojo Cloud Control Panel Apps Tab" class="wp-image-12082" srcset="https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Apps-Tab-1024x386.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Apps-Tab-300x113.png 300w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Apps-Tab-768x289.png 768w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Apps-Tab-1536x579.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Apps-Tab-2048x772.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="384" data-id="12083" src="https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Options-Tab-1024x384.png" alt="Xojo Cloud Control Panel Options Tab" class="wp-image-12083" srcset="https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Options-Tab-1024x384.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Options-Tab-300x112.png 300w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Options-Tab-768x288.png 768w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Options-Tab-1536x576.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/09/Xojo-Cloud-Control-Panel-Options-Tab-2048x768.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</figure>



<p>We take security very seriously. Xojo Cloud <strong>offers advanced security features</strong> to protect your data from cyberthreats, including a smart firewall, intrusion and hacking detection and Security-Enhanced Linux. Unlike most hosting solutions that provide little to no security, each Xojo Cloud server is built with our state-of-the-art, industrial-strength, multi-tiered security system woven into its very core.&nbsp;</p>



<p>Additional features and benefits include daily automatic backups, load balancing and support from the Xojo team. With nine global hosting locations, you are able to host your Xojo web applications close to your users, for speed and an ideal overall experience. </p>



<div class="wp-block-columns are-vertically-aligned-top is-layout-flex wp-container-core-columns-is-layout-9d6595d7 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-vertically-aligned-top is-layout-flow wp-block-column-is-layout-flow" style="flex-basis:100%">
<figure class="wp-block-image size-large is-style-default"><img loading="lazy" decoding="async" width="1024" height="576" src="https://blog.xojo.com/wp-content/uploads/2023/09/Add-a-heading-1024x576.png" alt="Xojo Cloud offers 3 packages offering options on RAM, storage and vCPU starting at $49/month. " class="wp-image-12078" srcset="https://blog.xojo.com/wp-content/uploads/2023/09/Add-a-heading-1024x576.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/09/Add-a-heading-300x169.png 300w, https://blog.xojo.com/wp-content/uploads/2023/09/Add-a-heading-768x432.png 768w, https://blog.xojo.com/wp-content/uploads/2023/09/Add-a-heading-1536x864.png 1536w, https://blog.xojo.com/wp-content/uploads/2023/09/Add-a-heading.png 1600w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>
</div>



<p>In addition to the <a href="http://xojo.com/store/#cloud">standard options</a>, Xojo Cloud servers with more RAM, storage and Virtual CPUs are available. Contact&nbsp;<a href="mailto:hello@xojo.com">customer support</a>&nbsp;for details about personalized plans.&nbsp;</p>



<p>Whether you are a seasoned Xojo developer or just getting started, Xojo Cloud provides an intuitive and user-friendly hosting solution for Xojo web applications. Today is a good day to start using Xojo Cloud, visit our <a href="https://xojo.com/cloud/">website</a> to learn more or see the Xojo <a href="https://xojo.com/store/#cloud">Store</a> to pick your package and location.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Develop Database Apps with Xojo</title>
		<link>https://blog.xojo.com/2023/09/26/develop-database-apps-with-xojo/</link>
		
		<dc:creator><![CDATA[Xojo]]></dc:creator>
		<pubDate>Tue, 26 Sep 2023 18:06:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Database Applications]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9320</guid>

					<description><![CDATA[After you have designed your interface and begun coding, your next step may be to connect to a database. This blog post tells you the databases supported by Xojo, shows you where to find code samples and examples, plus tutorials and videos that walk you through connecting, updating, querying and managing database, plus, an introduction to Xojo's new DBKit. Get the resources and knowledge you need to get your first database project off the ground today.]]></description>
										<content:encoded><![CDATA[
<p>After you have designed your interface and begun coding, your next step may be to connect to a database. This blog post tells you the databases supported by Xojo, shows you where to find code samples and examples, plus tutorials and videos that walk you through connecting, updating, querying and managing a database, plus, an introduction to Xojo&#8217;s new DBKit. Get the resources and knowledge you need to get your first database project off the ground today.</p>



<span id="more-9320"></span>



<h3 class="wp-block-heading">Database Support</h3>



<p>Xojo works with a wide variety of databases. SQLite is bundled with your Xojo license and is a great beginner database for desktop, web and mobile apps. Xojo includes direct support for SQLite, PostgreSQL and MySQL. Plus, you can use <a href="https://documentation.xojo.com/topics/databases/supported_engines/odbc.html#odbc">ODBC</a> to connect to just about anything else, such as Oracle, MS-SQL Server, Microsoft Access, Firebird or even IBM iSeries.</p>



<h3 class="wp-block-heading">Examples</h3>



<p>To help you get started, there are many examples in the Examples/Databases folder included with the Xojo <a href="https://xojo.com/download/">Download</a>, including examples that connect to each of the supported databases. You can find a <a href="https://documentation.xojo.com/resources/examples.html">breakdown of the examples</a> included in the Examples folder in the Xojo Programming Language Documentation.</p>



<p><a href="http://www.xojo.com/blog/en/assets_c/2014/07/DBExamples-429.php"></a>Additionally, you can check out the <a href="https://demos.xojo.com/#customerID">Eddie’s Electronics</a> sample app (located in Examples/Sample Applications/EddiesElectronics) to see how to share database code between Xojo desktop and Xojo web apps.</p>



<p>DBKit is an example project designed to make it easier to build desktop and web applications that are front-ends to databases. Specifically, DBKit makes it easy to connect a database table to the user interface controls on a layout. DBKit also handles a lot of the interface for you.&nbsp;You can read more about <a href="https://documentation.xojo.com/topics/databases/dbkit.html">DBKit</a> in the Xojo Documentation.</p>



<h3 class="wp-block-heading">Read: Documentation</h3>



<p>After you have reviewed the examples, the <a href="https://documentation.xojo.com/topics/databases/database_basics_for_beginners.html">Database Overview</a> in the Xojo Documentation will help with next steps. Remember, Xojo comes bundled with SQLite which is an excellent database for desktop, web and mobile apps. Read more about using <a href="https://documentation.xojo.com/topics/databases/supported_engines/sqlite/overview.html">SQLite</a> in the Xojo Documentation and check out this <a href="https://documentation.xojo.com/topics/databases/supported_engines/sqlite/sqlite_basics.html">SQLite Tutorial</a> for more detail.</p>



<h3 class="wp-block-heading">Watch: Videos</h3>



<p>The Xojo YouTube channel has hundreds of videos on all things Xojo. Here are the most recent Xojo Database videos and playlists:</p>



<ul class="wp-block-list">
<li>Video: <a href="https://youtu.be/GGyu4D0ni28">Connecting to a Database from Xojo</a></li>



<li>Video: <a href="https://youtu.be/JWja37wXz2U">Updating a Database from Xojo</a></li>



<li>Video: <a href="https://youtu.be/8ENtgkzvyS0">Querying a Database from Xojo</a></li>



<li>Video: <a href="https://youtu.be/wVHYk-4XG2o">Managing the UI when Updating a Database</a></li>



<li>Video: <a href="https://youtu.be/3Jjf1Xrnm2w">Using DBKit to easily connect databases to Xojo applications</a></li>



<li>Playlist: <a href="https://www.youtube.com/playlist?list=PLPoq910Q9jXhRoPw0_mHKdVUKPXpL9TKV">Using Databases with Xojo</a> &#8211; A growing, catch-all playlist for videos related to Xojo and databases.</li>



<li>Playlist: <a href="https://www.youtube.com/playlist?list=PLPoq910Q9jXjDBrL3KymUwnagM8d7Xbia">Xojo and SQLite</a> &#8211; SQLite comes bundled with Xojo and is a great database for beginners building desktop, web and mobile apps with Xojo.</li>
</ul>



<h3 class="wp-block-heading">Vendor Documentation</h3>



<p>Lastly, you should always refer to the vendor-specific documentation for the database you are using to learn the specifics about how that database works, including SQL syntax.</p>



<ul class="wp-block-list">
<li><a href="http://www.sqlite.org/docs.html">SQLite</a></li>



<li><a href="http://www.postgresql.org/docs/">PostgreSQL</a></li>



<li><a href="http://dev.mysql.com/doc/">MySQL</a></li>



<li><a href="http://www.oracle.com/technetwork/indexes/documentation/index.html?ssSourceSiteId=ocomen">Oracle Database</a></li>



<li><a href="http://msdn.microsoft.com/en-us/library/bb545450.aspx">Microsoft SQL Server</a></li>
</ul>



<p>Xojo simplifies the development process, reduces complexity and empowers developers to create efficient and functional database applications with relative ease. The Xojo IDE is free to use for development and testing &#8211; design, develop, run and debug your app all without a license. Purchase a license when you are ready to compile your apps, licenses start at $149. Visit the <a href="https://xojo.com/store/">Xojo Store</a> to find the license right for your project.</p>



<p>If you have questions after you have reviewed these materials, the Xojo <a href="https://forum.xojo.com">Forum</a> is an accessible and essential resource for Xojo users of all levels. You can also <a href="https://www.xojo.com/company/contact.php">contact</a> Xojo directly with your questions.</p>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQLite 3.39.4: New Features</title>
		<link>https://blog.xojo.com/2022/12/13/sqlite-new-features-in-xojo-2022r4/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 13 Dec 2022 14:32:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Database Applications]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11053</guid>

					<description><![CDATA[In Xojo 2022r4, we have updated our SQLite library to SQLite v3.39.4. I thought I'd highlight a few notable upgrades including: STRICT tables
PRAGMA table_list
RIGHT and FULL OUTER JOIN
Built-in JSON support]]></description>
										<content:encoded><![CDATA[
<p>In Xojo 2022r4, we have updated our SQLite library to SQLite v3.39.4. Previously Xojo was using 3.36.0, and since there have been <a href="https://www.sqlite.org/changes.html">quite a few SQLite updates since then</a> I thought I&#8217;d highlight a few notable features:</p>



<ul class="wp-block-list"><li>STRICT tables</li><li>PRAGMA table_list</li><li>RIGHT and FULL OUTER JOIN</li><li>Built-in JSON support</li></ul>



<p>More about each of these below.</p>



<h2 class="wp-block-heading">STRICT Tables</h2>



<p>One of SQLite&#8217;s most unusual capabilities is that it does not care about what data goes into a column. Although you could specify a type for a column, it was really more of a suggestion as other types of data could be put into the column. This behavior is different than most other relational databases and can sometimes be a source of confusion.</p>



<p>Now you can create your tables using the <a href="https://www.sqlite.org/stricttables.html">STRICT keyword</a> to force them to require column types and to force the column types to always be checked when putting data into them.</p>



<p>You are still limited to INT, INTEGER, REAL, TEXT and BLOB. That means there is still no DATE or DATETIME type like you might find in other databases. Instead use TEXT with YYYY-MM-DD format.</p>



<p>However, an ANY type was added which essentially allows you to clearly state that the column can contain anything. This allows you to have a mixture of specific types and generic types in your STRICT tables.</p>



<p>Note that the STRICT keyword goes at the end of the CREATE TABLE command:</p>



<pre class="wp-block-preformatted">CREATE TABLE Team (ID INTEGER, Name TEXT, Coach TEXT, City TEXT, PRIMARY KEY(ID)) STRICT;</pre>



<p>The <a href="https://www.sqlite.org/stricttables.html">SQLite docs</a> have more information about the new STRICT table feature.</p>



<h2 class="wp-block-heading">PRAGMA table_list</h2>



<p>With Xojo you could always get the list of tables by using the <a href="https://documentation.xojo.com/api/databases/database.html#database-tables">Database.Tables()</a> method. However if you wanted to get the list of table using SQL you had to directly query the sqlite_master table.</p>



<p>Now there is a simple PRAGMA that can do the same thing:</p>



<pre class="wp-block-code"><code>PRAGMA table_list</code></pre>



<p>It returns a list of tables and some other details about the table (which may change over time <a href="https://www.sqlite.org/pragma.html#pragma_table_list">according to the SQLite docs</a>).</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.16.02@2x-1024x852.png" alt="" class="wp-image-11057" width="625" height="520" srcset="https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.16.02@2x-1024x852.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.16.02@2x-300x250.png 300w, https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.16.02@2x-768x639.png 768w, https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.16.02@2x.png 1144w" sizes="auto, (max-width: 625px) 100vw, 625px" /></figure>



<h2 class="wp-block-heading">RIGHT and FULL OUTER JOIN</h2>



<p>Joining tables is a common task with SQL. The most common type of join is an INNER JOIN where only the rows common to both tables are included in the result. Other less common types of joins include LEFT OUTER, RIGHT OUTER and FULL OUTER (sometimes OUTER is omitted when referring to these types of joins).</p>



<p>SQLite has had support for LEFT OUTER joins for a long time, but support for RIGHT OUTER and FULL OUTER were missing. But now they are here, giving your more complicated queries better compatibly with the &#8220;big name&#8221; databases.</p>



<p>Learn more about these types of joins at <a href="https://www.w3schools.com/sql/sql_join.asp">W3 schools</a>.</p>



<h2 class="wp-block-heading">JSON Support</h2>



<p>I&#8217;ve saved the big one for last: your SQL databases can now work with JSON data within columns.</p>



<p>Here is a sample table to work with with some JSON data that is stored in the players column:</p>



<pre class="wp-block-preformatted">CREATE TABLE team(id INTEGER PRIMARY KEY, Name TEXT, players TEXT);</pre>



<pre class="wp-block-preformatted">INSERT INTO TEAM VALUES (NULL, 'Seagulls', '[ {"Name":"Bob","position":"1B"}, {"Name":"Tom","position":"2B"} ]')</pre>



<pre class="wp-block-preformatted">INSERT INTO TEAM VALUES (NULL, 'Pigeons', '[ {"Name":"Bill","position":"1B"}, {"Name":"Tim","position":"2B"} ]')</pre>



<pre class="wp-block-preformatted">INSERT INTO TEAM VALUES (NULL, 'Crows', '[ {"Name":"Betty","position":"1B"}, {"Name":"Tina","position":"2B"} ]')</pre>



<p>Let&#8217;s say you want to get the first player on each team. Without SQLite JSON support you would have to pull out the JSON column data and parse it out separately. But now you can do it with this SQL like this:</p>



<pre class="wp-block-preformatted">SELECT players -&gt; 0 FROM team</pre>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="590" height="568" src="https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.54.09@2x.png" alt="" class="wp-image-11063" srcset="https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.54.09@2x.png 590w, https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-10.54.09@2x-300x289.png 300w" sizes="auto, (max-width: 590px) 100vw, 590px" /></figure>



<p>The above SQL says: for each row fetch the first array element from the JSON data in players.</p>



<p>This is how you would list all the players on all the teams:</p>



<pre class="wp-block-preformatted">SELECT team.Name, json_each.value -&gt; 'Name' FROM team, json_each(team.players)</pre>



<p>And if you want to get the actual value without the quotes, you can use the -&gt;&gt; operator (and also rename the result):</p>



<pre class="wp-block-preformatted">SELECT team.Name, json_each.value -&gt;&gt; 'Name' As PlayerName FROM team, json_each(team.players)</pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="544" src="https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-11.40.49@2x-1024x544.png" alt="" class="wp-image-11075" srcset="https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-11.40.49@2x-1024x544.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-11.40.49@2x-300x159.png 300w, https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-11.40.49@2x-768x408.png 768w, https://blog.xojo.com/wp-content/uploads/2022/12/CleanShot-2022-12-12-at-11.40.49@2x.png 1250w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The SQLite JSON support can do much, much more which you can read about on the <a href="https://www.sqlite.org/json1.html">SQLite JSON doc page</a>.</p>



<p><em>Paul learned to program in BASIC at age 13 and has programmed in more languages than he remembers, with Xojo being an obvious favorite. When not working on Xojo, you can find him talking about retrocomputing at <a href="https://goto10.substack.com" target="_blank" rel="noreferrer noopener">Goto 10</a> and </em>on Mastodon @lefebvre@hachyderm.io.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQLite 3.34.1 New Features</title>
		<link>https://blog.xojo.com/2021/03/31/sqlite-3-34-1-new-features/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 31 Mar 2021 12:03:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[WAL]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8292</guid>

					<description><![CDATA[Xojo 2021 Release 1 updates its SQLite engine to 3.34.1 (from 3.33.0). This release does not have a lot of new features, but there are&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2021 Release 1 updates its SQLite engine to 3.34.1 (from 3.33.0). This release does not have a lot of new features, but there are a few notable ones that you might find useful.</p>



<p>First, the performance of <a href="https://documentation.xojo.com/api/databases/sqlitedatabase.html#sqlitedatabase-writeaheadlogging">WAL mode</a> (write-ahead logging) is improved when there are lots of connections all accessing the same database file. This ought to provide noticeable improvements for web apps that use SQLite databases.</p>



<p>If you use <a href="https://documentation.xojo.com/topics/databases/supported_engines/sqlite/full_text_searching.html">full text searching with FTS5</a>, you can now enable <a href="https://www.sqlite.org/draft/fts5.html#trigramidx">trigram indexing</a> to allow search terms to better match within text blocks.</p>



<p>A minor change is that the &#8220;<a href="https://www.sqlite.org/draft/lang_corefunc.html#substr">substr()</a>&#8221; SQL function can now also be called &#8220;substring()&#8221; for compatibility with SQL Server.</p>



<p>There are a few other performance improvements as well. Visit the SQLite site to read the <a href="https://www.sqlite.org/draft/changes.html">official release notes</a>.</p>



<p><a href="https://blog.xojo.com/tag/sqlite/">Find more SQLite tips</a> </p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Good Change, API 2.0 Database Benefits</title>
		<link>https://blog.xojo.com/2020/09/17/good-change-api-2-0-database-benefits/</link>
		
		<dc:creator><![CDATA[Wayne Golding ]]></dc:creator>
		<pubDate>Thu, 17 Sep 2020 10:00:20 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[MS SQL Server]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7292</guid>

					<description><![CDATA[I decided when updating the project, I would also update to API 2.0 database commands using Xojo 2019 R3.2 and I would like to share some of those code changes with you.]]></description>
										<content:encoded><![CDATA[
<p>Recently I needed to update an old Web project that used a Microsoft SQL Server Database as its data source. This application is running as a service on a Windows machine and is for internal use only. I decided when updating the project, I would also update to API 2.0 database commands using Xojo 2019 R3.2 and I would like to share some of those code changes with you.</p>



<span id="more-7292"></span>



<p>In API 2.0, SQLSelect became <a href="http://documentation.xojo.com/api/databases/database.html#database-selectsql">SelectSQL</a> and SQLExecute became <a href="http://documentation.xojo.com/api/databases/database.html#database-executesql">ExecuteSQL</a>. Additionally API 2.0 automatically uses prepared statements. Now, while they perform much the same actions, there are enhancements which make code much simpler to create and read. This is because they implement Prepared Statements under the hood.</p>



<p>For Example, this API 1.0 code:</p>



<pre class="wp-block-preformatted">Dim ps As PreparedSQLStatement<br>Dim rs As RecordSet<br><br>ps = Session.db.Prepare("SELECT * FROM users WHERE emailaddress = ?;")<br>ps.BindType(0, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)<br>ps.Bind(0, "wayne@axisdirect.co.nz")<br><br>rs = ps.SQLSelect()<br><br>Session.UserID = rs.Field("id").IntegerValue</pre>



<p>Becomes:</p>



<pre class="wp-block-preformatted">Var rs As RowSet

rs = Session.db.SelectSQL("SELECT * FROM users WHERE emailaddress = ?;" _
 ,"wayne@axisdirect.co.nz")

Session.UserID = rs.Column("id").IntegerValue</pre>



<p>Seven lines of code become just four and in my opinion the second is much easier to follow.&nbsp;A prepared statement is not required (as it is implemented under the hood), and the bind type is automatic.</p>



<p>That SELECT statement does not have many bindings, but here is an INSERT statement that does – API 1.0 code</p>



<pre class="wp-block-preformatted">Dim ps As PreparedSQLStatement
ps = Session.db.Prepare("INSERT INTO reports (title, scheduletype, dayofmonth, dayofweek, sunday, monday, tuesday, wednesday, thursday, friday, saturday, nextrun, reportfile, deliverymethod, suspended) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)")<br><br>ps.BindType(0, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)<br>ps.BindType(1, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)<br>ps.BindType(2, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)<br>ps.BindType(3, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)<br>ps.BindType(4, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br>ps.BindType(5, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br>ps.BindType(6, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br>ps.BindType(7, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br>ps.BindType(8, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br>ps.BindType(9, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br>ps.BindType(10, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br>ps.BindType(11, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING) ' This is a datetime value, but we're going to bind a SQLDateTime String<br>ps.BindType(12, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_STRING)<br>ps.BindType(13, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_INT)<br>ps.BindType(14, MSSQLServerPreparedStatement.MSSQLSERVER_TYPE_TINYINT)<br><br>ps.Bind(0, TitleField.Text)
ps.Bind(1, ScheduleTypeMenu. ListIndex)
ps.Bind(2, If(ScheduleTypeMenu. ListIndex = 2, Val(DayOfMonthField.Text), 0)
ps.Bind(3, If(ScheduleTypeMenu. ListIndex = 1, Val(DayOfWeekField.Text), 0)
ps.Bind(4, If(WeekDay(0).Value, 1, 0)
ps.Bind(5, If(WeekDay(1).Value, 1, 0)<br><br>ps.Bind(6, If(WeekDay(2).Value, 1, 0)
ps.Bind(7, If(WeekDay(3).Value, 1, 0)
ps.Bind(8, If(WeekDay(4).Value, 1, 0)
ps.Bind(9, If(WeekDay(5).Value, 1, 0)
ps.Bind(10, If(WeekDay(6).Value, 1, 0)
ps.Bind(11, NextRunField.DateValue.SQLDateTime)
ps.Bind(12, ReportFileField.Text)
ps.Bind(13, DeliveryMethodMenu.SelectedIndex)
ps.Bind(14, 1)

ps.SQLExecute()

If Session.db.Error Then
  Break ' The insert statement failed for some reason - this should only happen during debugging.
End If</pre>



<p>Becomes:</p>



<pre class="wp-block-preformatted">Var sql As String

sql = "INSERT INTO reports (title, scheduletype, dayofmonth, dayofweek, sunday, monday, tuesday, wednesday, thursday, friday, saturday, nextrun, reportfile, deliverymethod, suspended) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

Try
&nbsp; Session.db.ExecuteSQL(sql, _
&nbsp;  TitleField.Value, _
&nbsp;  ScheduleTypeMenu.ListIndex, _
&nbsp;  If(ScheduleTypeMenu.ListIndex = 2, Val(DayOfMonthField.Text), 0), _
&nbsp;  If(ScheduleTypeMenu.ListIndex = 1, Val(DayOfWeekField.Text), 0), _
&nbsp;  If(WeekDay(0).Value, 1, 0), _
&nbsp;  If(WeekDay(1).Value, 1, 0), _
&nbsp;  If(WeekDay(2).Value, 1, 0), _
&nbsp;  If(WeekDay(3).Value, 1, 0), _
&nbsp;  If(WeekDay(4).Value, 1, 0), _
&nbsp;  If(WeekDay(5).Value, 1, 0), _
&nbsp;  If(WeekDay(6).Value, 1, 0), _
&nbsp;  NextRunField.DateValue.SQLDateTime, _
&nbsp;  ReportFileField.Value, _
&nbsp;  DeliveryMethodMenu.ListIndex, _
&nbsp;  1)

Catch Err As DatabaseException
  Break ' The insert statement failed for some reason - this should only happen during debugging.
End Try</pre>



<p>Again, a huge reduction in coding and a more readable result.&nbsp;You will also notice the use of a try/catch block. API 2.0 methods raise exceptions and during debugging these are invaluable as they break on the exception rather than later when your logic bug bites <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f60a.png" alt="😊" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>



<p>The API 2.0 SelectSQL method also returns a <a href="https://documentation.xojo.com/api/databases/rowset.html">RowSet</a> rather than a RecordSet.&nbsp;The RowSet is iterable unlike the RecordSet and that makes it much more user friendly. I can’t tell you how many times I’ve run a project only to find it just sits there using all the CPU cycles it can because I forgot to call the MoveNext method.</p>



<p>I understand that many people using Xojo on Windows probably aren&#8217;t targeting MS SQL Server, but I believe this is changing. And as more developers target Windows and MS SQL Server, the fixes and improvements that come with API 2.0 will make this easier for them. I know they are making my life a lot easier.</p>



<p>Oh, and by the way, before this update this application would start with a memory usage of about 100MB and grow to &gt;500MB over the week and then I would restart the service.&nbsp;Updating this project to API 2.0 resulted in ongoing memory usage of between 7.5 and 8.5MB for the running application.&nbsp;I suspect this is a combination of my improved coding and improvements under the hood by Xojo.</p>



<p><em>Wayne Golding has been a Xojo developer since 2005 and is a Xojo MVP. He operates the IT Company <a href="http://www.axisdirect.nz">Axis Direct Ltd </a>which primarily develops applications using Xojo that integrate with Xero www.xero.com. Wayne’s hobby is robotics where he uses Xojo to build applications for his Raspberry Pi, often implementing IoT for remote control.</em></p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Quick Tips: Xojo Cloud and Databases</title>
		<link>https://blog.xojo.com/2020/09/02/quick-tips-xojo-cloud-and-databases/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Wed, 02 Sep 2020 10:00:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7209</guid>

					<description><![CDATA[Based on recent conversations with a couple Xojo users, here are a few quick tip for uploading and working with SQLite and MySQL databases on Xojo Cloud.]]></description>
										<content:encoded><![CDATA[<p>Based on recent conversations with a couple Xojo users, here are a few quick tips for uploading and working with SQLite and MySQL databases on Xojo Cloud.</p>
<p>If you aren&#8217;t already familiar with <a href="https://www.xojo.com/cloud/">Xojo Cloud</a>, it&#8217;s simple, secure, maintenance-free hosting for your Xojo web apps. </p>
<p><span id="more-7209"></span></p>
<h3>SQLite Database Tip</h3>
<p>For the first tip, which involves SQLite databases, this is the scenario: Let&#8217;s say you added a SQLite database to the project using a Build step and set the proper Folder/Subfolder, and then you connect to it from the <code>Session.Opening</code> event (or any other, for this case) in order to access its tables.</p>
<p>Even if you are running your Web app in local or debug mode (from the IDE) the connection to the SQLite database works, no matter if you&#8217;re typing the database file name in either upper or lowercase. Remember, when you are deploying the database to Xojo Cloud, you need to pass along the database name using the proper lowercase and uppercase characters in its original name.</p>
<p>Let&#8217;s suposse that the original database name on disk is &#8220;MyPrettyDatabase.sqlite&#8221;, then you&#8217;re using the following code in order to connect to it:</p>
<pre>#if DebugBuild then
    f=SpecialFolder.Desktop.Child("myprettydatabase.sqlite")
#else
    f=specialfolder.documents.child("myprettydatabase.sqlite")
#EndIf

BBDD.DatabaseFile=f

Try

    BBDD.Connect

catch e as IODatabaseException

End Try</pre>
<p>In this case, when running the web app from your computer everything will work fine (because most desktop operating systems use a case-insensitive file system, although Linux is often case-sensitive); but if you deploy the web app to Xojo Cloud you&#8217;ll find yourself with a database that does not connect. Fixing this is as simple as typing the string representing the database filename observing the uppercase characters existing in its original name:</p>
<pre>#if DebugBuild then
    f=SpecialFolder.Desktop.Child("myprettydatabase.sqlite")
#else
    f=specialfolder.documents.child("MyPrettyDatabase.sqlite")
#EndIf

    BBDD.DatabaseFile=f

Try

    BBDD.Connect

catch e as DatabaseException

End Try</pre>
<p><em><strong>SQLite Tip</strong>: Xojo 2020r1 updated to SQLite 3.31.1, which adds some <a href="https://blog.xojo.com/2020/08/31/sqlite-3-31-1-new-features/">cool new features</a>!</em></p>
<h3>MySQL/MariaDB Database Tip</h3>
<p>The second problem we&#8217;re solving involves the connection with MySQL/MariaDB databases hosted on a remote server from your Xojo Cloud app.</p>
<p>Although connecting to a remote MySQL database is <a href="https://documentation.xojo.com/api/databases/mysqlcommunityserver.html">well documented here</a>, let&#8217;s review. If you need to establish this kind of connection, remember to open the Xojo Cloud firewall port first.</p>
<p>For example, something like this code snippet will let the web app work when deployed on Xojo Cloud and when you are doing a local test running it from the IDE (debug mode):</p>
<pre>#If TargetXojoCloud
    Var fwp As New XojoCloud.FirewallPort(3306, XojoCloud.FirewallPort.Direction.Outgoing)
    fwp.Open
    If fwp.isOpen Then
        connectDatabase
    End If
#Else
    ConnectDatabase
#EndIf</pre>
<p>Where, in this case, ConnectDatabase is the method in charge of doing the real connection setting the usual parameters agains the MySQLCommunityServer instance.</p>


<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>3 Steps to Seamlessly Deploy SQLite Projects on Desktop, Web &#038; iOS</title>
		<link>https://blog.xojo.com/2020/03/17/3-steps-to-seamlessly-deploy-sqlite-projects-on-desktop-web-ios/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 17 Mar 2020 10:00:25 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[Mobile]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Object-Oriented]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=6725</guid>

					<description><![CDATA[This tutorial will show you how to deploy your SQLite based projects so they behave right on Desktop, Web and iOS, copying the database file to the right place on every target.]]></description>
										<content:encoded><![CDATA[<p>This tutorial will show you how to deploy your SQLite based projects so they behave right on Desktop, Web and iOS, copying the database file to the right place on every target.</p>
<h2>1. Adding the database file</h2>
<p>You probably created your SQLite database file using an external editor; so first add that file to your Xojo project.</p>
<p>You can do that in several ways, but usually it&#8217;s best to add a Build Step. This way, the file will be added automatically to the folder of your choice every time you compile your app. <em>Bonus: Doing this allows you to decide to use different paths when debugging or deploying your app.</em></p>
<p>In order to add a new Build Step in a <span style="text-decoration: underline;">Desktop</span> project select the target in the Build Settings then, from the contextual menu, choose the &#8220;Add to Build Settings &gt; Build Step &gt; Copy Files&#8221; option.</p>
<p><img loading="lazy" decoding="async" class="size-medium wp-image-6726 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.37.51-300x70.png" alt="" width="300" height="70" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.37.51-300x70.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.37.51.png 655w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>The previous action will give you access to the Inspector Panel for the just-added item where you will be able to type a name for the Build Step, choose if the copy file action will be executed both for debugging or deployment and, most importantly, choose the location where the file should be copied when the app compiles.</p>
<p>In fact, the Destination menu contains a number of typical paths (or most relevant folders). For example, a good Destination option would be &#8220;Resources Folder&#8221;. Of course, don&#8217;t forget to add the database file itself using the buttons on the Build Editor toolbar.</p>
<p><img loading="lazy" decoding="async" class="size-medium wp-image-6727 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.42.04-300x173.png" alt="" width="300" height="173" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.42.04-300x173.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.42.04.png 359w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<p>When you&#8217;re working with a <span style="text-decoration: underline;">Web project</span>, you&#8217;ll find exactly the same behavior, even if you choose to deploy with Xojo Cloud.</p>
<p>On <span style="text-decoration: underline;">iOS</span>, the only change is that you&#8217;ll have to choose the icon with an iPhone picture in it in order to access the Build Step contextual menu; in addition to the fact that every added resource needs to be signed with a certificate.</p>
<p><img loading="lazy" decoding="async" class="size-medium wp-image-6728 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.43.45-300x47.png" alt="" width="300" height="47" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.43.45-300x47.png 300w, https://blog.xojo.com/wp-content/uploads/2020/03/Screenshot-2020-03-04-at-12.43.45.png 608w" sizes="auto, (max-width: 300px) 100vw, 300px" /></p>
<h2>2. Copying the database file to a &#8220;Working&#8221; folder</h2>
<p>You may think that the previous step is all you need to do, because if the database file is already copied in a well know path then you only need to provide that path as the DatabaseFile property on a new SQLiteDatabase or iOSSQLiteDatabase instance. But this is not the case.</p>
<p>They are many reasons you shouldn&#8217;t do that, specifically because the database would be open in read/write mode and if you write to that database file inside an application bundle, then you&#8217;ll be modifying a resource that would invalidate any certificate signature on your app.</p>
<p>The best thing to do is o detect every time you run the app if the database file has already been copied from the app bundle (or folder) into a target folder that doesn&#8217;t have an access problem when it is time to use the database. The Application Support folder is a good place for Desktop apps, while the Documents folder is fine for Xojo Cloud and iOS apps.</p>
<p>For example, if our database file is named &#8220;EddiesElectronics.sqlite&#8221; and our app name is &#8220;Xojotest&#8221;, then we can add the following code fragment into the Open Event Handler of a Desktop app:</p>
<pre>Var source As FolderItem = SpecialFolder.Resource("EddiesElectronics.sqlite")
Var name As String = app.ExecutableFile.name.NthField(".",1)

// We check if there is a folder with the App name in special Application Data
// if not, we create it and copy the database file from Resources bundle/directory
If Not (SpecialFolder.ApplicationData.Child(name).Exists And SpecialFolder.ApplicationData.Child(name).IsFolder) Then SpecialFolder.ApplicationData.Child(name).CreateFolder
If Not SpecialFolder.ApplicationData.child(name).child(source).exists Then source.CopyTo(SpecialFolder.ApplicationData.Child(name))

Try
  // Create a SQLiteDatabase instance and try to open our database file from
  // the path
  pDatabase = New SQLiteDatabase
  pDatabase.DatabaseFile = SpecialFolder.ApplicationData.Child(name).Child("EddiesElectronics.sqlite")
  pDatabase.Connect

Catch e As DatabaseException
  MessageBox e.Message
End Try</pre>
<p>For an iOS app, the code would be:</p>
<pre>Var source As Xojo.IO.FolderItem = xojo.io.SpecialFolder.GetResource("EddiesElectronics.sqlite")

// We check if there is our database file already copied on the Documents Sandbox folder
// if not, we copy the database file from Resources bundle/directory
If Not xojo.io.SpecialFolder.Documents.Child("EddiesElectronics.sqlite").Exists Then
  source.CopyTo(xojo.io.SpecialFolder.documents)
End If

Try
  // Create a SQLiteDatabase instance and try to open our database file from
  // the path
  pDatabase = New iosSQLiteDatabase

  Var f As FolderItem = xojo.io.SpecialFolder.Documents
  pDatabase.DatabaseFile = f.Child("EddiesElectronics.sqlite")
  Call pDatabase.Connect

Catch e As RuntimeException
  MessageBox e.Reason
End Try</pre>
<p>If you&#8217;re working on Xojo Cloud, the code will be even shorter. First, make sure that the Copy File Build Step has the following values in the Inspector Panel:</p>
<ul>
<li><strong>Destination:</strong> Contents Folder</li>
<li><strong>Subdirectory:</strong> Documents</li>
</ul>
<p>Then, the code will be:</p>
<pre>Try
  pDatabase = new SQLiteDatabase
  pDatabase.DatabaseFile = SpecialFolder.Documents.Child("EddiesElectronics.sqlite")
  pDatabase.connect
Catch e as RuntimeException
  MessageBox e.Reason
End Try</pre>
<p>What about a Web app that you host? That would mean you are in control about the folder/directory you want to use to store the app resources. Thus, it wouldn&#8217;t make much sense to automatize this process (but it is certainly doable following the same principles).</p>
<h2>3. Simplifying the process</h2>
<p>What we have seen already works, but that means that you need to change the file database name and probably that would change on every app you build. That also means that you&#8217;ll have to write the same code snippet again and again on every new app. Wouldn&#8217;t it be great to be able to extend the SQLiteDatabase and iOSSQLiteDatabase classes in order to simplify that?</p>
<p>Well, you can do that! Start by adding a new Module to the example project (for example one named &#8220;DatabaseExtensions&#8221;) with a couple of methods on it. The first method will be the one executed on our Desktop, Web and Console apps, because all of these targets use the SQLiteDatabase class.</p>
<p>So, add a new method using the following signature in the just-created module:</p>
<pre>OpenDatabase( databaseName as String )</pre>
<p>It extends the SQLiteDatabase class, adding a new method that takes as parameter the name of the file we want to copy on the &#8220;work&#8221; folder/directory.</p>
<p>The code you should type on this method is:</p>
<pre>pDatabase = New SQLiteDatabase

#If TargetDesktop Or TargetConsole Or TargetWeb Then

  Var source As FolderItem = SpecialFolder.Resource( databaseName )
  Var name As String = app.ExecutableFile.name.NthField(".",1)
  // We check if there is a folder with the App name in special Application Data
  // if not, we create it and copy the database file from Resources bundle/directory
  If Not (SpecialFolder.ApplicationData.Child(name).Exists And SpecialFolder.ApplicationData.Child(name).IsFolder) Then
SpecialFolder.ApplicationData.Child(name).CreateFolder
If Not SpecialFolder.ApplicationData.Child(nam).Child(Source).exists Then source.CopyTo(SpecialFolder.ApplicationData.Child(name))

  Try
    // Create a SQLiteDatabase instance and try to open our database file from
    // the path
    pDatabase.DatabaseFile = SpecialFolder.ApplicationData.Child(name).Child(databaseName)
    pDatabase.Connect

  Catch e As DatabaseException
    MessageBox e.Message
  End Try

#ElseIf TargetXojoCloud
  Try
    pDatabase.DatabaseFile = SpecialFolder.Documents.Child( databaseName )
    pDatabase.connect
  Catch e As RuntimeException
    MessageBox e.Reason
  End Try
#EndIf</pre>
<p>Of course, we need to add the &#8220;pDatabase&#8221; property to our module too: pDatabase As SQLiteDatabase</p>
<p>Now, you&#8217;ll only need to use:</p>
<pre>OpenDatabase("EddiesElectronics.sqlite")</pre>
<p>With the method selected in the Project Browser, click on the Attributes section of the Inspector Panel (the Cog Wheel icon), and uncheck the &#8220;iOS 64&#8221; checkbox. This way, that method will not be included when compiling for iOS apps.</p>
<p><img loading="lazy" decoding="async" class="size-medium wp-image-6729 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2020/03/Captura-de-pantalla-2020-03-09-a-las-6.55.49-281x300.png" alt="" width="281" height="300" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/Captura-de-pantalla-2020-03-09-a-las-6.55.49-281x300.png 281w, https://blog.xojo.com/wp-content/uploads/2020/03/Captura-de-pantalla-2020-03-09-a-las-6.55.49.png 420w" sizes="auto, (max-width: 281px) 100vw, 281px" /></p>
<p>Do the same thing with the &#8220;pDatabase&#8221; property, so it is only compiled on the supported targets.</p>
<p>The second method is the one we will be using for iOS apps. The method signature would be:</p>
<pre>OpenDatabase(databseName as String)</pre>
<p>And typing the following fragment of code in the associated Code Editor:</p>
<pre>pIOSDatabase = New iOSSQLiteDatabase

Var source As Xojo.IO.FolderItem = xojo.io.SpecialFolder.GetResource( databaseName )

// We check if there is our database file already copied on the Documents Sandbox folder
// if not, we copy the database file from Resources bundle/directory
If Not xojo.io.SpecialFolder.Documents.Child( databaseName ).Exists Then
  source.CopyTo(xojo.io.SpecialFolder.documents)
End If

Try
  // Create a SQLiteDatabase instance and try to open our database file from
  // the path

  Var f As FolderItem = xojo.io.SpecialFolder.Documents
  pIOSDatabase.DatabaseFile = f.Child( databaseName )
  Call db.Connect

Catch e As RuntimeException
  MessageBox e.Reason
End Try</pre>
<p><img loading="lazy" decoding="async" class="size-medium wp-image-6730 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2020/03/Captura-de-pantalla-2020-03-09-a-las-6.55.27-282x300.png" alt="" width="282" height="300" srcset="https://blog.xojo.com/wp-content/uploads/2020/03/Captura-de-pantalla-2020-03-09-a-las-6.55.27-282x300.png 282w, https://blog.xojo.com/wp-content/uploads/2020/03/Captura-de-pantalla-2020-03-09-a-las-6.55.27.png 423w" sizes="auto, (max-width: 282px) 100vw, 282px" /></p>
<p>Lastly, and with the method item still selected in the Project Browser, go to the Attributes section of the Inspector Panel and make sure that the &#8220;iOS 64&#8221; checkbox is the only one selected under the &#8220;Include In&#8221; section. This way, we make sure that the method will be compiled only on iOS targets.</p>
<p>And do the same thing with the &#8220;piOSDatabase&#8221;, so it is only compiled for iOS targets.</p>
<h2>To Summarize</h2>
<p>As we see, the use of Modules in combination with OOP Class Extension is a good way to get more flexibility when developing your apps; using a common function (or method) name no matter if you are working on Desktop, Web or iOS. Additionally, that leads to a more convenient reutilization of your codeand, of course, less code to maintain through all our projects!</p>
<p>(You can find this article in Spanish <a href="https://www.aprendexojo.com/2020/03/prepara-bases-de-datos-sqlite-para-despliegue-en-desktop-web-y-ios/">here</a>)</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Revisiting SQL Injections on the Final Frontier</title>
		<link>https://blog.xojo.com/2019/03/20/revisiting-sql-injections-on-the-final-frontier/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 20 Mar 2019 10:00:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Star Trek]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5551</guid>

					<description><![CDATA[In the fictional 23rd century relational databases and SQL are still in use not only by the United Federation of Planets but also by alien probes from the future! ]]></description>
										<content:encoded><![CDATA[<p>In a recent <a href="https://www.imdb.com/title/tt8288440/?ref_=ttep_ep8">Star Trek Discovery episode</a>, the crew was investigating how a probe (from the future!) was attempting to hack into their systems. This is what was said about it:</p>
<p><figure id="attachment_5552" aria-describedby="caption-attachment-5552" style="width: 800px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-5552" src="https://blog.xojo.com/wp-content/uploads/2019/03/IMG_1808.jpg" alt="" width="800" height="600" /><figcaption id="caption-attachment-5552" class="wp-caption-text">&#8220;The probe used multiple SQL injections&#8221;</figcaption></figure></p>
<p><span id="more-5551"></span></p>
<p>Apparently, in the fictional 23rd century relational databases and SQL are still in use not only by the United Federation of Planets but also by alien probes from the future! Normally Star Trek creates some technobabble gibberish for this sort of thing, so I certainly found this line surprising. Perhaps the writers thought it was just gibberish or that it would sound like gibberish to the average person.</p>
<p>But anyone who uses databases knows that SQL Injections can be a real issue. A SQL Injection refers to an issue when your app inadvertently allows a user to inject their own SQL into one of its database queries. Read <a href="https://blog.xojo.com/2016/02/18/avoiding-sql-injection/">this post</a> on how to avoid them.</p>
<p>Essentially, it can occur when you use standard string concatenation to create an SQL query from user-provided text. If you prompt the user for a name so you can show their tasks, for example then you&#8217;d normally get SQL like this:</p>
<pre>SELECT * FROM Task WHERE Name = 'Paul';</pre>
<p>But what if the user provides malicious input, such as this: Paul&#8217; OR 1</p>
<p>Then your concatenation code might create SQL like this:</p>
<pre>SELECT * FROM Task WHERE Name = 'Paul' OR 1;</pre>
<p>And this will return a lot more data. Obviously this is a simple example, but this type of exploit can be much more sophisticated. And apparently also something that alien probes from the future might try to use.</p>
<p>You can avoid this problem by taking advantage of a feature called database binding so that you do not use string concatenation to generate the SQL. With Xojo you do this by creating a <strong>prepared statement</strong> with placeholders for input strings and then let the database create the query itself using binding. So the SQL might look something like this:</p>
<pre>SELECT * FROM Task WHERE Name = ?</pre>
<p>Read the User Guide topic to more about how to avoid SQL injection by using prepared statements with your Xojo database code:</p>
<p><a href="https://documentation.xojo.com/topics/databases/protecting_your_database_from_attack.html">UserGuide:SQL Injection</a></p>
<p>And of course, <a href="https://xkcd.com/327/">relevant XKCD</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tip: SQLite in RAM … to improve speed!</title>
		<link>https://blog.xojo.com/2019/02/11/tip-sqlite-in-ram-to-improve-speed/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Mon, 11 Feb 2019 10:00:18 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5399</guid>

					<description><![CDATA[One technique is the creation of a new in-memory based SQLite database, where we will be able to copy the table (or tables) we are interested in getting the maximum speed possible with. Continue reading to see how to do this.]]></description>
										<content:encoded><![CDATA[<p>It&#8217;s very usual to use encrypted <b>SQLite</b> databases in our Xojo projects where we expect to get the maximum read speed from them. But the truth is that encrypting the data in these databases can introduce a penalty in our queries, both from read and writing/updating data to them. How can we improve this? One technique is the creation of a new in-memory based SQLite database, where we will be able to copy the table (or tables) we are interested in getting the maximum speed possible with. Continue reading to see how to do this.<span id="more-5399"></span></p>
<p>You can further modify this technique so you can work with your databases in a <em>mixed</em> way; that is, where we want to simultaneously execute a query involving both an encrypted database table and an in-memory table database.</p>
<p>But for this example code we are only focused on opening an encrypted SQLite database (based on disk) as a new SQLite class instance, and using next a SQL sentence to create a new in-memory database (named <code>RAMDB</code> in the example), creating the same table on the RAM database next and then copying the data from the <em>source</em> table during the process.</p>
<p>From that time on, you will be able to use the new table on RAM at light speed!</p>
<p>Another SQL command you might find of interest, and that you can use in all your SQLite databases where you expect to get a gain in the read speed, is to use the exclusive mode, using for that <code>PRAGMA LOCKING_MODE = Exclusive</code>.</p>
<p>However, and focusing on the tip itself, this is the snippet of code you can use:</p>
<pre>Var db As SQLiteDatabase = New SQLiteDatabase
db.DatabaseFile =  // Assign here a FolderItem to the SQLite database file on disk
db.EncryptionKey = "aes256:" +  // Add here a String with the same password that the one used to encrypt the data
If db.Connect = False Then
  Var re As New RuntimeException
  re.message = "Error trying to connect to the database"
  Raise re
End If
db.ExecuteSQL("PRAGMA LOCKING_MODE = Exclusive") // Improves the read access to the database

// We create a in-memory database, 'attaching' it with the disk based SQLite database
db.ExecuteSQL("attach database ':memory:' as 'RAMDB'")

// Copying all the contents from the source table
// to the newly created table on the RAM SQLite database

db.ExecuteSQL("create table RAMDB.product_table as select * from main.product_table")</pre>
<p>As you can see, the second line of code expects a valid <code>FolderItem</code> instance pointing to the SQLite database on disk. In addition, you need to provide the String to the password used originally to encrypt the data on the source database. This example assumes that this has been done using the <b>AES 256</b> option, stronger than the one using a length of 128 bits and the only option available before Xojo 2018r1.</p>
<p>Finally, in the last sentence <code>db.SQLExecute</code> you&#8217;ll have to change the table name you want to copy from the source database to the new RAM based one (<code>product_table</code> in the example).</p>
<p><em>Javier Rodri­guez has been the Xojo Spanish Evangelist since 2008, he’s also a Developer, Consultant and Trainer who has be using Xojo since 1998. He manages <a href="http://www.aprendexojo.com">AprendeXojo.com</a> and is the developer behind the GuancheMOS plug-in for Xojo Developers, Markdown Parser for Xojo, HTMLColorizer for Xojo and the Snippery app, among others.</em></p>
<p>*<a href="https://www.aprendexojo.com/2019/01/truco-sqlite-en-ram-mejora-al-maximo-el-rendimiento/">Read this post in Spanish</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQLite is not a server</title>
		<link>https://blog.xojo.com/2019/01/10/sqlite-is-not-a-server/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 10 Jan 2019 10:00:54 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Web Service]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5299</guid>

					<description><![CDATA[If you are using SQLite you might be trying to share your database. What are your options when you want to be able to share your database?  ]]></description>
										<content:encoded><![CDATA[<p>People often ask about a way to share a <a href="http://www.sqlite.org">SQLite</a> database across multiple apps. Essentially they want to know how to use SQLite as a server and the most common questions relate to putting a SQLite database file on a shared network drive and accessing the database file from apps running on multiple computers. This is a really bad idea, as even the SQLite folks will tell you. I&#8217;ll quote the relevant section from their &#8220;<a href="https://www.sqlite.org/whentouse.html">When to use SQLite</a>&#8221; page:</p>
<blockquote><p><strong>Situations Where A Client/Server RDBMS May Work Better</strong></p>
<p><strong>Client/Server Applications</strong></p>
<p>If there are many client programs sending SQL to the same database over a network, then use a client/server database engine instead of SQLite. SQLite will work over a network filesystem, but because of the latency associated with most network filesystems, performance will not be great. Also, file locking logic is buggy in many network filesystem implementations (on both Unix and Windows). If file locking does not work correctly, two or more clients might try to modify the same part of the same database at the same time, resulting in corruption. Because this problem results from bugs in the underlying filesystem implementation, there is nothing SQLite can do to prevent it.</p>
<p>A good rule of thumb is to avoid using SQLite in situations where the same database will be accessed directly (without an intervening application server) and simultaneously from many computers over a network.</p></blockquote>
<p>So what are your options when you want to share your database?</p>
<p>If you want to stick with SQLite then you&#8217;ll need to put something in front of it that can handle requests from multiple client apps. The most obvious solution is to create a web service by using a web app with WebApplication.HandleURL (or HandleSpecialURL). The web app can accept requests from multiple client apps (or any type &#8212; desktop, web, mobile, etc.), fetch the data requested from the SQLite database and then send it back as JSON. This works because the web app is the only app that is connected to the SQLite database.</p>
<p>The <a href="https://documentation.xojo.com/UserGuide:Eddie%27s_Electronics_Sample_Web_Service">Eddie&#8217;s Electronics Web Service sample</a> shows you how you might set this up: Examples/Communication/Web Services/EddiesWebService</p>
<p>Another option for setting up your own database web service is to use the <a href="https://aloe.zone">Aloe open-source project</a>, which gives you a robust framework for building web services.</p>
<p>To learn more about database web services, check out the <a href="https://youtu.be/X58zSmm2iSE">Making Database Web Services video</a>.</p>
<p>By the way, this is also why a regular web app can safely use SQLite with multiple users &#8212; the web app manages the multiple users but is the only app that is connected to the SQLite database.</p>
<p>If you want to stick with SQLite but would rather not create a web service, another option to consider is to use a product that puts a database server around SQLite. <a href="https://www.sqlabs.com/cubesql.php">CubeSQL</a> and <a href="https://www.valentina-db.com/en/sqlite-database-server">Valentina</a> have products available that can do this.</p>
<p>Your final option is to switch to an actual database server. PostgreSQL and MySQL are popular alternatives.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQLite 3.25 Adds Window Functions and Improves ALTER TABLE</title>
		<link>https://blog.xojo.com/2018/12/18/sqlite-3-25-adds-window-functions-and-improves-alter-table/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 18 Dec 2018 10:00:15 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=5142</guid>

					<description><![CDATA[Xojo 2018 Release 4 updated SQLite to 3.25. The SQLite 3.25 release had two significant changes: Window Functions and an improved ALTER TABLE command. ALTER&#8230;]]></description>
										<content:encoded><![CDATA[<p>Xojo 2018 Release 4 updated SQLite to 3.25. The <a href="https://www.sqlite.org/releaselog/3_25_0.html">SQLite 3.25 release</a> had two significant changes: Window Functions and an improved ALTER TABLE command.</p>
<p><span id="more-5142"></span></p>
<h2>ALTER TABLE</h2>
<p>If you&#8217;ve been using SQLite for a while you probably know that the ALTER TABLE command has always been pretty restrictive. It really only let you change the table name or add new columns. You could not modify or remove columns. This meant that in order to modify or remove columns from a table you typically used a multi-step process of creating the new table the way you wanted, copying the data to it and then renaming the two tables so the new table now has the name of the original table. It was a hassle. And because this was manual it would break any triggers or views that used the old name.</p>
<p>Now with SQLite 3.25 you can directly rename columns on a table, which will update triggers and views as necessary.</p>
<p>The syntax is as you might expect:</p>
<pre>ALTER TABLE MyTable RENAME COLUMN OldColumn TO NewColumn;</pre>
<p>In Xojo code you send this command to the database using the SQLExecute method. Here&#8217;s an example that changes a column name:</p>
<pre>Dim sql As String = "ALTER TABLE Team RENAME COLUMN Coach To HeadCoach;"
DB.SQLExecute(sql)</pre>
<p>Sadly you still cannot remove a column so you&#8217;ll have to resort to the manual method described above.</p>
<h2>Window Functions</h2>
<p>According to the SQLite docs:</p>
<blockquote><p>A window function is a special SQL function where the input values are taken from a &#8220;window&#8221; of one or more rows in the results set of a SELECT statement.</p></blockquote>
<p>SQLite now has these built-in Window functions:</p>
<ul>
<li>row_number()</li>
<li>rank()</li>
<li>dense_rank()</li>
<li>percent_rank()</li>
<li>cume_dist()</li>
<li>ntile(N)</li>
<li>lag(expr), lag(expr, offset), lag(expr, offset, default)</li>
<li>lead(expr), lead(expr, offset), lead(expr, offset, default)</li>
<li>first_value(expr)</li>
<li>last_value(expr)</li>
<li>nth_value(expr, N)</li>
</ul>
<p>This example uses the row_number function to assign a row number based on ordered City names while still ordering the overall results by team name:</p>
<p>SELECT Name, City, row_number() OVER (ORDER By City) AS row_num FROM Team ORDER BY Name;</p>
<p>Window Functions are powerful and can get complex quickly. Read more about them at the official <a href="https://www.sqlite.org/windowfunctions.html">SQLite Window Function doc page</a>.</p>
<p>Xojo 2018 Release 4 includes SQLite 3.25.3 so be sure to upgrade to get access to these great new SQLite improvements. <a href="https://www.xojo.com/download/">Download</a> Xojo 2018 Release 4 for free today.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Getting the MySQL Server Version</title>
		<link>https://blog.xojo.com/2018/05/14/getting-the-mysql-server-version/</link>
		
		<dc:creator><![CDATA[Norman Palardy]]></dc:creator>
		<pubDate>Mon, 14 May 2018 10:00:30 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=4283</guid>

					<description><![CDATA[Do you need to know what version of MySQL you're using in code? Maybe you need one of the many other configuration parameters that MySQL offers? It's simple to do it in SQL with this code snippet.]]></description>
										<content:encoded><![CDATA[<p>Do you need to know what version of MySQL you&#8217;re using in code? Maybe you need one of the many other configuration parameters that MySQL offers? It&#8217;s easy to get this information with some simple code!</p>
<p><span id="more-4283"></span></p>
<pre>Dim db As New MySQLCommunityServer

db.Host = "somehost"
db.port = &lt;port # for your mysql server&gt;
db.DatabaseName = "somedbname"
db.UserName = "someuser"
db.Password = "somepassword"

If db.Connect Then

  Dim rs As RecordSet = db.SQLSelect("select @@Global.version")

  While rs &lt;&gt; Nil And rs.eof &lt;&gt; True

    // and here you get a row with the value selected

    rs.MoveNext

  Wend
End If
</pre>
<p>There are a whole host of possible items you can select this way.  See all your <a href="https://dev.mysql.com/doc/refman/5.5/en/variables-table.html">options</a> at the MySQL Docs site.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>SQLite Rocks, Let Us Tell You Why</title>
		<link>https://blog.xojo.com/2017/10/03/sqlite-rocks-let-us-tell-you-why/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 03 Oct 2017 07:39:30 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2690</guid>

					<description><![CDATA[SQLite is a great database to use for all kinds of apps, here are 8 reasons why it rocks.]]></description>
										<content:encoded><![CDATA[
<p>Here at Xojo, we <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/2764.png" alt="❤" class="wp-smiley" style="height: 1em; max-height: 1em;" />&nbsp;<a href="http://www.sqlite.org">SQLite</a>&nbsp;so much &#8211; It&#8217;s truly a great database to use for all kinds of apps.</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img decoding="async" src="https://www.xojo.com/resources/images/sqlite/sqlite.gif" alt=""/></figure>
</div>


<p>Here are 8 reasons why you should be using SQLite with your apps:</p>



<span id="more-2690"></span>



<p><strong>1. It is fast</strong></p>



<p>SQLite is an embedded database so the database engine gets built right into your app. It is also designed for incredible speed. It can handle millions of rows with ease.</p>



<p><strong>2. It is typeless</strong></p>



<p>Unlike other databases, SQLite does not care what type of data you put into a column. In fact, it really doesn&#8217;t use types at all! Columns are assigned an &#8220;affinity&#8221; of INTEGER, REAL, TEXT and BLOB which helps determine how they are used for queries and functions. But you can stick text data into an integer column without a problem. You can read more about SQLite&#8217;s unique handling of Data Types on their <a href="http://www.sqlite.org/datatype3.html" target="_blank&quot;" rel="noopener">documentation page</a>.</p>



<p><strong>3. It is cross-platform</strong></p>



<p>SQLite works on every platform imaginable, including: Windows, macOS, Linux, Raspberry Pi, web, iOS and Android. Additionally, the database files themselves are cross-platform. So if you create a database and populate with data on iOS, you can move the file over to Windows and be able to read, write and otherwise use it without trouble. This makes SQLite a great fit for cross-platform development tools like Xojo.</p>



<p><strong>4. It is public domain</strong></p>



<p>Because it is public domain, SQLite is complete free to use with no restrictions of any kind. And the <a href="https://www.sqlite.org/src/doc/trunk/README.md">full source code is readily available</a>, of course.</p>



<p><strong>5. It works with most programming languages</strong></p>



<p>Most programming languages have built-in support for SQLite, including: Delphi, C, C#, C++, Go, Java, JavaScript, LiveCode, Lue, Objective-C, Perl, PHP, Python, Ruby, Visual Basic and Xojo. With Xojo you can use SQLite with macOS, Windows, Linux, web, console, iOS and Android apps.</p>



<p><strong>6. It is updated often</strong></p>



<p>SQLite is a mature database with few bugs, but it is <a href="https://www.sqlite.org/news.html">updated often</a>&nbsp;to ensure it remains at its best quality. If any bugs sneak in, they are quickly squashed.</p>



<p><strong>7. It is fast</strong></p>



<p>SQLite is so fast that it is worth saying again. Seriously, it is fast. Don&#8217;t use a text file or JSON or some other thing that will likely be much slower, especially when the files get large. Use SQLite and you&#8217;ll be happier.</p>



<p><strong>8. It is used everywhere</strong></p>



<p>It is a good bet that apps you rely on are using SQLite in some way. It is a great storage mechanism for preferences, general app data and can even be used as the app file format itself. For example, Apple Mail uses SQLite to save email messages and Firefox uses SQLite databases to store much of its profile information.</p>



<p>You can <a href="http://www.xojo.com/download">download Xojo for free</a> to start making apps that use <a href="https://documentation.xojo.com/topics/databases/database_basics_for_beginners.html">SQLite</a>. For more information, check out these videos:</p>



<ul class="wp-block-list">
<li><a href="http://developer.xojo.com/webinar-using-sqlite">Using SQLite</a></li>



<li><a href="http://developer.xojo.com/webinar-sqlite">SQLite Features</a></li>



<li><a href="http://developer.xojo.com/webinar-advanced-sqlite">Advanced SQLite</a></li>
</ul>



<ul class="wp-block-social-links has-normal-icon-size is-content-justification-center is-layout-flex wp-container-core-social-links-is-layout-16018d1d wp-block-social-links-is-layout-flex"><li class="wp-social-link wp-social-link-facebook  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.facebook.com/goxojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12 2C6.5 2 2 6.5 2 12c0 5 3.7 9.1 8.4 9.9v-7H7.9V12h2.5V9.8c0-2.5 1.5-3.9 3.8-3.9 1.1 0 2.2.2 2.2.2v2.5h-1.3c-1.2 0-1.6.8-1.6 1.6V12h2.8l-.4 2.9h-2.3v7C18.3 21.1 22 17 22 12c0-5.5-4.5-10-10-10z"></path></svg><span class="wp-block-social-link-label screen-reader-text">Facebook</span></a></li>

<li class="wp-social-link wp-social-link-x  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://x.com/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M13.982 10.622 20.54 3h-1.554l-5.693 6.618L8.745 3H3.5l6.876 10.007L3.5 21h1.554l6.012-6.989L15.868 21h5.245l-7.131-10.378Zm-2.128 2.474-.697-.997-5.543-7.93H8l4.474 6.4.697.996 5.815 8.318h-2.387l-4.745-6.787Z" /></svg><span class="wp-block-social-link-label screen-reader-text">X</span></a></li>

<li class="wp-social-link wp-social-link-linkedin  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.linkedin.com/company/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M19.7,3H4.3C3.582,3,3,3.582,3,4.3v15.4C3,20.418,3.582,21,4.3,21h15.4c0.718,0,1.3-0.582,1.3-1.3V4.3 C21,3.582,20.418,3,19.7,3z M8.339,18.338H5.667v-8.59h2.672V18.338z M7.004,8.574c-0.857,0-1.549-0.694-1.549-1.548 c0-0.855,0.691-1.548,1.549-1.548c0.854,0,1.547,0.694,1.547,1.548C8.551,7.881,7.858,8.574,7.004,8.574z M18.339,18.338h-2.669 v-4.177c0-0.996-0.017-2.278-1.387-2.278c-1.389,0-1.601,1.086-1.601,2.206v4.249h-2.667v-8.59h2.559v1.174h0.037 c0.356-0.675,1.227-1.387,2.526-1.387c2.703,0,3.203,1.779,3.203,4.092V18.338z"></path></svg><span class="wp-block-social-link-label screen-reader-text">LinkedIn</span></a></li>

<li class="wp-social-link wp-social-link-github  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://github.com/topics/xojo" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M12,2C6.477,2,2,6.477,2,12c0,4.419,2.865,8.166,6.839,9.489c0.5,0.09,0.682-0.218,0.682-0.484 c0-0.236-0.009-0.866-0.014-1.699c-2.782,0.602-3.369-1.34-3.369-1.34c-0.455-1.157-1.11-1.465-1.11-1.465 c-0.909-0.62,0.069-0.608,0.069-0.608c1.004,0.071,1.532,1.03,1.532,1.03c0.891,1.529,2.341,1.089,2.91,0.833 c0.091-0.647,0.349-1.086,0.635-1.337c-2.22-0.251-4.555-1.111-4.555-4.943c0-1.091,0.39-1.984,1.03-2.682 C6.546,8.54,6.202,7.524,6.746,6.148c0,0,0.84-0.269,2.75,1.025C10.295,6.95,11.15,6.84,12,6.836 c0.85,0.004,1.705,0.114,2.504,0.336c1.909-1.294,2.748-1.025,2.748-1.025c0.546,1.376,0.202,2.394,0.1,2.646 c0.64,0.699,1.026,1.591,1.026,2.682c0,3.841-2.337,4.687-4.565,4.935c0.359,0.307,0.679,0.917,0.679,1.852 c0,1.335-0.012,2.415-0.012,2.741c0,0.269,0.18,0.579,0.688,0.481C19.138,20.161,22,16.416,22,12C22,6.477,17.523,2,12,2z"></path></svg><span class="wp-block-social-link-label screen-reader-text">GitHub</span></a></li>

<li class="wp-social-link wp-social-link-youtube  wp-block-social-link"><a rel="noopener nofollow" target="_blank" href="https://www.youtube.com/c/XojoInc" class="wp-block-social-link-anchor"><svg width="24" height="24" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false"><path d="M21.8,8.001c0,0-0.195-1.378-0.795-1.985c-0.76-0.797-1.613-0.801-2.004-0.847c-2.799-0.202-6.997-0.202-6.997-0.202 h-0.009c0,0-4.198,0-6.997,0.202C4.608,5.216,3.756,5.22,2.995,6.016C2.395,6.623,2.2,8.001,2.2,8.001S2,9.62,2,11.238v1.517 c0,1.618,0.2,3.237,0.2,3.237s0.195,1.378,0.795,1.985c0.761,0.797,1.76,0.771,2.205,0.855c1.6,0.153,6.8,0.201,6.8,0.201 s4.203-0.006,7.001-0.209c0.391-0.047,1.243-0.051,2.004-0.847c0.6-0.607,0.795-1.985,0.795-1.985s0.2-1.618,0.2-3.237v-1.517 C22,9.62,21.8,8.001,21.8,8.001z M9.935,14.594l-0.001-5.62l5.404,2.82L9.935,14.594z"></path></svg><span class="wp-block-social-link-label screen-reader-text">YouTube</span></a></li></ul>



<p><em>Updated February 2024 to include Xojo Android.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Spotlight: Build Flexible, Powerful and Secure Database Applications</title>
		<link>https://blog.xojo.com/2017/06/22/use-xojo-to-create-database-apps/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 22 Jun 2017 07:56:05 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[ODBC]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2696</guid>

					<description><![CDATA[Xojo's powerful language allows for rapid development while supporting a wide variety of databases &#038; ODBC, it offers flexible form design, database binding, reporting and more.]]></description>
										<content:encoded><![CDATA[<p>Whether you are new to building database applications or you need to expand your toolbox, Xojo is a smart choice. With Xojo you can build real, native apps. And Xojo&#8217;s powerful language allows for rapid app development while supporting a wide variety of databases and ODBC, plus it offers flexible form design, database binding, reporting and more.</p>
<p><span id="more-2696"></span></p>
<h3>Multiple Databases Supported</h3>
<p>Xojo supports a wide variety of databases, including: SQLite, PostgreSQL, MySQL, Microsoft SQL Server and Oracle.</p>
<p>In addition, you can use ODBC to connect to other databases such as Access (JET), FoxPro, FileMaker, Firebird and even IBM iSeries (DB2). You’ll always have access to your data using Xojo, <a href="http://blog.xojo.com/2013/06/19/database-connectivity-with-xojo/">read more</a> about connectivity between Xojo and your preferred database.</p>
<h3>Flexible Form Design</h3>
<p>Xojo includes dozens of controls available for desktop, web and mobile apps. You can use these controls to design any type of user interface that you can imagine. You’ll find controls for buttons, check boxes, popup menus, text fields, text areas, graphics, tabs, progress, lists, HTML, images and more.</p>
<h3>Simple and Powerful Programming Language</h3>
<p>How can a language be both simple and powerful? Xojo is simple because its language is small, focused and object-oriented. It is powerful because its framework, which is also object-oriented, includes robust capabilities you can start using right away, including: native user interface controls, file management, graphics, text processing, networking, threading and more.</p>
<p align="center"><img decoding="async" src="https://www.xojo.com/resources/images/database/Figure04-Code.png" /></p>
<h3>Database Binding for Security</h3>
<p>Xojo has built-in support for SQL binding so that you can avoid the security risks that can occur with <a href="http://blog.xojo.com/2016/02/18/avoiding-sql-injection/">SQL injection</a>, a type of security vulnerability that can occur when you create SQL statements using simple string manipulation.</p>
<h3>Reporting</h3>
<p>What good is data without a way to report on it? Xojo desktop apps can use the built-in reporting tool to help you design and display simple reports. And there are also many <a href="http://documentation.xojo.com/Resources:3rd_Party_Products#Reporting">3rd party reporting products</a> available for those with more advanced needs or for other platforms.</p>
<p align="center"><img decoding="async" src="https://www.xojo.com/resources/images/database/Figure05-Report.png" /></p>
<h3>Documentation</h3>
<p>If you are new to this, read about how to get started on database apps in this <a href="http://blog.xojo.com/2014/07/08/working-with-databases/">earlier post</a>. Xojo has an in-depth <a href="http://documentation.xojo.com/getting_started/introduction/what_is_xojo?.html">User Guide</a>, a complete <a href="http://documentation.xojo.com/Category:Keywords">Language Reference</a>, and a <a href="https://www.youtube.com/playlist?list=PLPoq910Q9jXhRoPw0_mHKdVUKPXpL9TKV">playlist of videos</a> about using databases with Xojo. The User Guide even has sections on migrating from <a href="http://developer.xojo.com/migrating-from-microsoft-access">Microsoft Access</a>, <a href="http://developer.xojo.com/migrating-from-visual-foxpro">Visual FoxPro</a> and <a href="http://developer.xojo.com/migrating-from-filemaker">FileMaker</a>!</p>
<h3>Try Xojo Free</h3>
<p>Xojo is free to use for learning and development. <a href="http://www.xojo.com/download">Download and try it today</a> and see for yourself!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>7 Reasons You Should Be Using PostgreSQL</title>
		<link>https://blog.xojo.com/2017/06/19/7-reasons-you-should-be-using-postgresql/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Mon, 19 Jun 2017 10:49:42 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2709</guid>

					<description><![CDATA[PostgreSQL is an open source object-relational database system that's had more than 15 years of active development. Here are 7 reasons you should be using PostgreSQL.]]></description>
										<content:encoded><![CDATA[<p><a href="https://www.postgresql.org/about/">PostgreSQL</a> is an open source object-relational database system that&#8217;s had more than 15 years of active development. Here are 7 reasons you should be using PostgreSQL.</p>
<p><span id="more-2709"></span></p>
<p><strong>Free<br />
</strong>PostgreSQL is completely free to use. It has a license similar to BSD and MIT which means you can use it with no restrictions whatsoever, unlike other open-source databases such as MySQL.</p>
<p><strong>Easy to setup</strong><br />
Want to test PostgreSQL on macOS? You can use <a href="http://postgresapp.com/" target="_blank" rel="noopener noreferrer">Postgres.app</a> to get a working PostgreSQL database just by running a single app with no installation required at all.</p>
<p>Even if you need to install PostgreSQL, easy installers are also available with pre-built binaries for <a href="http://www.postgresql.org/download/" target="_blank" rel="noopener noreferrer">Windows, macOS and Linux</a>.</p>
<p>If you need more support you can turn to <a href="http://www.enterprisedb.com/" target="_blank" rel="noopener noreferrer">EnterpriseDB</a>, which offers PostgreSQL with support.</p>
<p>Often you don’t even have to bother with installing PostgreSQL because many server hosts automatically provide it as an option that you can easily turn on or configure. For example, with <a href="http://www.xojo.com/cloud" target="_blank" rel="noopener noreferrer">Xojo Cloud</a>, you can enable PostgreSQL with a <a href="http://developer.xojo.com/xojo-cloud">single click in the Control Panel</a>.</p>
<p>With other hosting companies you may have to install PostgreSQL yourself, but steps are often provided. For example, Digital Ocean provides these <a href="https://www.digitalocean.com/community/tutorials/how-to-install-and-use-postgresql-on-centos-7" target="_blank" rel="noopener noreferrer">steps</a> for installing PostgreSQL in CentOS 7.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-2974" src="https://blog.xojo.com/wp-content/uploads/2017/06/postgresql-card.png" alt="" width="480" height="240" /></p>
<p><strong>Powerful</strong><br />
PostgreSQL has all the professional-grade features you expect in a server database. You can have multiple users, multiple databases, stored procedures, robust types for your tables, views, full SQL, backups and more.</p>
<p><strong>Secure</strong><br />
PostgreSQL has SSL for secure connections. It is updated regularly and is used by many, many organizations ensuring that it is kept up-to-date with security updates as necessary. You can find the full PostgreSQL security report <a href="http://www.postgresql.org/support/security/" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p><strong>Flexible</strong></p>
<p>You can use PostgreSQL with any programming language. Because PostgreSQL is so ubiquitous, nearly any programming language easily connects to it. In Xojo, your code would look like this:</p>
<pre>Dim pg As New PostgreSQLDatabase
pg.Host = “sheep”
pg.DatabaseName = “Mary”
pg.Port = 5432
pg.UserName = “lamb”
pg.Password = “foo”
If pg.Connect Then
  // Connected
End If</pre>
<p>In PHP, your code looks like this:</p>
<pre><code>$dbconn3 = pg_connect("host=sheep port=5432 dbname=mary user=lamb password=foo");</code></pre>
<p><strong>Lots of Tools</strong><br />
Working with PostgreSQL is much easier when you use a GUI tool. There are many, many tools available such a pgAdmin, Navicat and SQLPro. For a complete list, refer to the PostgreSQL tool <a href="https://wiki.postgresql.org/wiki/Community_Guide_to_PostgreSQL_GUI_Tools" target="_blank" rel="noopener noreferrer">wiki page</a>.</p>
<p><strong>Documentation</strong><br />
If you do happen to get stumped while working with PostgreSQL, you’ll find there is lot of information and documentation available. The official documentation is available online <a href="http://www.postgresql.org/docs/" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p>There are also dozens of books and information that you can easily find on how to use PostgreSQL, many of which are listed <a href="http://www.postgresql.org/docs/books/" target="_blank" rel="noopener noreferrer">here</a>.</p>
<p>Want to learn even more? Watch this <a href="http://developer.xojo.com/webinar-postgresql">PostgreSQL video</a>.</p>
<p>As the PostgreSQL site says, it is “the world’s most advanced open source database”. Once you give it a try, you will most definitely agree!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Appreciating SQL</title>
		<link>https://blog.xojo.com/2017/05/09/appreciating-sql/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 09 May 2017 19:51:27 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=2651</guid>

					<description><![CDATA[Noted recently at the SQLizer blog, the SQL language was first created 43 years ago. And what is remarkable about that is that SQL is still used today. ]]></description>
										<content:encoded><![CDATA[<p>Noted recently at the <a href="http://blog.sqlizer.io/posts/sql-43/">SQLizer blog</a>, the SQL language was first created 43 years ago. And what is remarkable about that is that SQL is still used today. According to the <a href="https://stackoverflow.com/insights/survey/2017">Stack Overflow 2017 developer survey</a> it is the #2 programming language. Not many languages remain in use for such a long period of time. Although we’re happy to also note that Xojo celebrated our 20th anniversary in 2016!</p>
<p><span id="more-2651"></span></p>
<p>One reason that SQL might rank so high is that it is not really a single language. Although the term SQL is used to refer to the default language used with every relational database, each version is different. SQL actually means <a href="https://en.wikipedia.org/wiki/SQL">Structured Query Language</a>, not Standard Query Language as I often hear people refer to it. Every database that uses SQL also uses its own variant of SQL and these variants differ by just enough to be annoying, although the core commands are mostly the same. It reminds me of how BASIC was in the 1970s and 80s with different versions for each computer with nothing but the most basic (pun intended) compatibility between them.</p>
<p>Even though SQL is a programming language, it is not like languages you are likely most familiar with. You use SQL to write database queries that return sets of data so it works differently than just about any other language you might be familiar with (although some versions add some procedural commands).</p>
<p>For example if you wanted to process a bunch of rows in a typical language you might write code like this to loop through all the data:</p>
<pre>For Each i As Integer = 0 To row.Ubound
 row(i) = row(i) * 2
Next</pre>
<p>In SQL that data would be in a table and you would change the values of all the rows by using an UPDATE command:</p>
<pre>UPDATE data SET value = value * 2;</pre>
<p>Both effectively do a loop, but they don’t look all that similar.</p>
<p>Another interesting thing about SQL is that it really is a companion to any programming language you use to make apps. Since no one would ever make an actual app using just SQL, but most apps need a database of some kind, SQL becomes the 2nd language that you have to know alongside your primary language.</p>
<p>Xojo works with SQL by using one of its database classes to send SQL directly to the database you are using. For example, to work with a SQLite database you would use the SQLiteDatabase class for desktop, web or console app or the iOSSQLiteDatabase class for iOS apps. Those classes each have two methods to send SQL commands to the database: SQLSelect and SQLExecute. Essentially SQLSelect is used for SQL commands that return sets of data and SQLExecute is used for commands that do an action (such as create a table).</p>
<p>Like other programming languages, Xojo does not care what database you use nor does it care what SQL you are sending to it.</p>
<p>You can learn about some common SQL commands in the <a href="http://developer.xojo.com/userguide/database-operations">Database Operations</a> topic of the User Guide at the Xojo Dev Center.</p>
<p>&nbsp;</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>About PostgreSQL Case Sensitivity</title>
		<link>https://blog.xojo.com/2016/09/28/about-postgresql-case-sensitivity/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Wed, 28 Sep 2016 07:01:21 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[SQL]]></category>
		<guid isPermaLink="false">http://blog.xojo.com/?p=1912</guid>

					<description><![CDATA[Sometimes you hear that PostgreSQL is case-insensitive, but it isn't really. What it actually does is convert your SQL to lowercase by default.]]></description>
										<content:encoded><![CDATA[<p>I&#8217;ve ran into PostgreSQL case sensitivity myself before and I&#8217;ve seen it <a href="https://forum.xojo.com/34715-postgresql-and-fieldschema">come up on the forums</a>, so I thought it might be a good thing to bring up here.</p>
<p>Sometimes you hear that PostgreSQL is case-insensitive, but it isn&#8217;t really. What it actually does is convert your SQL to lowercase by default. So take a look at this SQL:</p>
<pre>SELECT FullName FROM Person</pre>
<p>This gets converted to:</p>
<pre>SELECT fullname FROM person</pre>
<p>That is nice if you happen to like to write your queries with mixed casing.</p>
<p><span id="more-1912"></span></p>
<p>But you&#8217;ll start to run into a problem if you&#8217;ve actually created the table with case-sensitive names, which happens when you use quotes around the names. For example, consider these SQL CREATE statements:</p>
<pre>CREATE TABLE person (fullname VARCHAR(100), address VARCHAR(100))</pre>
<pre>CREATE TABLE Person (FullName VARCHAR(100), Address VARCHAR(100))</pre>
<pre>CREATE TABLE "Person" ("FullName" VARCHAR(100), "Address" VARCHAR(100))</pre>
<p>In the first two examples, you get a table called &#8220;person&#8221; with two columns called &#8220;fullname&#8221; and &#8220;address&#8221;. That may not be obvious in the second example since the names are not lowercase, but remember that PostgreSQL converts your SQL to lowercase for you.</p>
<p>In the last example, the names are in quotes so their case is maintained. This means you&#8217;ll get a table called &#8220;Person&#8221; with two columns called &#8220;FullName&#8221; and &#8220;Address&#8221;. Now what happens if you try to run a query with a table called &#8220;Person&#8221;? Well, using SQL like this:</p>
<pre>SELECT FullName FROM Person</pre>
<p>you&#8217;ll get a syntax error:</p>
<p><strong>ERROR: relation &#8220;person&#8221; does not exist</strong><br />
<strong>LINE 1: SELECT FullName FROM Person</strong></p>
<p>This is because PostgreSQL is converting &#8220;Person&#8221; to &#8220;person&#8221;, but there is no table called &#8220;person&#8221;. It is actually called &#8220;Person&#8221;.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-1913" src="https://blog.xojo.com/wp-content/uploads/2016/09/2016-09-23_09-38-33.png" alt="2016-09-23_09-38-33" width="800" height="595" /></p>
<p>To avoid this error you instead have to write the SQL with quotes like this:</p>
<pre>SELECT "FullName" FROM "Person"</pre>
<p>Obviously that can start to become a bit of a pain, so the moral of the story is don&#8217;t use quotes when creating tables or writing SQL queries so that everything is created as lowercase and things will work like you probably expect. You&#8217;ll especially want to pay attention to any tools you use to create SQL for you. If you use a tool&#8217;s UI to create a table and have a habit of typing in mixed case, the tool might generate SQL (or even the table itself) for you using quotes, which as you can see could mess you up later.</p>
<p>Learn more about <a href="http://developer.xojo.com/userguide/postgresql">PostgreSQL</a> in the Xojo Dev Center.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>XojoTalk 027 &#8211; Database Goddess</title>
		<link>https://blog.xojo.com/2016/07/26/xojotalk-027-database-goddess/</link>
					<comments>https://blog.xojo.com/2016/07/26/xojotalk-027-database-goddess/#comments</comments>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 26 Jul 2016 00:00:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[XojoTalk]]></category>
		<category><![CDATA[BKeeney]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Podcast]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Women in Tech]]></category>
		<guid isPermaLink="false">http://blogtemp.xojo.com/?p=367</guid>

					<description><![CDATA[Paul talks with Carol Keeney of BKeeney Software. Topics include databases, requirements analysis, agile/scrum and much more.]]></description>
										<content:encoded><![CDATA[<p>Paul talks with Carol Keeney of BKeeney Software about databases, requirements analysis, agile/scrum and much more.</p>
<p><span id="more-367"></span></p>
<p>Download <a href="http://files.xojo.com/Podcasts/XojoTalk-027.mp3">MP3</a>.</p>
<p><audio class="wp-audio-shortcode" id="audio-367-1" preload="none" style="width: 100%;" controls="controls"><source type="audio/mpeg" src="http://files.xojo.com/Podcasts/XojoTalk-027.mp3?_=1" /><a href="http://files.xojo.com/Podcasts/XojoTalk-027.mp3">http://files.xojo.com/Podcasts/XojoTalk-027.mp3</a></audio></p>
<p>&nbsp;</p>
<h2>Show Notes</h2>
<ul>
<li><a href="http://www.bkeeney.com/">BKeeney Software</a></li>
<li><a href="https://www.microsoft.com/en-us/server-cloud/products/sql-server/">Microsoft SQL Server</a></li>
<li><a href="http://blogs.microsoft.com/blog/2016/03/07/announcing-sql-server-on-linux">Microsoft SQL Server on Linux</a></li>
<li><a href="https://www.navicat.com/">Navicat</a></li>
<li><a href="https://en.wikipedia.org/wiki/Data_definition_language">Data Definition Language</a></li>
<li><a href="http://projectcartoon.com/cartoon/1111">Tree swing Requirements</a></li>
<li><a href="http://www.bkeeney.com/rbinto/activerecord/">ActiveRecord</a></li>
</ul>
<p><!--HubSpot Call-to-Action Code --> <span id="hs-cta-wrapper-32eb9715-5c1c-45a4-9f37-717ffc906d8e" class="hs-cta-wrapper"> <span id="hs-cta-32eb9715-5c1c-45a4-9f37-717ffc906d8e" class="hs-cta-node hs-cta-32eb9715-5c1c-45a4-9f37-717ffc906d8e"><br />
<!-- [if lte IE 8]>


<div id="hs-cta-ie-element"></div>


<![endif]--> <a href="feeds.feedburner.com/xojotalk" target="_blank"><img loading="lazy" decoding="async" id="hs-cta-img-32eb9715-5c1c-45a4-9f37-717ffc906d8e" class="hs-cta-img aligncenter" style="border-width: 0px; margin: 0 auto; display: block; margin-top: 20px; margin-bottom: 20px;" src="https://blog.xojo.com/wp-content/uploads/2014/09/32eb9715-5c1c-45a4-9f37-717ffc906d8e.png" alt="Subscribe Podcast" width="622" height="107" align="middle" /></a></span></span> <!-- end HubSpot Call-to-Action Code --></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.xojo.com/2016/07/26/xojotalk-027-database-goddess/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		<enclosure url="http://files.xojo.com/Podcasts/XojoTalk-027.mp3" length="20845214" type="audio/mpeg" />

			</item>
		<item>
		<title>Database Usage with Web Apps</title>
		<link>https://blog.xojo.com/2016/06/28/database-usage-with-web-apps/</link>
					<comments>https://blog.xojo.com/2016/06/28/database-usage-with-web-apps/#comments</comments>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 28 Jun 2016 09:35:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">http://blogtemp.xojo.com/2016/06/15/database-usage-with-web-apps/</guid>

					<description><![CDATA[A quick tip on how best to connect to databases from web apps.]]></description>
										<content:encoded><![CDATA[<p>Using databases with web apps is not much different than using them with desktop apps, but there are a few things to keep in mind. The most important thing to note is that a web app allows multiple users. This means you&#8217;ll want your database connection to be unique for each user that connects to the web app, rather than global to the app itself (as is common in desktop apps). The simplest way to ensure this is to create the connection to your database in the WebSession.Open event handler, saving a reference to the connection as a property that you add to WebSession.</p>
<p><span id="more-265"></span></p>
<p>A property such as &#8220;DB As SQLiteDatabase&#8221; on the Session object works well. Then in its Open event handler, you actually connect to the database:</p>
<pre>Dim dbFile As FolderItem = GetFolderItem("MyDatabase.sqlite")
DB = New SQLiteDatabase
DB.DatabaseFile = dbFile
If Not db.Connect Then
 ' Display an error page and log the error
 ' You should not show specifics of the error to users
 ErrorPage.Show
End If</pre>
<p>In the rest of your project, you can refer to the database like this:</p>
<pre>Session.DB</pre>
<p>The second thing to remember is that because a web app can be accessed by many more users it is more susceptible to <a href="http://blog.xojo.com/2016/02/18/avoiding-sql-injection/">SQL Injection</a>. To limit your exposure here, you should always use SQL Prepared Statements with any SQL statements that contain parameters with values from user-entered input.</p>
<p>To learn more about databases and web apps, view the <a href="http://developer.xojo.com/database-usage-with-web-apps">Database Usage with Web Apps</a> topic in the Dev Center and watch our <a href="http://developer.xojo.com/webinar-connecting-to-db">Webinar: Connecting to Databases</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.xojo.com/2016/06/28/database-usage-with-web-apps/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
			</item>
		<item>
		<title>Avoiding SQL Injection</title>
		<link>https://blog.xojo.com/2016/02/18/avoiding-sql-injection/</link>
					<comments>https://blog.xojo.com/2016/02/18/avoiding-sql-injection/#comments</comments>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 18 Feb 2016 00:00:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[XKCD]]></category>
		<guid isPermaLink="false">http://blogtemp.xojo.com/2016/02/18/avoiding-sql-injection/</guid>

					<description><![CDATA[An SQL injection can allow unintended database access - here's how a SQL Injection works and what you can do to avoid it.]]></description>
										<content:encoded><![CDATA[<p>Maybe you&#8217;ve heard the term <a href="https://en.wikipedia.org/wiki/SQL_injection" target="_blank" rel="noopener noreferrer">SQL injection</a> and how it can allow unintended database access. Here&#8217;s how a SQL Injection works and what you can do to avoid it.</p>
<p><span id="more-236"></span></p>
<p>Generally, you work with databases by sending SQL commands. In particular the SELECT command is used to get data from a database. These SELECT statements are simply built out of text. This is normally not a problem, but it can be when you start to concatenate text to build an SQL statement.</p>
<p>In particular, the risk occurs when you build an SQL statement with user-supplied input. For example, say you prompt the user for some information to filter (it doesn&#8217;t matter what) and then create an SQL statement by concatenating what they typed. You might have code that looks like this:</p>
<pre>Dim sql As String
sql = "SELECT * FROM Tasks WHERE UserName = 'Paul' AND Title = '" + userValue " + "'"</pre>
<p>If the user types &#8220;Mow&#8221; as the value then the SQL looks like this:</p>
<pre>SELECT * FROM Tasks WHERE UserName = 'Paul' AND Title = 'Mow'</pre>
<p>But what if the user types something a bit more nefarious, such as &#8220;Mow&#8217; OR 1;&#8221;? This now results in SQL that looks like this:</p>
<pre>SELECT * FROM Tasks WHERE UserName = 'Paul' AND Title = 'Mow' OR 1;'</pre>
<p>Now there are two SQL statements. The first one returns all the data in the table (because of the &#8220;OR 1&#8221;) and the second statement (just a &#8216;) is likely just ignored. So now your app is displaying lots of data that the user was not meant to see (perhaps data from other users in this case).</p>
<p>This is called SQL Injection because the user was able to inject their own SQL into your query, all because you were using concatenation.</p>
<p><a href="https://xkcd.com/license.html"><img decoding="async" class="aligncenter" title="" src="https://blog.xojo.com/wp-content/uploads/2016/02/exploits_of_a_mom.png" /></a></p>
<p>So how do you avoid this? Instead of concatenating, you use the databases built-in ability to create <a href="https://en.wikipedia.org/wiki/Prepared_statement">prepared statements</a> by binding values to parameters. For Xojo, you use the appropriate PreparedStatement class for your database. In the case of SQLite, you would use <a href="http://developer.xojo.com/sqlitepreparedstatement">SQLitePreparedStatement</a>.</p>
<p>To start you first declare the SQL to have parameters:</p>
<pre>Dim sql As String
sql = "SELECT * FROM Tasks WHERE UserName = 'Paul' AND TITLE = ?"</pre>
<p>Then you create a prepared statement, bind the value and send it to the database:</p>
<pre>Dim ps As SQLitePreparedStatement
ps = MyDB.Prepare(sql)
ps.BindType(0, SQLitePreparedStatement.SQLITE_TEXT)
ps.Bind(0, userValue)
Dim rs As RecordSet
rs = ps.SQLSelect</pre>
<p><strong>Update (October 10, 2019)</strong>:</p>
<p>If you&#8217;re using API 2.0 in 2019r2 or later, the above code is even simper:</p>
<pre>Var results As RowSet = MyDB.SelectSQL(sql, userValue)</pre>
<p>Because the value is treated as a parameter, if evildoers again try to inject their own SQL, the resulting SQL sent to the database is actually equivalent to this:</p>
<pre>SELECT * FROM Tasks WHERE UserName = 'Paul' AND TITLE = 'Mow'' OR 1;'"</pre>
<p>This is a valid SQL statement that will simply return no rows.</p>
<p>Any apps that embed user input into SQL statements should always use prepared SQL statements. Do not think you can just write your own code to sanitize user input as this still poses a risk.</p>
<p>And there are also reasons to use prepared statements even when SQL injection is not a concern: some databases cache the parsing of the database command, which can result in some performance improvements if the database command is used repeatedly in the app.</p>
<p>Reference: <a href="http://developer.xojo.com/userguide/sql-injection">SQL Injection in the Xojo User Guide</a></p>
<p><!--HubSpot Call-to-Action Code --> <span id="hs-cta-wrapper-de1ba131-3831-49df-90a1-b9efde8e17d2" class="hs-cta-wrapper"> <span id="hs-cta-de1ba131-3831-49df-90a1-b9efde8e17d2" class="hs-cta-node hs-cta-de1ba131-3831-49df-90a1-b9efde8e17d2"><br />
<!-- [if lte IE 8]>


<div id="hs-cta-ie-element"></div>


<![endif]--> <a href="http://blog.xojo.com/2015/12/21/speed-up-sqlite-with-write-ahead-logging/" target="_blank" rel="noopener noreferrer"><img loading="lazy" decoding="async" id="hs-cta-img-de1ba131-3831-49df-90a1-b9efde8e17d2" class="hs-cta-img aligncenter" style="border-width: 0px; margin: 0 auto; display: block; margin-top: 20px; margin-bottom: 20px;" src="https://blog.xojo.com/wp-content/uploads/2016/01/de1ba131-3831-49df-90a1-b9efde8e17d2.png" alt="Code Tip: Speed up SQLite with Write-Ahead Logging" width="393" height="72" align="middle" /></a></span></span></p>
]]></content:encoded>
					
					<wfw:commentRss>https://blog.xojo.com/2016/02/18/avoiding-sql-injection/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
