<?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>Database &#8211; Xojo Programming Blog</title>
	<atom:link href="https://blog.xojo.com/category/database/feed/" rel="self" type="application/rss+xml" />
	<link>https://blog.xojo.com</link>
	<description>Blog about the Xojo programming language and IDE</description>
	<lastBuildDate>Tue, 31 Mar 2026 20:18:09 +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>Year of Code 2025: February Project, Database Apps</title>
		<link>https://blog.xojo.com/2025/02/11/year-of-code-2025-february-project/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 11 Feb 2025 16:48:26 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Fun]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Year of Code]]></category>
		<category><![CDATA[#YearofCode]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Database Applications]]></category>
		<category><![CDATA[GitHub]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14441</guid>

					<description><![CDATA[February&#8217;s&#160;Year of Code 2025&#160;topic is Databases and my project is a SQLite object-relation mapping library that I call Storm. I first created Storm in 2008&#8230;]]></description>
										<content:encoded><![CDATA[
<p>February&#8217;s&nbsp;<a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/" target="_blank" rel="noreferrer noopener">Year of Code 2025</a>&nbsp;topic is Databases and my project is a SQLite object-relation mapping library that I call Storm.</p>



<p>I first created Storm in 2008 when I was working on consulting projects as a way to more rapidly create database apps for clients. It has been updated over the years and the latest version is available on GitHub:</p>



<p><a href="https://github.com/paullefebvre/storm">Storm</a></p>



<p>An ORM lets you write code like this to set database column values and save them:</p>



<pre class="wp-block-code"><code>Var dodgers As New Team
dodgers.Name = "LA Dodgers"
dodgers.Coach = "Dave Roberts"
dodgers.Save</code></pre>



<p>Team is a table in the database with a corresponding class in Xojo that inherits from Storm.DBObject.</p>



<p>The included demo projects shows how you can implement a simple UI for a database with Team and Player tables.</p>



<figure class="wp-block-image size-large is-resized"><img fetchpriority="high" decoding="async" width="1024" height="851" src="https://blog.xojo.com/wp-content/uploads/2025/02/CleanShot-2025-02-04-at-16.45.54@2x-1024x851.png" alt="" class="wp-image-14445" style="width:550px;height:auto" srcset="https://blog.xojo.com/wp-content/uploads/2025/02/CleanShot-2025-02-04-at-16.45.54@2x-1024x851.png 1024w, https://blog.xojo.com/wp-content/uploads/2025/02/CleanShot-2025-02-04-at-16.45.54@2x-300x249.png 300w, https://blog.xojo.com/wp-content/uploads/2025/02/CleanShot-2025-02-04-at-16.45.54@2x-768x639.png 768w, https://blog.xojo.com/wp-content/uploads/2025/02/CleanShot-2025-02-04-at-16.45.54@2x.png 1424w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>The docs for Storm are contained within its <a href="https://github.com/paullefebvre/storm/wiki">Github repository wiki</a>.</p>



<p>In addition to accessing the full repository on GitHub, you can also download <a href="https://github.com/paullefebvre/storm/archive/refs/tags/v1.2.1.zip">Storm as a ZIP</a>.</p>



<p>I’ve created a&nbsp;<a href="https://forum.xojo.com/t/2025-year-of-code-february/84239">forum topic</a>&nbsp;for you to start sharing your Year of Code projects and I’ll also be sure to include this one as well. Remember, <a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/">participants can win a $100</a> to use in the Xojo Store!</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>



<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><strong>Year of Code Project</strong></p>



<ul class="wp-block-list">
<li><a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/">Year of Code: Kickoff</a></li>



<li><a href="https://blog.xojo.com/2025/01/15/year-of-code-2025-january-project/" target="_blank" rel="noreferrer noopener">January Project: Desktop Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/year-of-code-2025-january-project-sharing/83927" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/02/11/year-of-code-2025-february-project/">February Project: Database Apps</a>&nbsp;|&nbsp;<a href="https://forum.xojo.com/t/2025-year-of-code-february" target="_blank" rel="noreferrer noopener">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/03/05/year-of-code-2025-march-project-web-apps/">March Project: Web Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-march/84474?u=alyssa_foley">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/04/08/year-of-code-2025-april-project-user-interface/">April Project: User Interface</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-april-user-interface/84926">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/05/07/year-of-code-2025-may-project-mobile-apps/">May Project: Mobile Apps</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-may-is-mobile/85272">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/06/10/year-of-code-2025-june-project-cross-platform-code-class/">June Project: Code Sharing</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-june-is-code-sharing/85612">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/07/10/year-of-code-2025-july-project-charting/">July Project: Charting</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-july-is-charting/85896">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/08/07/year-of-code-2025-august-project-console-apps/">August Project: Console Apps</a> | <a href="https://forum.xojo.com/t/august-2025-year-of-code-console-apps/86203">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/09/08/year-of-code-2025-september-project-games/">September Project: Games</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-septgamer">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/10/13/year-of-code-2025-october-project-multi-platform-communication/">October Project: Multi-Platform</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-october-multi-platform-communication/86717">Forum Discussion</a></li>



<li><a href="https://blog.xojo.com/2025/11/10/year-of-code-2025-november-project-pdf-postcard-generator/">November Project: PDF</a> | <a href="https://forum.xojo.com/t/2025-year-of-code-november-pdf/86969">Forum Discussion</a></li>
</ul>



<p><strong>How to Play:</strong></p>



<p>Each month we&#8217;ll announce a new theme and share an example project of our own. Share your projects to the Xojo Forum thread for that month via GitHub (all the links you need are posted above ↑ ). Learn how to use <a href="https://blog.xojo.com/2024/04/02/using-xojo-and-github/">Xojo and GitHub</a>.</p>



<p><strong>The Prizes:</strong></p>



<p>Monthly winners get $100 at the Xojo store. Every month you submit a project is another chance to win the grand prize. The grand prize is $250 cash plus a Xojo Pro license and a year of GraffitiSuite and will be announce in December. Learn more about the <a href="https://blog.xojo.com/2025/01/09/year-of-code-2025-kickoff/#prizes">prizes</a>.</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 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>Xojo for 4D Developers</title>
		<link>https://blog.xojo.com/2024/12/10/xojo-for-4d-developers/</link>
		
		<dc:creator><![CDATA[Geoff Perlman]]></dc:creator>
		<pubDate>Tue, 10 Dec 2024 23:35:07 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[4D]]></category>
		<category><![CDATA[Development]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=14178</guid>

					<description><![CDATA[If you are a longtime 4D developer you may recognize my name because I worked for 4D, Inc. (then ACIUS, Inc.) back in the early&#8230;]]></description>
										<content:encoded><![CDATA[
<p>If you are a longtime 4D developer you may recognize my name because I worked for 4D, Inc. (then ACIUS, Inc.) back in the early 1990s, as well as authored a book about 4D. But my experience with 4D goes back even further to 1987 when I began using 4D to build database applications for consulting clients. Over time I found the need to build more general purpose applications. This ultimately resulted in my founding the company that has become Xojo, Inc. and developing and publishing what is now Xojo for the last 28 years. Now, with my credentials out of the way, let’s talk about what Xojo can offer 4D developers.</p>



<p>Like 4D, Xojo has a drag and drop user interface builder, a Code Editor, a Debugger and a Compiler as well as a cross-platform framework. While 4D now has an object-oriented language as an option, Xojo has always been object-oriented. The language is a dot syntax not unlike Javascript. You do not have to become an experienced object-oriented programmer to use Xojo. One of its strengths is that you can learn incrementally.</p>



<p>Xojo supports database application development but there are differences between how it and 4D handles that. 4D has its own database engine and query syntax. Xojo supports SQLite, PostgreSQL, MySQL and ODBC for accessing databases. Unsurprisingly it uses SQL as its query syntax. Because 4D is solely designed for database application development, it ties the user interface you create to tables in the database. Xojo does not. 4D&#8217;s model prevents you from having to write code to get data from database records in and out of your user interface. While by default Xojo does not provide this, it provides an add-on called <a href="https://documentation.xojo.com/topics/databases/dbkit.html" target="_blank" rel="noreferrer noopener">DBKit</a> which assists you in connecting to and interacting with databases.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="660" src="https://blog.xojo.com/wp-content/uploads/2024/12/dbkit_window-1024x660.png" alt="" class="wp-image-14180" srcset="https://blog.xojo.com/wp-content/uploads/2024/12/dbkit_window-1024x660.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/12/dbkit_window-300x193.png 300w, https://blog.xojo.com/wp-content/uploads/2024/12/dbkit_window-768x495.png 768w, https://blog.xojo.com/wp-content/uploads/2024/12/dbkit_window-1536x990.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/12/dbkit_window-2048x1320.png 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Xojo supports desktop development for Linux, macOS, Windows and Raspberry Pi (Linux on ARM). It supports web development as well and mobile development for iOS and Android. You can also build console apps which can be handy when you need an app with no user interface to run on a server. Xojo uses native controls and compiles to native machine code for x86 and ARM. Whether you come to Xojo to build desktop, web or mobile apps, you&#8217;ll find that 95% of what you learn and the code you write will be applicable to all targets. With the exception of iOS (which because of Apple&#8217;s requirements must be built from a Mac) you can build your apps from any platform to any platform. Xojo also includes a Remote Debugger which allows you to build from one operating system and run on another. For example, you might do your development on macOS but want to debug on Windows to track down a Windows-specific issue. With the Remote Debugger, this is quite easy.</p>



<p>Xojo is free to use for development. You only purchase a license when you need to deploy. This is a developer license, not a deployment license. That means that you can deploy as many applications as you like to as many users as you like, without any additional cost. Each developer purchases their own license. A Xojo license comes with 12 months of updates. The new Xojo releases available during your license period continue to be available to you even after your license expires. Renewing your license gets you another 12 months of updates. If you only need to deploy cross-platform desktop applications, the Xojo Desktop license is $399USD. Yearly updates are also $399USD. If you wish to build for any platform we support, the Pro license is $799USD. Yearly updates are also $799USD. <a href="https://xojo.com/store/#prettyPhoto/0/" target="_blank" rel="noreferrer noopener">Compare licenses</a> and find more pricing details at <a href="https://xojo.com/store/" target="_blank" rel="noreferrer noopener">our webstore</a>.</p>



<p>If you&#8217;d like to give Xojo a spin, I recommend starting with the <a href="https://documentation.xojo.com/getting_started/quickstarts/desktop_quickstart.html" target="_blank" rel="noreferrer noopener">QuickStart</a> and then the <a href="https://documentation.xojo.com/getting_started/tutorials/desktop_tutorial.html" target="_blank" rel="noreferrer noopener">full tutorial</a>. After that, check out <a href="https://documentation.xojo.com/topics/databases/dbkit.html" target="_blank" rel="noreferrer noopener">DBKit</a>, the <a href="https://www.youtube.com/watch?v=3Jjf1Xrnm2w&amp;t=401s" target="_blank" rel="noreferrer noopener">video</a> and its <a href="https://documentation.xojo.com/getting_started/tutorials/dbkit_desktop_tutorial.html" target="_blank" rel="noreferrer noopener">tutorial</a> which will make it easier to build database-oriented applications. These are the desktop tutorials but there are also <a href="https://documentation.xojo.com/getting_started/tutorials/index.html" target="_blank" rel="noreferrer noopener">tutorials for mobile and web application development</a>. Because Xojo is a general, cross-platform development tool rather than one specifically for database applications, what you build with it is truly limited only by your imagination. If you have any further questions, please <a href="https://xojo.com/company/contact.php" target="_blank" rel="noreferrer noopener">reach out to us</a>. Our <a href="https://forum.xojo.com" target="_blank" rel="noreferrer noopener">user forum</a> is also filled with experienced and enthusiastic Xojo users that answer and have answered hundreds of questions. And the <a href="https://blog.xojo.com/tag/database/" target="_blank" rel="noreferrer noopener">Xojo Blog</a> has many posts on database development with Xojo.</p>



<p><em>Geoff Perlman is the Founder and CEO of Xojo. When he’s not leading the Xojo team he can be found playing drums in Austin, Texas and spending time with his family.</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>Fuzzy Searches with SQLite&#8217;s SOUNDEX</title>
		<link>https://blog.xojo.com/2024/10/01/fuzzy-searches-with-sqlites-soundex/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Tue, 01 Oct 2024 15:31:15 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[2024r3]]></category>
		<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Fuzzy searches]]></category>
		<category><![CDATA[SoundEx]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[SQLiteDatabase]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13654</guid>

					<description><![CDATA[Though a minor update, Xojo now offers access to another core SQLite function: SOUNDEX. What is SOUNDEX? SOUNDEX is a core function in SQLite that&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Though a minor update, Xojo now offers access to another core SQLite function: SOUNDEX.</p>



<h2 class="wp-block-heading">What is SOUNDEX?</h2>



<p>SOUNDEX is a core function in SQLite that encodes a string into a 4-byte sequence, enabling indexing based on pronunciation. While the technical details of the algorithm are available on <a href="https://en.wikipedia.org/wiki/Soundex" target="_blank" rel="noreferrer noopener">Wikipedia</a>, the gist is that SOUNDEX(&#8220;Smith&#8221;) will match SOUNDEX(&#8220;Smythe&#8221;), making it useful for large searches to identify different spellings of the same term.</p>



<h2 class="wp-block-heading">How is it used?</h2>



<p>For the curious, you can see how words are indexed by simply invoking a select on a SOUNDEX term:</p>



<pre class="wp-block-code"><code>Var db As New SQLiteDatabase
db.Connect

Var rs As RowSet
rs = db.SelectSQL("SELECT SOUNDEX('Smith')")
Var smith As String = rs.ColumnAt(0).StringValue
rs = db.SelectSQL("SELECT SOUNDEX('Smythe')")
Var smythe As String = rs.ColumnAt(0).StringValue</code></pre>



<p>Running this you&#8217;ll notice that &#8216;Smith&#8217; and &#8216;Smythe&#8217; both return the same SOUNDEX 4-byte sequence of &#8220;S530&#8221; &#8212; Here&#8217;s a quick breakdown of how this was generated:</p>



<ol class="wp-block-list">
<li><strong>First Letter (S)</strong>: The first letter of the name stays the same, so &#8220;S&#8221; from the name &#8220;Smith&#8221; or &#8220;Smythe&#8221; becomes the first character in the code.</li>



<li><strong>Numbers (530)</strong>: The remaining characters in the code represent the sounds of the next letters in the name. Each number is based on a group of similar-sounding consonants:
<ul class="wp-block-list">
<li><strong>5</strong>&nbsp;= &#8220;M&#8221; (because M sounds like &#8220;M&#8221; in &#8220;Smith&#8221; or &#8220;Smythe&#8221;)</li>



<li><strong>3</strong>&nbsp;= &#8220;T&#8221; (because T sounds like &#8220;T&#8221; in &#8220;Smith&#8221; or &#8220;Smythe&#8221;)</li>



<li><strong>0</strong>&nbsp;= No sound match or a vowel, so it acts as a filler to complete the 4-character code.</li>
</ul>
</li>
</ol>



<h2 class="wp-block-heading">Practical Use Case</h2>



<p>With a better understanding of the algorithm, we can put it to practical use by searching our database for names that sound similar to &#8220;Smith.&#8221;</p>



<pre class="wp-block-code"><code>db.ExecuteSQL("CREATE TABLE contacts(id INTEGER PRIMARY KEY, name TEXT)")
db.ExecuteSQL("INSERT INTO contacts (name) VALUES ('Smith'), ('Smythe'), ('Simith'), ('John')")

rs = db.SelectSQL("SELECT name FROM contacts WHERE SOUNDEX(name) = SOUNDEX('Smith')")

// Expected to find 3 names: Smith, Smythe, and Simith
Var namesFound As Integer = rs.RowCount</code></pre>



<h2 class="wp-block-heading">The Fuzzy Conclusion</h2>



<p>Because the SOUNDEX algorithm is designed around English pronunciation patterns, it may not work as well for languages with different sound structures or alphabets, so results may vary depending on the language. It&#8217;s also worth noting that this feature is available for all targets, except Android at this time.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</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>Xojo Cloud: More Than Web App Hosting</title>
		<link>https://blog.xojo.com/2024/08/15/xojo-cloud-more-than-web-app-hosting/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Thu, 15 Aug 2024 22:59:40 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[iOS]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[App Hosting]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Push Notifications]]></category>
		<category><![CDATA[SFTP]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[Web Service]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13449</guid>

					<description><![CDATA[What better way to celebrate 10 years of Xojo Cloud than bragging about all the things it can do! When you think of Xojo Cloud,&#8230;]]></description>
										<content:encoded><![CDATA[
<p>What better way to celebrate 10 years of Xojo Cloud than bragging about all the things it can do! When you think of Xojo Cloud, you might think that it is for hosting Xojo web apps. And that&#8217;s true, Xojo Cloud continues to be the best and easiest way to host your Xojo web apps, but Xojo Cloud also offers several useful services for other types of apps.</p>



<h2 class="wp-block-heading">iOS Notifications</h2>



<p>Xojo Cloud can function as an <a href="https://developer.apple.com/documentation/usernotifications/sending-notification-requests-to-apns">Apple Push Notification system</a> (APNs) for handling iOS push notifications. This works with Xojo and non-Xojo iOS apps. All Xojo Cloud servers are pre-configured to <a href="https://documentation.xojo.com/topics/ios/sending_and_receiving_mobile_notifications.html#topics-ios-creating-notifications-on-the-user-s-mobile-device-using-xojo-cloud-to-send-remote-notifications">send remote notifications</a>. Unlike many other cloud hosts, there is no extra charge for this feature nor is there any limit as to how many notifications you can send.</p>



<p>To send remote notifications from your iOS app you&#8217;ll need to go to the Apple Developer website to do these tasks:</p>



<ol class="wp-block-list">
<li>Add the Push Notifications feature to the App ID.</li>



<li>Generate an Apple Push Services certificate.</li>
</ol>



<p>In Xojo you need to enable the Remote Notifications entitlement for your app in the Capabilities section of the iOS Build Settings Advanced tab.</p>



<p>The final step is to upload your Push Services certificate using the Xojo Cloud control panel.</p>



<p>With super-easy access and no limits for notifications, Xojo Cloud can serve as a great APNs for handling your iOS notification needs.</p>



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



<p>Most desktop apps use a database of some kind and many are client/server database apps that talk directly to the database server. With Xojo Cloud you can host PostgreSQL or MariaDB/MySQL database servers and connect to them using an SSH tunnel for security purposes.</p>



<p>Setting up a database server on your Xojo Cloud is as easy as checking a box in the control panel.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="630" src="https://blog.xojo.com/wp-content/uploads/2024/08/image-1024x630.png" alt="" class="wp-image-13451" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/image-1024x630.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/08/image-300x185.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/image-768x472.png 768w, https://blog.xojo.com/wp-content/uploads/2024/08/image.png 1398w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You can turn on PostgreSQL or MySQL/MariaDB. If your Xojo Cloud server is large enough you could even do both.</p>



<p>If you want to access a database on Xojo Cloud from a desktop app, you will have to enable the SSH Tunnel and then connect to the tunnel from the computer. An SSH tunnel is a secure connection between your computer and another (in this case your Xojo Cloud server) which is used for transmitting data on a specific port. In essence, it creates a private connection through the internet which allows you to see into your server on the other end and connect to a particular service there.</p>



<p>To create a tunnel between a computer and your Xojo Cloud server, you first need to turn on the tunnel capability on your Xojo Cloud server. Go to your control panel and click the &#8220;SSH Tunnel&#8221; checkbox. You will be presented with a generated username and a password which you will use later for establishing the connection.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="694" height="302" src="https://blog.xojo.com/wp-content/uploads/2024/08/image-1.png" alt="" class="wp-image-13453" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/image-1.png 694w, https://blog.xojo.com/wp-content/uploads/2024/08/image-1-300x131.png 300w" sizes="auto, (max-width: 694px) 100vw, 694px" /></figure>



<p>On macOS and Linux, you can use a terminal command to access the tunnel (replace username and ipaddress as appropriate; you&#8217;ll be prompted for the password).</p>



<p>Use this command to tunnel to PostgreSQL:</p>



<pre class="wp-block-code"><code>ssh -L 5432:localhost:5432 username@ipaddress -N</code></pre>



<p>Use this command to tunnel to MySQL:</p>



<pre class="wp-block-code"><code>ssh -L 3306:localhost:3306 username@ipaddress -N</code></pre>



<p>If you are using Windows, you will need to use an external app such as PuTTY. There are a number of tutorials available on the internet, just put “putty ssh tunnel” into your favorite search engine.</p>



<p>With the tunnel in place you connect to the database as if it were local to the computer. This works with anything, not just Xojo apps.</p>



<h2 class="wp-block-heading">SFTP</h2>



<p>Xojo Cloud offers SFTP (Secure File Transfer Protocol) for file transfer. SFTP is a secure variant of FTP which transmits files over the internet using strong encryption. That way you don&#8217;t have to worry about anyone intercepting your username and password or your files as they&#8217;re sent to or from your server.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>When choosing a client, keep in mind that SFTP is different than FTPS or FTP w/ SSL. They are not interchangeable with one another.</p>
</blockquote>



<p>Once you enable SFTP in the Control Panel, you&#8217;ll be presented with a dialog showing a generated username and password.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="447" src="https://blog.xojo.com/wp-content/uploads/2024/08/image-2-1024x447.png" alt="" class="wp-image-13454" srcset="https://blog.xojo.com/wp-content/uploads/2024/08/image-2-1024x447.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/08/image-2-300x131.png 300w, https://blog.xojo.com/wp-content/uploads/2024/08/image-2-768x335.png 768w, https://blog.xojo.com/wp-content/uploads/2024/08/image-2.png 1186w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You can now connect using your favorite SFTP client. If you don&#8217;t have one, there are a number of free and paid options available including:</p>



<ul class="wp-block-list">
<li>ForkLift</li>



<li>Transmit</li>



<li>FileZilla</li>



<li>CyberDuck</li>
</ul>



<p>Having a place to store files online is always handy and can be useful when needing to share files with others without having to rely on services such as DropBox.</p>



<h2 class="wp-block-heading">Web Services</h2>



<p>OK, a web service is technically a Xojo web app but it is really an API that is meant to be used by other apps, often desktop or mobile apps. Since a web service doesn’t have any actual UI, you don’t really need to learn how to use the majority of the Xojo Web framework.</p>



<p>Instead you basically add code to the <a href="https://documentation.xojo.com/api/web/webapplication.html#webapplication-handleurl">App.HandleURL</a> event to route web service API calls to do specific tasks and then return the results, usually as JSON for the client app to handle.</p>



<p>A web service can be a great way to consolidate code that will be used by desktop and mobile apps, for example.</p>



<p>For example, you could create a Web Service that talks to a database server (such as one of the ones available in Xojo Cloud itself). Your Desktop and Mobile apps can use the same web service to work with the database. All your database-specific code lives in the web service and the client apps make requests and display results.</p>



<p>This is a very common design pattern these days and is a necessary one if you want a mobile app to talk to a database server.</p>



<p>If you want to learn more about web services, here&#8217;s a fun webinar to check out:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Using Xojo and the Star Wars API" width="500" height="281" src="https://www.youtube.com/embed/hwhkZtP6fA8?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>Learn more about <a href="https://xojo.com/cloud/">Xojo Cloud</a> today. Xojo Cloud servers start at $49/month, custom servers with more RAM, storage, and virtual CPUs are available. The best way to host your Xojo web apps is so much more than just hosting web apps!</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>



<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>Using a WebDataSource to Display Millions of Rows in a WebListBox</title>
		<link>https://blog.xojo.com/2024/08/01/using-a-webdatasource-to-display-millions-of-rows-in-a-weblistbox/</link>
		
		<dc:creator><![CDATA[Ricardo Cruz]]></dc:creator>
		<pubDate>Thu, 01 Aug 2024 18:31:45 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[SQLiteDatabase]]></category>
		<category><![CDATA[Web 2.0]]></category>
		<category><![CDATA[Web Development]]></category>
		<category><![CDATA[WebListBox]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13373</guid>

					<description><![CDATA[If you are wondering why you would use a WebDataSource for your WebListBox, this post will give you some arguments and tips for making that decision and implementing it.]]></description>
										<content:encoded><![CDATA[
<p>If you are wondering why you would use a WebDataSource for your WebListBox, this post gives you some arguments and tips for making that decision and implementing it.</p>



<h2 class="wp-block-heading">Why would you need a WebDataSource, isn’t AddRow enough?</h2>



<p>If you are making a quick prototype, or for small data sets that won&#8217;t grow too much, yes, you can absolutely place a WebListBox into your WebPage and fill it using AddRow. If your WebListBox displays a fixed, small amount of data, say around 500~1000 rows, WebDataSource can be overkill.<br><br>However, for data that comes from a large database, it&#8217;s a different story. You could waste precious server resources duplicating the same data you have in your database into your app’s memory. And even worse, the data would be duplicated in every Session seeing that WebListBox.<br><br>In this tutorial, this is the WebListBox we are going to build:</p>



<figure class="wp-block-video"><video height="1416" style="aspect-ratio: 1368 / 1416;" width="1368" controls src="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-14.42.03.mp4.mp4"></video></figure>



<h2 class="wp-block-heading">Let’s prepare a million records database to play with.</h2>



<p>In this example we will use a humble SQLite database, but keep in mind a WebDataSource can be anything. For example you could display the result of calling an external API, or your hard drive filesystem.</p>



<p>The following SQL creates a table called “things”, with three columns: “foo”, “bar” and “baz” with one million rows:</p>



<pre class="wp-block-code"><code>CREATE TABLE things (
  id    INTEGER PRIMARY KEY AUTOINCREMENT,
  foo TEXT,
  bar TEXT,
  baz TEXT
);

-- Time to populate that table
WITH RECURSIVE cnt(x) AS 
(
   SELECT
      1 
   UNION ALL
   SELECT
      x + 1 
   FROM
      cnt LIMIT 1000000
)
INSERT INTO things (foo, bar, baz)
SELECT
    'foo_' || x AS foo,
    'bar_' || x  AS bar,
    'baz_' || x AS baz
FROM cnt;

-- Finally, let's create some indexes, so we can sort the columns quickly
CREATE INDEX "idx_foo" ON things (
    foo, id, bar, baz
);

CREATE INDEX "idx_bar" ON things (
    bar, id, foo, baz
);

CREATE INDEX "idx_baz" ON things (
    baz, id, foo, bar
);

VACUUM;</code></pre>



<p>We just need to store this SQL as a string constant, for convenience. Let’s create one, called <code>kDatabaseSetupSQLite</code> in your Application class, and paste it above the SQL code.</p>



<h2 class="wp-block-heading">First Time Setup</h2>



<p>The first time we launch the application, we need to make sure our database file has been created and populated. It won&#8217;t take too much to generate the database, but we&#8217;ll try to do it just once anyway.</p>



<p>Create a new method in your App class, called DBFile, that returns a FolderItem, pointing to the place we want to store the DataBase. Make it Public, as we will use this method later from the Session. The contents:</p>



<pre class="wp-block-code"><code>Return SpecialFolder.Desktop.Child("test-db.sqlite")</code></pre>



<p>Nothing fancy. Use another path if you want. It will be around ~200MB, just remember to delete it when you don&#8217;t need it anymore.</p>



<p>Let&#8217;s create another App method, called SetupDatabase. It will be in charge of creating and populating the database just once, so if you restart the server, the data will still be there:</p>



<pre class="wp-block-code"><code>Var db As New SQLiteDatabase
db.DatabaseFile = DBFile
db.WriteAheadLogging = True

// The file is already there, no need to build it again
If db.DatabaseFile.Exists Then
  Return
End If

db.CreateDatabase
db.Connect
db.ExecuteSQL(kDatabaseSetupSQLite)</code></pre>



<p>Lastly, implement the App.Opening event and add a method call to SetupDatabase:</p>



<pre class="wp-block-code"><code>SetupDatabase</code></pre>



<p>That should do the trick.</p>



<h2 class="wp-block-heading">Preparing the Session</h2>



<p>It&#8217;s recommended to have a Database instance for each Session. Add a new public Property to your Session class called Database of type SQLiteDatabase.</p>



<p>Then, add a handler for the Opening event with the following code:</p>



<pre class="wp-block-code"><code>Database = New SQLiteDatabase
Database.DatabaseFile = App.DBFile
Database.WriteAheadLogging = True
Database.Connect</code></pre>



<p>Every time a user arrives to the web application, a new isolated SQLiteDatabase connection will be created.</p>



<h2 class="wp-block-heading">Implementing the WebDataSource Interface</h2>



<p>Since Xojo 2024r2, the amount of methods you need in order to implement WebDataSource has been reduced.</p>



<p>Create a new class called DatabaseDataSource. Then, in the inspector panel, select the WebDataSource interface:</p>



<figure class="wp-block-video"><video height="1528" style="aspect-ratio: 2560 / 1528;" width="2560" controls src="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-11.48.19.mp4.mp4"></video></figure>



<p>This includes the three required methods: ColumnData, RowCount and RowData.</p>



<p><strong>ColumnData</strong><br>In this method, you need to return an array of <a href="https://documentation.xojo.com/api/web/weblistboxcolumndata.html#weblistboxcolumndata">WebListBoxColumnData</a>. We have four columns in this example, here is the code:</p>



<pre class="wp-block-code"><code>Var result() As WebListBoxColumnData
result.Add(New WebListBoxColumnData("ID", "id"))
result.Add(New WebListBoxColumnData("Foo", "foo"))
result.Add(New WebListBoxColumnData("Bar", "bar"))
result.Add(New WebListBoxColumnData("Baz", "baz"))

Return result</code></pre>



<p><strong>RowCount</strong><br>Xojo needs to know the amount of data your data source has. Returning an Integer is enough, but we will query our database.</p>



<pre class="wp-block-code"><code>Try
  Var rows As RowSet = Session.Database.SelectSQL("SELECT COUNT(*) AS counter FROM things")
  Return rows.Column("counter").IntegerValue
Catch DatabaseException
  Return 0
End Try</code></pre>



<p><strong>RowData</strong><br>This is the place where you need to return the row contents. As you can see, there is a rowCount and a rowOffset parameter, meaning that we won&#8217;t need to return 1 million records. The control just loads a subset. The amount is dynamically calculated, and varies depending on the height of your WebListBox and the height of the rows.</p>



<p>A sortColumns parameter is also provided. If you allow your users to sort the columns, you need to use it to know the column and direction. Fortunately, this example has sortable columns. Here is the code to comply with the WebDataSource Interface:</p>



<pre class="wp-block-code"><code>Var sql As String = "SELECT id, foo, bar, baz FROM things"
If sortColumns &lt;&gt; "" Then
  sql = sql + " ORDER BY " + sortColumns
End If
sql = sql + " LIMIT " + rowOffset.ToString + ", " + rowCount.ToString

Var result() As WebListBoxRowData
Var rows As RowSet = Session.Database.SelectSQL(sql)

// This isn't needed, it's just to demonstrate how to use cell renderers
Var style As New WebStyle
style.Bold = True
style.BackgroundColor = Color.Teal
style.ForegroundColor = Color.White

For Each row As DatabaseRow In rows
  Var newRowData As New WebListBoxRowData
  newRowData.PrimaryKey = row.Column("id").IntegerValue
  newRowData.Value("id") = row.Column("id")
  newRowData.Value("foo") = row.Column("foo")
  newRowData.Value("bar") = New WebListBoxStyleRenderer(style, row.Column("bar"))
  newRowData.Value("baz") = row.Column("baz")
  result.Add(newRowData)
Next

Return result</code></pre>



<h2 class="wp-block-heading">Preparing the User Interface</h2>



<p>You&#8217;ve reached the easiest part, building the interface takes less than a minute.</p>



<ol class="wp-block-list">
<li>Drop a DatabaseDataSource control into your WebPage</li>



<li>Drop a WebListBox control into your WebPage</li>



<li>In the WebListBox Opening event, configure the DataSource</li>
</ol>



<p>If you name your DataSource instance &#8220;MyDataSource&#8221;, this is the line of code required in the WebListBox Opening event:</p>



<pre class="wp-block-code"><code>Me.DataSource = MyDataSource</code></pre>



<p>Here is a short video:</p>



<figure class="wp-block-video"><video height="1682" style="aspect-ratio: 2800 / 1682;" width="2800" controls src="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-12.21.41.mp4.mp4"></video></figure>



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



<p>The WebListBox control, when combined with a WebDataSource, is a very robust and performant solution for displaying a large set of data.</p>



<p>Download the project:</p>



<div class="wp-block-file"><a id="wp-block-file--media-6f1fe487-dbb0-4d6e-a5c9-3a89f0f2fb9b" href="https://blog.xojo.com/wp-content/uploads/2024/07/weblistbox-million-rows.xojo_binary_project-1.zip">weblistbox-million-rows.xojo_binary_project</a></div>



<p>Happy coding!</p>



<p><em>Ricardo has always been curious about how things work. Growing up surrounded by computers</em> he became interested in <em>web technologies in the dial-up connections era. Xojo has been his secret weapon and language of preference since 2018. When he’s not online, chances are he will be scuba diving … or crocheting amigurumis. Find Ricardo on Twitter <a href="https://web.archive.org/web/20220805000833/https://www.twitter.com/piradoiv" target="_blank" rel="noreferrer noopener">@piradoiv</a>.</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>
					
		
		<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-14.42.03.mp4.mp4" length="2629948" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-11.48.19.mp4.mp4" length="1234967" type="video/mp4" />
<enclosure url="https://blog.xojo.com/wp-content/uploads/2024/07/Grabacion-de-pantalla-2024-06-18-a-las-12.21.41.mp4.mp4" length="2146506" type="video/mp4" />

			</item>
		<item>
		<title>New Database Connections</title>
		<link>https://blog.xojo.com/2024/06/26/new-database-connections/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Wed, 26 Jun 2024 15:00:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[2024r2]]></category>
		<category><![CDATA[Beginner Tips]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[ODBC]]></category>
		<category><![CDATA[PostgreSQL]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=13226</guid>

					<description><![CDATA[While Xojo has always supported adding database connections, the old method was far from ideal. Let's delve into the improved approach using the new DatabaseConnection project items and explore some recent additions to our database API.]]></description>
										<content:encoded><![CDATA[
<p>While Xojo has always supported adding database connections, the old method was far from ideal. Let&#8217;s delve into the improved approach using the new Database Connection project items and explore some recent additions to our database API.</p>



<h2 class="wp-block-heading">Out With The Old</h2>



<p>The old database connections were quite limiting, requiring you to create a new connection and re-enter all the parameters whenever one changed. With our new Database Connection items, you can now easily update specific connection parameters directly in the inspector.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="303" src="https://blog.xojo.com/wp-content/uploads/2024/06/PostgresqlDBConnectionModification-1024x303.png" alt="" class="wp-image-13230" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/PostgresqlDBConnectionModification-1024x303.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/06/PostgresqlDBConnectionModification-300x89.png 300w, https://blog.xojo.com/wp-content/uploads/2024/06/PostgresqlDBConnectionModification-768x228.png 768w, https://blog.xojo.com/wp-content/uploads/2024/06/PostgresqlDBConnectionModification-1536x455.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/06/PostgresqlDBConnectionModification-2048x607.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Additionally, you can now choose whether the item will auto-connect or if you prefer to connect to it later in your code.</p>



<h2 class="wp-block-heading">Connecting to a Specific Database</h2>



<p>There are times when you need to connect to a database for debugging and testing, but for the final builds, you want to connect to your production database/server. Setting this up correctly with the old database connection method required creating two separate connection items—one for debug and one for release. With the new Database Connection items, this process is much simpler and fits more easily into the build process.  You now have several new Database Connection subitems that can be customized based on the stage of your build. These subitems are linked to the Stage Code in your Shared Build Settings, ensuring that when you build a final release, your database connection uses the correct settings automatically.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="329" src="https://blog.xojo.com/wp-content/uploads/2024/06/DatabaseConnectionStageCode-1024x329.png" alt="" class="wp-image-13238" srcset="https://blog.xojo.com/wp-content/uploads/2024/06/DatabaseConnectionStageCode-1024x329.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/06/DatabaseConnectionStageCode-300x96.png 300w, https://blog.xojo.com/wp-content/uploads/2024/06/DatabaseConnectionStageCode-768x247.png 768w, https://blog.xojo.com/wp-content/uploads/2024/06/DatabaseConnectionStageCode-1536x493.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/06/DatabaseConnectionStageCode.png 1968w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Additional Database Features</h2>



<p>In addition to this change, there are two new database APIs that may be useful to you:</p>



<ol class="wp-block-list">
<li>A new method, IsConnected, has been added to the SQLiteDatabase, ODBCDatabase, PostgreSQLDatabase, and MySQLCommunityServer classes. This method returns true if the connection is still active, and false if it is not.</li>



<li>We&#8217;ve enhanced <a href="https://documentation.xojo.com/api/databases/database.html#database-addrow">Database.AddRow</a> with a new signature that returns the unique ID of the newly inserted row. This feature is supported for SQLiteDatabase, ODBCDatabase, PostgreSQLDatabase, and MySQLCommunityServer classes. It is recommended to use this new API instead of the deprecated SQLiteDatabase.LastRowID and MySQLCommunityServer.LastInsertedRowID</li>
</ol>



<p>Let&#8217;s explore how the new Database.AddRow feature can assist you. Previously, only SQLiteDatabase and MySQLCommunityServer had APIs to retrieve the unique ID of the last inserted row. Now, PostgreSQLDatabase and ODBCDatabase also have this capability by using the new <code>Database.AddRow(tableName As String, row As DatabaseRow, idColumnName As String = "") As Integer</code></p>



<p>The new aspect of this signature is the idColumnName parameter and the return value. For databases that support the SQL <strong>RETURNING</strong> clause, the idColumnName specifies the column whose value will be returned.  For databases that do not support the <strong>RETURNING</strong> clause, we will use the suitable method for each specific database to return a unique value.</p>



<p>We recognize the significance of databases in your Xojo apps. So with these updates to database connectivity for your desktop, web and console apps, and the addition of new features, we aim to make your database programming easier and more efficient.</p>



<p><em><em><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo’s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</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>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 loading="lazy" 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="auto, (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 loading="lazy" 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="auto, (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>SQLite 3.45.1</title>
		<link>https://blog.xojo.com/2024/03/26/sqlite-3-45-1/</link>
		
		<dc:creator><![CDATA[Paul Lefebvre]]></dc:creator>
		<pubDate>Tue, 26 Mar 2024 15:27:31 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[2024r1]]></category>
		<category><![CDATA[Database Applications]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[SQLite]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=12700</guid>

					<description><![CDATA[Xojo 2024 Release 1 includes an updated version of SQLite for your Desktop, Web, Console and iOS apps. We have upgraded the library from 3.39.4 (which is from 2022-09-29) to 3.45.1 (released 2024-01-30). Here are a few of the improvements.]]></description>
										<content:encoded><![CDATA[
<p>Xojo 2024 Release 1 includes an updated version of SQLite for your Desktop, Web, Console and iOS apps. We have upgraded the library from 3.39.4 (which is from 2022-09-29) to 3.45.1 (released 2024-01-30). Here are a few of the improvements.</p>



<h2 class="wp-block-heading">Functions</h2>



<p>There are a few new SQLite functions that can now be used in your SQL statements.</p>



<p><strong>concat()</strong></p>



<p>The <a href="https://www.sqlite.org/lang_corefunc.html#concat">concat()</a> function takes an arbitrary number of string parameters and concatenates them all together. Previous versions of SQLite required you to instead use the concat operator, this is the double-pipe: ||. Concat() is a standard function on many other databases (PostgreSQL, MySQL and SQL Server) so it is nice to finally see it available on SQLite as it allow more consistent SQL code.</p>



<p>Using the Chinook sample database, this SQL concatenates the Name and Composer columns from the Track table:</p>



<pre class="wp-block-code"><code>SELECT concat(Name, ‘ by ‘, Composer) FROM Track</code></pre>



<p>Here is the output:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="652" src="https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1024x652.png" alt="" class="wp-image-12701" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1024x652.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-300x191.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-768x489.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1536x978.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-2048x1304.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong>concat_ws()</strong></p>



<p>The <a href="https://www.sqlite.org/lang_corefunc.html#concat_ws">concat_ws()</a> method is <strong>concat</strong> but <strong>w</strong>ith a <strong>s</strong>eparator. Strange naming aside, it works the same except that the first parameter is used a separator that is inserted between each string. This SQL separates the Name, Composer and Milliseconds with &#8220;&#8212;&#8220;:</p>



<pre class="wp-block-code"><code>SELECT concat_ws(‘---‘, Name, Composer, Milliseconds) FROM Track</code></pre>



<p>Here is the output:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="652" src="https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1-1024x652.png" alt="" class="wp-image-12702" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1-1024x652.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1-300x191.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1-768x489.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1-1536x978.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-1-2048x1304.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p><strong>timediff()</strong></p>



<p>The <a href="https://www.sqlite.org/lang_datefunc.html#tmdif">timediff()</a> function calculates the elapsed time between two dates and returns the result in a human-readable format.</p>



<p>This SQL displays the time difference between Dec 12, 2023 and March 26, 2024:</p>



<pre class="wp-block-code"><code>SELECT timediff('2023-12-12','2024-03-26')</code></pre>



<p>Here is the output of 3 months and 14 days (note that it is negative because the earlier date is first in the parameter list):</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="652" src="https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-2-1024x652.png" alt="" class="wp-image-12703" srcset="https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-2-1024x652.png 1024w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-2-300x191.png 300w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-2-768x489.png 768w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-2-1536x978.png 1536w, https://blog.xojo.com/wp-content/uploads/2024/03/Pasted-Graphic-2-2048x1304.png 2048w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Other Changes</h2>



<p>Overall I didn&#8217;t notice many other other significant new features. However, many bugs have been fixed, especially around  database integrity checks and the somewhat <a href="https://blog.xojo.com/2022/12/13/sqlite-new-features-in-xojo-2022r4">new JSON support</a>.</p>



<p>You can find the full list of SQLite changes on their <a href="https://www.sqlite.org/changes.html">Release History 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>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>PDFTable from a RowSet</title>
		<link>https://blog.xojo.com/2023/01/17/pdftable-from-a-rowset/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Tue, 17 Jan 2023 16:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Desktop]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Eddie&#039;s Electronics]]></category>
		<category><![CDATA[PDF]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Tables]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=11146</guid>

					<description><![CDATA[Xojo recently introduced the ability to add (aka draw) tables in PDFDocument using the PDFTable class and the PDFTableDataSource class interface together. Perhaps you already know how to use it, but what if you want to add a table using data from a RowSet? Continue reading and I will show you a technique that will have you doing just that!]]></description>
										<content:encoded><![CDATA[
<p>Xojo recently introduced the ability to add (aka draw) tables in <a href="https://documentation.xojo.com/api/pdf/pdfdocument.html#pdfdocument">PDFDocument</a> using the <a href="https://documentation.xojo.com/api/pdf/pdftable.html#pdftable">PDFTable</a> class and the <a href="https://documentation.xojo.com/api/pdf/pdftabledatasource.html#pdftabledatasource">PDFTableDataSource</a> class interface together. Perhaps you already know how to use it, but what if you want to add a table using data from a <a href="https://documentation.xojo.com/api/databases/rowset.html#rowset">RowSet</a>? Continue reading and I will show you a technique that will have you doing just that!</p>



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



<p>But before we dive into the code,&nbsp;this example project requires the &#8220;EddiesElectronics.sqlite&#8221; SQLite database file. You can find the Eddie&#8217;s Electronics example, along with the other example projects provided with Xojo, in the Examples section of the Project Chooser. Because I am such a kind person, you can also <a href="https://drive.google.com/file/d/1zts_ZL2ZQujW7fWD1m2qr_XpQGq3dbHD/view?usp=share_link">download it directly from this link</a>.</p>



<p>And, if you want, it is also possible to download the resulting <a href="https://drive.google.com/file/d/1Z5Eurwxm7UXlCLU_aj270SNKnlDmpT7Z/view?usp=share_link">Xojo Project file (for Desktop) from this link</a>.</p>



<p>I&#8217;m pretty sure you will be able to adapt the example project so it works for you with other databases too!</p>



<figure class="wp-block-image is-style-default"><img loading="lazy" decoding="async" width="809" height="1024" src="https://blog.xojo.com/wp-content/uploads/2023/01/GeneratedPDF-809x1024.png" alt="" class="wp-image-11149" srcset="https://blog.xojo.com/wp-content/uploads/2023/01/GeneratedPDF-809x1024.png 809w, https://blog.xojo.com/wp-content/uploads/2023/01/GeneratedPDF-237x300.png 237w, https://blog.xojo.com/wp-content/uploads/2023/01/GeneratedPDF-768x972.png 768w, https://blog.xojo.com/wp-content/uploads/2023/01/GeneratedPDF-1214x1536.png 1214w, https://blog.xojo.com/wp-content/uploads/2023/01/GeneratedPDF.png 1342w" sizes="auto, (max-width: 809px) 100vw, 809px" /></figure>



<h3 class="wp-block-heading">Helper class to the rescue!</h3>



<p>All the work of drawing the table in the PDF document will be done by a helper class. That is, a class that we are going to use to &#8220;delegate&#8221; the work. With Xojo open and a new Desktop project created, the first thing we are going to do is add a new Class to the project (Insert &gt; Class).</p>



<p>With the added Class selected in the Navigator, go to the associated Inspector Panel and use the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> PDFRenderer</li>



<li><strong>Interfaces:</strong> Click on the &#8220;Choose&#8221; button and select the PDFTableDataSource class interface</li>
</ul>



<p>The just added Class will be populated with all the methods defined by the PDFTableDataSource class interface. Do not worry about them now.</p>



<p>Next, let&#8217;s add a few properties to our PDFRenderer class:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> data</li>



<li><strong>Type:</strong> RowSet</li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<ul class="wp-block-list">
<li><strong>Name:</strong> document</li>



<li><strong>Type:</strong> PDFDocument</li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<ul class="wp-block-list">
<li><strong>Name:</strong> DrawingFromRowSet</li>



<li><strong>Type:</strong> Boolean</li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<ul class="wp-block-list">
<li><strong>Name:</strong> Headers()</li>



<li><span style="font-size: revert;"><strong>Type:</strong> String</span></li>



<li><span style="font-size: revert;"><strong>Scope:</strong> Protected</span></li>
</ul>



<p>We are going to use the DrawingFromRowSet as a flag, so the PDFRenderer knows when the table is going to be created from a RowSet. You could use any other data source, you are limited to RowSet. That&#8217;s just something you will need to implement yourself! Take it as an exercise.</p>



<p>Next, add a new Method to the PDFRenderer class (while still selected in the Navigator) using the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> Constructor</li>



<li><strong>Parameters:</strong> document As PDFDocument</li>



<li><strong>Scope:</strong> Public</li>
</ul>



<p>And type the following line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted xojo"><code>Self.Document = document</code></pre>



<p>Yep, it is truly that simple. Assign the received PDFDocument object to the &#8220;Document&#8221; property of the object created from the PDFRenderer class.</p>



<p>Add a second method using the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> DrawTable</li>



<li><strong>Parameters:</strong> rs As RowSet, headers() As String</li>



<li><strong>Scope:</strong> Public</li>
</ul>



<p>And type the following code in the associated Code Editor:</p>



<pre class="wp-block-preformatted"><code>// This is the method we call on the Class to draw
// a table on a PDFDocument based on a RowSet

If document &lt;&gt; Nil And rs &lt;&gt; Nil Then

  // Assign the received RowSet to the "Data" property
  Self.data = rs

  // Assign the received headers to the "Headers" property
  Self.Headers = Headers

  // Hey! We are going to create a table from a RowSet
  // so we use a Boolean property as a flag for that
  // (Yeah, we can do it using other techniques, but this
  // is easy enough for this purpose…&nbsp;while leave this
  // helper class "open" enough for drawing tables based on other
  // data sources).
  Self.DrawingFromRowSet = True

  // How many columns are we going to draw?
  // Well… as many as columns in the RowSet.
  Var totalColumns As Integer = rs.ColumnCount

  // This is going to be the "drawable area" on the page
  // for the table = total page width less the left and right margins
  Var totalWidth As Double = document.Graphics.Width - 40 // 40 = 20 points left/right margins

  // Creating the PDFTable object here!
  Var table As New PDFTable

  // We want to repeat the headers on every page
  table.HasRepeatingHeader = True

  // Setting the column count for the table
  table.ColumnCount = totalColumns

  // …and the width for every column.
  table.ColumnWidths = CalculateColumnWidths(TotalWidth, totalColumns)

  // The object from this class will be the responsible
  // for handling all the methods associated with the
  // PDFTableDataSouce Class Interface
  table.DataSource = Self

  // Setting the Top and Bottom margins for the drawing
  // of the table on every PDF page
  table.TopMargin = 20
  table.BottomMargin = 20

  // …and finally we instruct the PDFDocument object
  // to draw the table!
  document.AddTable(table, 20, 0)

  // Lastly, clearing the flag
  Self.DrawingFromRowSet = False

End If</code></pre>



<p>As you can see here, we are calling the &#8220;CalculateColumnWidths&#8221; method in order to get the expected string for the column widths for the PDFTable.ColumnWidths property; so add a new method to the PDFRenderer class using the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> CalculateColumnWidths</li>



<li><strong>Parameters:</strong> TotalWidth As Double, NumberOfColumns As Double</li>



<li><strong>Return Type:</strong> String</li>



<li><strong>Scope:</strong> Protected</li>
</ul>



<p>And type the following snippet of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted"><code>Var ColumnWidth As Integer = TotalWidth / NumberOfColumns
Var s() As String

For n As Integer = 0 To NumberOfColumns-1
  s.Add(Str(ColumnWidth))
Next

Return String.FromArray(s, ",")</code></pre>



<h3 class="wp-block-heading">PDFTableDataSource Methods with RowSet data!</h3>



<p>Let&#8217;s fill the required methods from the PDFTableDataSource class interface so they work in combination with the received RowSet.</p>



<h4 class="wp-block-heading">AddNewRow Method</h4>



<p>Add this snippet of code for the &#8220;AddNewRow&#8221; method:</p>



<pre class="wp-block-preformatted"><code>If DrawingFromRowSet And data &lt;&gt; Nil Then

  // We are going to draw as many rows as rows are in the
  // "data" rowset
  Return rowCount &lt;&gt; data.RowCount

End If</code></pre>



<p>As you can see, that fragment of code will only run when both conditions are meet. That is, when the &#8220;DrawingFromRowSet&#8221; is set to True and the &#8220;data&#8221; property is set to a not niled RowSet. If this is the case, we then instruct our PDFTable to set the number of rows to be drawn to the same number of rows in the RowSet.</p>



<h4 class="wp-block-heading">Completed Method</h4>



<p>This is the method that will be called once the drawing of the PDFTable has been completed. We will use it to draw the page numbers at the bottom of every page in the PDFDocument. As you probably already know, it is really easy to change the active graphic context to a given page of the PDF document using the CurrentPage property, so we will use that to iterate every one of our PDF document pages, adding the page number to it as a footer.</p>



<p>This is the snippet of code responsible for doing just that:</p>



<pre class="wp-block-preformatted"><code>// This method is called once the table has been drawn
// so let's "print" the page number on every page
// of the PDF Document

Static pageNumber As String = "Page: "

If document &lt;&gt; Nil Then
  Var g As Graphics = document.Graphics

  For n As Integer = 1 To document.PageCount
    document.CurrentPage = n
    g.DrawText(pageNumber + Str(n), g.Width - g.TextWidth(pageNumber+Str(n))-20, g.Height-g.FontAscent)
  Next

End If</code></pre>



<h4 class="wp-block-heading">HeaderHeight Method</h4>



<p>This is the method called so we can set the PDFTable the desired height for the drawing of the Header. In this case we are going to use a fixed value: 20 points. The code for that method is:</p>



<pre class="wp-block-preformatted"><code>// Fixed header height
Return 20</code></pre>



<h4 class="wp-block-heading">PaintCell Method</h4>



<p>This is the method responsible for drawing every cell of the PDFTable. It receives as parameters the Graphic context for a particular cell (so its origin is at 0,0) and the row and column values corresponding for such cell.</p>



<p>In this case, draw the outline of a rectangle for the cell plus the text itself retrieved from the RowSet based on the received Column value. The text will be draw vertically centered in the cell:</p>



<pre class="wp-block-preformatted"><code>If DrawingFromRowSet And data &lt;&gt; Nil Then
  // Drawing the outer rectangle for the cell
  g.DrawRectangle(0, 0, g.Width, g.Height)

  // retrieving the text to be drawn from the RowSet,
  // using the column parameter for that.
  Var s As String = data.ColumnAt(column)

  // Centering vertically the text on the table cell
  // while the X offset is fixed at 5 points.
  g.DrawText(s, 5, g.Height / 2 + g.FontAscent / 2)

  // Have we drawn all the columns for this row?
  If column = data.ColumnCount - 1 Then

    // if that is the case, then move to the next row
    // in the RowSet!
    data.MoveToNextRow
  End If

End If</code></pre>



<h4 class="wp-block-heading">PaintHeaderContent Method</h4>



<p>This is the method called in order to draw the Header of the table itself. It is a more simple version of the previous method. In this case, the text will be centered both vertically and horizontally on every header cell:</p>



<pre class="wp-block-preformatted"><code>If column &lt;= Self.Headers.LastIndex Then

  Var s As String = headers(column)
  g.DrawingColor = Color.Black
  g.FillRectangle(0, 0, g.Width, g.Height)
  g.DrawingColor = Color.White
  g.DrawText(s, g.Width / 2 - g.TextWidth(headers(column)) / 2, g.Height / 2 + g.FontAscent / 2)

End If</code></pre>



<h4 class="wp-block-heading">RowHeight Method</h4>



<p>As it happen with the HeaderHeight method, this is the method called to set the height for a given row. As we did for the HeaderHeight method we are going to use a fixed value of 20 points, so type the following line of code in the associated Code Editor:</p>



<pre class="wp-block-preformatted"><code>Return 20</code></pre>



<h3 class="wp-block-heading">Testing The PDFRenderer class</h3>



<p>In order to test our PDFRenderer class in combination with a RowSet object, we need to do some additional work. First, select the Window1 window in the project Navigator and add a property using the following values:</p>



<ul class="wp-block-list">
<li><strong>Name:</strong> db</li>



<li><strong style="font-size: revert;">Type:</strong><span style="font-size: revert;"> SQLiteDatabase</span></li>



<li><strong style="font-size: revert;">Scope:</strong><span style="font-size: revert;"> Private</span></li>
</ul>



<p>Next, click the Window1 window in the Navigator so it is displayed in the Layout Editor. Then, drag a DesktopLabel from the Library and drop it on the left/top edge of the layout observing the aligning guides so it leaves the expected margin over the left and top edges of the Window. Use the dragging handlers of the DesktopLabel on the layout to resize it to the maximum width (once again, less the expected margins). Use the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Locking:</strong> Left, Top and Right locked. Bottom, unlocked.</li>



<li><strong>Multiline:</strong> on.</li>



<li><strong>Text:</strong> This example project needs to use the EddiesElectronics.sqlite database file. Click on the button in order to select it!</li>
</ul>



<p>The layout at this point should look like this:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="331" src="https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.17.36-1024x331.png" alt="" class="wp-image-11147" srcset="https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.17.36-1024x331.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.17.36-300x97.png 300w, https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.17.36-768x248.png 768w, https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.17.36.png 1274w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Now, drag a DesktopButton from the Library and drop it below the previous Label so it is horizontally centered, using the following values in the associated Inspector Panel:</p>



<ul class="wp-block-list">
<li><strong>Caption:</strong> Select EddiesElectronics database file</li>
</ul>



<p>The finished layout should look like this:</p>


<div class="wp-block-image is-style-default">
<figure class="aligncenter"><img loading="lazy" decoding="async" width="1024" height="747" src="https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.19.13-1024x747.png" alt="" class="wp-image-11148" srcset="https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.19.13-1024x747.png 1024w, https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.19.13-300x219.png 300w, https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.19.13-768x561.png 768w, https://blog.xojo.com/wp-content/uploads/2023/01/Screenshot-2023-01-10-at-15.19.13.png 1422w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>
</div>


<p>Double click the button to add the &#8220;Pressed&#8221; Event Handler. Then, add the following code in the associated Code Editor:</p>



<pre class="wp-block-preformatted"><code>Try

  // Assigning SQLite object to property
  db = New SQLiteDatabase

  // Setting the database file to the SQLite object
  db.DatabaseFile = FolderItem.ShowOpenFileDialog(".sqlite")

  // Just a simple check to see if this is the expected
  // file based on the name = "EddiesElectronics.sqlite"

  If db.DatabaseFile = Nil Or db.DatabaseFile.Name &lt;&gt; "EddiesElectronics.sqlite" Then Return

  //…and "connecting" to it!
  db.Connect

  // Let's select all the rows from the Customers table
  Var rs As RowSet = db.SelectSQL("SELECT FirstName,LastName,Address FROM Customers")

  // Creating a new PDFDocument Instance
  Var d As New PDFDocument

  // Creating the PDFTable renderer helper object (we pass the PDFDocument object to it in the Constructor)
  Var PDFRender As New PDFRenderer(d)

  // These will be the headers drawn in the Table
  Var headers() As String = Array("Name", "Surname", "Address")

  // And let's instruct the PDFTable renderer helper to draw the table
  // based in the SQLite database rowset we got in the previous step
  PDFRender.DrawTable(rs, headers)

  // …and save the resulting PDF File to the Desktop
  Var f As FolderItem = SpecialFolder.Desktop.Child("TableFromRowSet.pdf")

  If f &lt;&gt; Nil Then
    d.Save(f)
    f.Open
  End If

Catch e As DatabaseException
  System.DebugLog(e.Message)
Catch e As NilObjectException
  System.DebugLog(e.Message)
End Try</code></pre>



<p>As you can see, all this does is create a new SQLiteDatabase object and assign it to the &#8220;db&#8221; property. Then, we set the &#8220;DataBaseFile&#8221; property of that object to the file selected by the user. The code will do a simple check to see if the selected file is the expected &#8220;EddiesElectronics&#8221; database file. If that is the case, then it will connect to the database, getting a RowSet from a simple query that retrieves the &#8220;name&#8221;, &#8220;surname&#8221; and &#8220;address&#8221; columns from the &#8220;Customers&#8221; database table.</p>



<p>After creating the PDFDocument instance, the code creates a new instance from our PDFRenderer class and calls the &#8220;DrawTable&#8221; method on that object passing along both the RowSet and the Headers we want to use for drawing the table.</p>



<p>Lastly, the PDFDocument will be saved to disk and opened in the by default PDF viewer app.</p>



<p>Run the app, select the &#8220;EddiesElectronics&#8221; SQLite database file&nbsp;and the resulting PDF file will be opened after a few seconds. It will display the table generated from a RowSet data source!</p>



<h3 class="wp-block-heading">In Summary</h3>



<p>It is quite possible to draw tables in a PDFDocument when the data to render comes from a RowSet. Nearly everything was done through the use of a helper class. As always, this can be improved in several ways! For example, we are using a fixed height for every row of the table, but in a more realistic scenario may be using variable heights for the table rows based in the height / amount of data to be drawn. That is something that is doable too!</p>



<p><em>Javier Menendez is an engineer at Xojo and has been using Xojo since 1998. He lives in Castellón</em>, <em>Spain and hosts regular Xojo hangouts en español. Ask Javier questions on Twitter at <a href="https://twitter.com/xojoes" target="_blank" rel="noreferrer noopener">@XojoES</a> or on the <a href="https://forum.xojo.com/u/javier_menendez/summary" target="_blank" rel="noreferrer noopener">Xojo Forum</a>.</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>Hosting a Xojo Web Application Behind IIS</title>
		<link>https://blog.xojo.com/2022/10/20/hosting-a-xojo-web-application-behind-iis/</link>
		
		<dc:creator><![CDATA[Wayne Golding]]></dc:creator>
		<pubDate>Thu, 20 Oct 2022 13:00:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[DNS]]></category>
		<category><![CDATA[IIS]]></category>
		<category><![CDATA[Installer]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[webdev]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10897</guid>

					<description><![CDATA[Wayne Golding]]></description>
										<content:encoded><![CDATA[
<p>On July 1<sup>st</sup>, 2022, Microsoft withdrew the Web Platform Installer and plans to remove it and its catalogues from servers on December 31<sup>st</sup>, 2022.&nbsp; You can read more about this at <a href="https://blogs.iis.net/iisteam/web-platform-installer-end-of-support-feed">IIS Team Blog &#8211; Web Platform Installer &#8211; End of support and sunsetting the product/application feed</a>.&nbsp; The following instructions show you how to continue to host Xojo Web Applications behind IIS.</p>



<p>There are four parts to this article: Part 1 prepares the server for reverse proxy, Part 2 installs the Web Application and create a Windows Service for that app, Part 3 configures the Web Site and, finally, Part 4 looks at setting up the DNS record.</p>



<p>These instructions have been tested on Windows 2016, 2019 and 2022 servers. &nbsp;</p>



<h3 class="wp-block-heading">Part 1: Preparing the Server for Reverse Proxy</h3>



<ol class="wp-block-list"><li>Add the Web Server Role to your server.&nbsp; This is done through the Server Manager application.&nbsp; Default selections have been used.</li></ol>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="902" height="644" src="https://blog.xojo.com/wp-content/uploads/2022/10/image.png" alt="" class="wp-image-10898" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/image.png 902w, https://blog.xojo.com/wp-content/uploads/2022/10/image-300x214.png 300w, https://blog.xojo.com/wp-content/uploads/2022/10/image-768x548.png 768w" sizes="auto, (max-width: 902px) 100vw, 902px" /></figure>



<ol class="wp-block-list" start="2"><li>Download the URL Rewrite component from <a href="https://www.iis.net/downloads/microsoft/url-rewrite">https://www.iis.net/downloads/microsoft/url-rewrite</a> and install it.</li><li>Download the Application Request Routing (ARR) component from <a href="https://www.iis.net/downloads/microsoft/application-request-routing">https://www.iis.net/downloads/microsoft/application-request-routing</a> and install it.</li></ol>



<p>Your server is now ready to host Web Applications behind IIS.</p>



<h3 class="wp-block-heading">Part 2: Installing the Web Application and Configuring the Windows Service</h3>



<p>As Xojo built applications are stand-alone, it is simply a matter of copying the application to the server. Typically, the location will be C:\Program Files\&lt;Your Company Name&gt;\&lt;Your Application Name&gt;.</p>



<p>To create the Windows Service, you’ll need to run CMD As Administrator and enter the following commands.&nbsp; I have used Demo Company and Demo Application.</p>



<div class="wp-block-group"><div class="wp-block-group__inner-container is-layout-flow wp-block-group-is-layout-flow">
<pre class="wp-block-preformatted">SC Create Demo binpath= “C:\Program Files\Demo Company\Demo Application\Demo Application.exe –port=8080” Start= auto
SC Description Demo “Demo Web Application”
SC Failure Demo actions=restart/2000/restart/2000/restart/2000 reset=10
SC FailureFlag Demo 1
SC Start Demo</pre>
</div></div>



<pre class="wp-block-preformatted">SC Create creates the service setting the path to the binary (executable file) specifying Port 8080 and configuring the service to start with the server.</pre>



<pre class="wp-block-preformatted">SC Description sets the long description for the service and is optional</pre>



<pre class="wp-block-preformatted">SC Failure configures how the controller will handle service crashes.&nbsp; In this case the service will be restarted after 2seconds for the first, second and subsequent failures.&nbsp; The failure count will be reset after 10 seconds.</pre>



<pre class="wp-block-preformatted">SC FailureFlag configures the service to treat app crashes as service crashes.&nbsp; Without this the controller won’t execute the failure actions set previously</pre>



<pre class="wp-block-preformatted">SC Start simply starts the service.</pre>



<h3 class="wp-block-heading">Part 3: Configuring the Web Site</h3>



<p>First, you’ll need to create the website using Internet Information Server Manager:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="1424" height="752" src="https://blog.xojo.com/wp-content/uploads/2022/10/image-1.png" alt="" class="wp-image-10899" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/image-1.png 1424w, https://blog.xojo.com/wp-content/uploads/2022/10/image-1-300x158.png 300w, https://blog.xojo.com/wp-content/uploads/2022/10/image-1-1024x541.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/10/image-1-768x406.png 768w" sizes="auto, (max-width: 1424px) 100vw, 1424px" /></figure>



<p>Next, you’ll add a reverse proxy rule using the URL Rewrite function:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="1425" height="751" src="https://blog.xojo.com/wp-content/uploads/2022/10/image-2.png" alt="" class="wp-image-10900" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/image-2.png 1425w, https://blog.xojo.com/wp-content/uploads/2022/10/image-2-300x158.png 300w, https://blog.xojo.com/wp-content/uploads/2022/10/image-2-1024x540.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/10/image-2-768x405.png 768w" sizes="auto, (max-width: 1425px) 100vw, 1425px" /></figure>



<p>Select Add Rule:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="1426" height="750" src="https://blog.xojo.com/wp-content/uploads/2022/10/image-3.png" alt="" class="wp-image-10901" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/image-3.png 1426w, https://blog.xojo.com/wp-content/uploads/2022/10/image-3-300x158.png 300w, https://blog.xojo.com/wp-content/uploads/2022/10/image-3-1024x539.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/10/image-3-768x404.png 768w" sizes="auto, (max-width: 1426px) 100vw, 1426px" /></figure>



<p>Select Reverse Proxy:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="902" height="608" src="https://blog.xojo.com/wp-content/uploads/2022/10/image-4.png" alt="" class="wp-image-10902" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/image-4.png 902w, https://blog.xojo.com/wp-content/uploads/2022/10/image-4-300x202.png 300w, https://blog.xojo.com/wp-content/uploads/2022/10/image-4-768x518.png 768w" sizes="auto, (max-width: 902px) 100vw, 902px" /></figure>



<p>And finally configure the rule:</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="850" height="860" src="https://blog.xojo.com/wp-content/uploads/2022/10/image-5.png" alt="" class="wp-image-10903" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/image-5.png 850w, https://blog.xojo.com/wp-content/uploads/2022/10/image-5-297x300.png 297w, https://blog.xojo.com/wp-content/uploads/2022/10/image-5-768x777.png 768w" sizes="auto, (max-width: 850px) 100vw, 850px" /></figure>



<p>127.0.0.1 is the local machine and 8080 is the port configured in the service.</p>



<h3 class="wp-block-heading">Part 4: DNS</h3>



<p>For the client browsers to find the site you need to add a record to your Domain Name Server.</p>



<figure class="wp-block-image size-full is-style-default"><img loading="lazy" decoding="async" width="902" height="856" src="https://blog.xojo.com/wp-content/uploads/2022/10/image-6.png" alt="" class="wp-image-10904" srcset="https://blog.xojo.com/wp-content/uploads/2022/10/image-6.png 902w, https://blog.xojo.com/wp-content/uploads/2022/10/image-6-300x285.png 300w, https://blog.xojo.com/wp-content/uploads/2022/10/image-6-768x729.png 768w" sizes="auto, (max-width: 902px) 100vw, 902px" /></figure>



<p>You can see here I’m adding a CNAME record to the DNS Manager.&nbsp; The fully qualified domain name matches the website name, and the site is hosted on a machine called WebServer.&nbsp; We use a CNAME record which is an alias of the WebServer A record so that if the WebServer ip address was changed all the sites would automatically follow.</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>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What the PDB is this?</title>
		<link>https://blog.xojo.com/2022/07/25/what-the-pdb-is-this/</link>
		
		<dc:creator><![CDATA[William Yu]]></dc:creator>
		<pubDate>Mon, 25 Jul 2022 13:54:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[64-bit]]></category>
		<category><![CDATA[Debugging]]></category>
		<category><![CDATA[Microsoft]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[PDB]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=10547</guid>

					<description><![CDATA[Starting in Xojo 2022r2 you have the option to generate Program Database (PDB) files with your 64-bit Windows builds. If you&#8217;re unfamiliar with what PDB&#8230;]]></description>
										<content:encoded><![CDATA[
<p>Starting in Xojo 2022r2 you have the option to generate <a href="https://en.wikipedia.org/wiki/Program_database">Program Database (PDB)</a> files with your 64-bit Windows builds. If you&#8217;re unfamiliar with what PDB files are, or how they are used, then this post will help explain how PDBs can assist you with your debugging needs.</p>



<p>While our debugger is a powerful tool in helping you track down bugs in your program, there are times when tricky problems arise that go beyond the scope of what our debugger can handle. It&#8217;s times like these that PDBs can potentially come to the rescue.</p>



<p>So what is a PDB file? In short, PDBs are a file format developed by Microsoft for storing debugging information about a program. The most important part is how it maps each function address to its equivalent function name. Let&#8217;s take a simple example to see how this looks when we don&#8217;t have a PDB to help us.</p>



<h3 class="has-large-font-size wp-block-heading">The Offending Code</h3>



<pre class="wp-block-code has-black-color has-text-color"><code>Var mb As New MemoryBlock(8)
mb.Int64Value(0) = 1
mb = mb.Ptr(0)

// At this point the MemoryBlock is pointing to memory location
// 0x1 which should not be accessible.
mb.StringValue(0, 4) = "Test"</code></pre>



<p>In this example, we&#8217;re purposely causing a hard crash here by accessing memory that is not ours to access. Add the offending code somewhere in your program, i.e. in the Opening event or in the Pressed event of a PushButton. If you run this in the debugger you&#8217;ll notice that the app just quits, along with our debugger. Since our debugger has failed us here, let&#8217;s try Microsoft&#8217;s WinDbg and see if we can get any more information from it.</p>



<h3 class="has-large-font-size wp-block-heading">WinDbg</h3>



<p>If you don&#8217;t already have WinDbg installed, you can now download this from the Microsoft Store:<br><a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/debugger-download-tools</a><br>For many Windows developers this is a great (and free) addition to help you track down those annoying crashes. To use this, build the Xojo app with the offending code. Run WinDbg and point it to the executable to launch. Once the process is loaded in WinDbg, hit their Go button to cause the crash.</p>



<p>With the app crashed, you can see the most recent stack trace where some of the last functions that were called before it crashed. This is what the stack trace looks like when no PDB exists.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1766" height="1282" src="https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithoutPDB.png" alt="" class="wp-image-10552" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithoutPDB.png 1766w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithoutPDB-300x218.png 300w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithoutPDB-1024x743.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithoutPDB-768x558.png 768w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithoutPDB-1536x1115.png 1536w" sizes="auto, (max-width: 1766px) 100vw, 1766px" /></figure>



<p>Since the debugger doesn&#8217;t have the information it needs to map the address to a particular function, it&#8217;ll just report this random address which isn&#8217;t very helpful.</p>



<h3 class="has-large-font-size wp-block-heading"><strong>Generate the PDB File</strong></h3>



<p>Now build the app again but this time generate the PDB file. This option can be found in the Advanced build settings in Xojo 2022r2 and later.</p>


<div class="wp-block-image">
<figure class="aligncenter size-full is-resized"><img loading="lazy" decoding="async" src="https://blog.xojo.com/wp-content/uploads/2022/06/AdvancedBuildSettingWithPDB.png" alt="" class="wp-image-10550" width="301" height="336" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/AdvancedBuildSettingWithPDB.png 601w, https://blog.xojo.com/wp-content/uploads/2022/06/AdvancedBuildSettingWithPDB-269x300.png 269w" sizes="auto, (max-width: 301px) 100vw, 301px" /></figure>
</div>


<p>Run the app again under WinDbg. When you cause the app to crash again, WinDbg will look for a PDB file (note: it can be tuned to look in several different places, but by default it will look at the same directory as the executable). This time when the app crashes, you should get a more readable stack trace.</p>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="1920" height="1269" src="https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithPDB.png" alt="" class="wp-image-10551" srcset="https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithPDB.png 1920w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithPDB-300x198.png 300w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithPDB-1024x677.png 1024w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithPDB-768x508.png 768w, https://blog.xojo.com/wp-content/uploads/2022/06/StackTraceWithPDB-1536x1015.png 1536w" sizes="auto, (max-width: 1920px) 100vw, 1920px" /></figure>



<h3 class="has-large-font-size wp-block-heading">PDBs in the Real World</h3>



<p>While the scenario that we just went through isn&#8217;t the most common one in the real world, it should provide you an idea of how a PDB file can help with debugging. In a real world scenario, you as the developer, will likely store PDBs internally, maybe on a server somewhere. Each time you build your app for deployment (i.e. when your app is released to the public) you would keep this PDB somewhere. Whenever your clients/users experience crashes in your app, you can ask them to send over a minidump. The same principle applies to executables and minidumps, just load it up and run it. However, the only difference is that the minidump may need more help in locating the right PDB file.</p>



<p>For more information on this topic please refer to: <a href="https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/symbol-path">https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/symbol-path</a></p>



<p><em>William Yu grew up in Canada learning to program BASIC on a Vic-20. He is Xojo&#8217;s resident Windows and Linux engineer, among his many other skills. Some may say he has joined the dark side here in the USA, but he will always be a Canadian at heart.</em></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>All You Need is Xojo Pro</title>
		<link>https://blog.xojo.com/2021/10/04/all-you-need-is-xojo-pro/</link>
		
		<dc:creator><![CDATA[Alyssa Foley]]></dc:creator>
		<pubDate>Mon, 04 Oct 2021 14:00:00 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[Console]]></category>
		<category><![CDATA[Consulting]]></category>
		<category><![CDATA[Multi-Platform Development]]></category>
		<category><![CDATA[Priority Support]]></category>
		<category><![CDATA[Rapid Application Development]]></category>
		<category><![CDATA[Software Development]]></category>
		<category><![CDATA[Xojo Pro]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=9127</guid>

					<description><![CDATA[Whether you are new to Xojo or looking to upgrade your existing licenses, Xojo Pro is the best way to take advantage of everything Xojo has to offer. Xojo Pro includes support for every platform - desktop, web, mobile and Pi.]]></description>
										<content:encoded><![CDATA[
<p>Whether you are new to Xojo or looking to upgrade your existing licenses, Xojo Pro is the best way to take advantage of everything Xojo has to&nbsp;offer.</p>



<p>Xojo Pro includes support for every platform:</p>



<ul class="wp-block-list">
<li>Desktop &#8211; Cross-compile for Windows, macOS X &amp; Linux.</li>



<li>Web &#8211; Deploy web apps as standalone apps or to Xojo Cloud.</li>



<li>Mobile &#8211; Make apps for iPhone and iPads (iOS) and Android.</li>



<li>Pi &#8211; Make apps for Raspberry Pi and other single-board computers.</li>



<li>Console &#8211; Make apps with no graphical user interface that run from the terminal, command line or as background processes.</li>
</ul>



<p>In addition, Xojo Pro developers enjoy the following&nbsp;benefits:</p>



<ul class="wp-block-list">
<li>Technical Email &amp; Phone Support</li>



<li>Access to Xojo pre-releases</li>



<li>License activation on 3 machines</li>



<li>First access to Consulting Leads</li>
</ul>



<p><strong><a rel="noreferrer noopener" href="https://xojo.com/store/index.php" target="_blank"><span style="text-decoration: underline;">Xojo Pro is $799</span></a> and a new license includes build access to new Xojo releases for 12 months. </strong>Your Xojo license is perpetual, but access to building apps with new Xojo releases is limited. After 12 months you can renew your access to build apps with new releases or continue building apps with the older releases, indefinitely.<strong> </strong>You are never required to renew and can do so anytime to access new features and supported platforms. Your apps built with Xojo are yours forever. </p>



<p><strong>Already have a Xojo license? Upgrading it to Xojo Pro will earn you a discount.</strong> We&#8217;ve made it easy to Upgrade to Xojo Pro, just log in to <a rel="noreferrer noopener" href="https://xojo.com/account/login.php" target="_blank">your account</a>, go to your <a rel="noreferrer noopener" href="https://www.xojo.com/account/licenses/manage.php" target="_blank">licenses page</a> and select the license(s) you wish to upgrade. The more licenses you select, the greater your discount. After you have selected the licenses to upgrade,&nbsp;choose &#8220;Upgrade to Xojo Pro&#8221; to see your personal upgrade discount in the store.</p>



<p>Questions about Xojo Pro or upgrading your existing Xojo licenses to Xojo Pro? Email me anytime at hello@xojo.com.</p>



<p>Think you need more? Look into <a href="https://www.xojo.com/store/proplus.php">Xojo Pro Plus</a>, developed for businesses that depend on Xojo.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tutorial: Deploying Web Apps on Linux</title>
		<link>https://blog.xojo.com/2021/05/28/tutorial-deploying-web-apps-on-linux/</link>
		
		<dc:creator><![CDATA[Javier Menendez]]></dc:creator>
		<pubDate>Fri, 28 May 2021 15:00:00 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[App Hosting]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[Deployment]]></category>
		<category><![CDATA[Hello World]]></category>
		<category><![CDATA[Nginx]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[webdev]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8552</guid>

					<description><![CDATA[This tutorial provides a step-by-step guide to deploying Xojo web apps on a Linux server. You'll find deployment of more complex web apps can follow the same basic principles. If all of this seems too complex, Xojo Cloud is the easy, powerful and secure way to deploy web apps.]]></description>
										<content:encoded><![CDATA[<p>This tutorial provides a step-by-step guide to deploying Xojo web apps on a Linux server. We will use <strong>Ubuntu 20.4</strong> (64-bit) running on a remote server (VPS) in this example, but this tutorial should work on other Linux distros with minimal change, for example CentOS.</p>
<p>First, in order to deploy a web app you&#8217;ll need a way to access the remote server using the Terminal (macOS) or through the Command line, also a way to create and/or modify several files, and to copy files from your local computer to the remote server using (S)FTP.</p>
<blockquote><p><strong>Note:</strong> While we are using the &#8220;root&#8221; user for all the operations to keep the tutorial as short as possible, including files/folders/directories creation/edition and also for launching the web app, you&#8217;ll probably want to create a specific user with the proper privileges/group configuration for this. As we all know, you don&#8217;t usually want to run anything as the root user!</p></blockquote>
<p>Though this tutorial is focused on the <strong>deployment</strong> aspects of a web app, we&#8217;ll first create a very simple web app in Xojo. Feel free to use a web app of your own. At the end of this tutorial, you&#8217;ll find deployment of more complex web apps can follow the same basic principles.</p>
<h2>1. The Web App</h2>
<p>This very simple app will display a message when the button is clicked.  Start the Xojo IDE and choose Web from the Project Selector window:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8553 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/1-ProyectoWeb.png" alt="" width="882" height="538" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/1-ProyectoWeb.png 882w, https://blog.xojo.com/wp-content/uploads/2021/05/1-ProyectoWeb-300x183.png 300w, https://blog.xojo.com/wp-content/uploads/2021/05/1-ProyectoWeb-768x468.png 768w" sizes="auto, (max-width: 882px) 100vw, 882px" /></p>
<p>Click on the <code>WebPage1</code> item displayed in the Navigator to access the webpage Layout Editor.</p>
<p>Next, drag a button from the Library panel and drop it anywhere on the Layout Editor.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8554 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/2-Pagina.png" alt="" width="766" height="583" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/2-Pagina.png 766w, https://blog.xojo.com/wp-content/uploads/2021/05/2-Pagina-300x228.png 300w" sizes="auto, (max-width: 766px) 100vw, 766px" /></p>
<p>With the button still selected, add the <code>Pressed</code> Event Handler and type this line of code in the Code Editor:</p>
<pre>MessageBox "Hola Mundo"</pre>
<p>The classic &#8220;Hello World&#8221; en español, this is everything the web app will do.</p>
<h2>2. Setting the Deployment Options</h2>
<p>Click on the <code>Shared</code> option found under the <code>Build Settings</code> section in the Navigator. Next, enter <code>9000</code> as the port under the <code>Build Settings</code> section in the Inspector Panel.</p>
<blockquote><p><strong>Note:</strong> Adding the port is not required at this time because the port can be assigned when running the app once it is deployed to the server.</p></blockquote>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8567 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/InspectorPanel.png" alt="" width="301" height="710" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/InspectorPanel.png 301w, https://blog.xojo.com/wp-content/uploads/2021/05/InspectorPanel-127x300.png 127w" sizes="auto, (max-width: 301px) 100vw, 301px" /></p>
<h2>3. Compile the Web App</h2>
<p>Make sure to choose the Linux checkbox in <code>Build Settings</code>. Then, select <code>X86 64 bit</code> from the <code>Build</code> popup menu in the Inspector Panel.</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8556 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/4-AjustesCompilacion.jpg" alt="" width="596" height="355" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/4-AjustesCompilacion.jpg 596w, https://blog.xojo.com/wp-content/uploads/2021/05/4-AjustesCompilacion-300x179.jpg 300w" sizes="auto, (max-width: 596px) 100vw, 596px" /></p>
<p>Next, click on the <code>Build</code> button in Xojo&#8217;s IDE toolbar. Once the app is compiled, you&#8217;ll get a Folder/Directory with the following items inside:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8557 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/5-BuiltApp.png" alt="" width="626" height="341" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/5-BuiltApp.png 626w, https://blog.xojo.com/wp-content/uploads/2021/05/5-BuiltApp-300x163.png 300w" sizes="auto, (max-width: 626px) 100vw, 626px" /></p>
<p>This is the folder you will copy to the server. I&#8217;m using the <a href="https://cyberduck.io">Cyberduck</a> app on macOS but you can choose any method you like.</p>
<h2>4. Copying the App Folder to the Server</h2>
<p>Make sure to copy the folder with the compiled app to the <code>/var/XojoApps</code> path on the server (you&#8217;ll need to create that folder/directory first). Once all the files have been copied, make sure to set <code>750</code> as the privileges value for the folder and files (choose the option to apply these recursively to all of them).</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8568 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/SFTP-CopyFiles-1024x462.png" alt="" width="1024" height="462" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/SFTP-CopyFiles-1024x462.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/SFTP-CopyFiles-300x135.png 300w, https://blog.xojo.com/wp-content/uploads/2021/05/SFTP-CopyFiles-768x346.png 768w, https://blog.xojo.com/wp-content/uploads/2021/05/SFTP-CopyFiles.png 1426w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<h2>5. Installing Nginx</h2>
<p>If the server doesn&#8217;t have <a href="http://nginx.com">Nginx</a> already installed, install it now. Nginx is a light web server which provides more performance when compared with Apache (that is, it is able to serve more requests per second, among other improvements).</p>
<p>To install Nginx, access the remote server using SSH:</p>
<pre>&gt; SSH root@xxx.xxx.xxx.xxx</pre>
<p>Once the new session is open, type the following commands to install Nginx:</p>
<pre>$ sudo apt update
$ sudo apt install nginx</pre>
<h2></h2>
<h2>6. (Really) Basic Firewall Configuration</h2>
<p>Let&#8217;s tackle the firewall. It will need to accept incoming connections from Nginx. Nginx registers itself as a <a href="https://en.wikipedia.org/wiki/Uncomplicated_Firewall"><code>ufw</code></a> service during its installation. In order to simplify the deployment example, use the most restrictive option allowing only web traffic from port 80:</p>
<pre>$ sudo ufw allow 'Nginx HTTP'</pre>
<p>Type the following command to verify the changes:</p>
<pre>$ sudo ufw status</pre>
<p>The output should be similar to this (in my case access from SSH and 8080 ports are also enabled).</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-8592" src="https://blog.xojo.com/wp-content/uploads/2021/05/7-ufw-status.png" alt="" width="390" height="143" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/7-ufw-status.png 390w, https://blog.xojo.com/wp-content/uploads/2021/05/7-ufw-status-300x110.png 300w" sizes="auto, (max-width: 390px) 100vw, 390px" /></p>
<blockquote><p><strong>Note:</strong> This tutorial does not discuss web security which in the overwhelming majority of cases should be a paramount issue and not ignored. Securing a server is a very complicated process which is why we take care of the for you with <a href="https://www.xojo.com/cloud">Xojo Cloud</a>.</p></blockquote>
<h2>7. Creating a New Nginx &#8220;block&#8221;</h2>
<p>Once Nginx is installed, Ubuntu automatically starts this process, so the web server should be active already. Test this by typing:</p>
<pre>$ systemctl status nginx</pre>
<p>The output  should be similar to this:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8559 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/8-Nginx-Status.png" alt="" width="841" height="192" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/8-Nginx-Status.png 841w, https://blog.xojo.com/wp-content/uploads/2021/05/8-Nginx-Status-300x68.png 300w, https://blog.xojo.com/wp-content/uploads/2021/05/8-Nginx-Status-768x175.png 768w" sizes="auto, (max-width: 841px) 100vw, 841px" /></p>
<p>Once the server is running, create a new server block. Think about this block like the virtual hosts on Apache. They will encapsulate the configuration details and will allow hosting of more than one domain on the same server.</p>
<p>Nginx loads these configuration files from the <code>/etc/nginx/sites-available</code> path. Create a new file using the <code>nano</code> editor:</p>
<pre>$ sudo nano /etc/nginx/sites-available/XojoDemo</pre>
<p>Next type the following block in the resulting new document:</p>
<pre>server	{
listen 80;
listen [::]:80;
root /var/XojoApps/XojoDemo;
index index.html index.htm index.nginx-debian.html;

server_name xxx.xxx.xxx.xxx;

location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:9000;
}
}</pre>
<p>Replace <code>xxx.xxx.xxx.xxx</code> with your server IP address or the server domain (DNS record, if you have one pointing to it). We are instructing Nginx to redirect the traffic from port 80 to 9000 where our web app will be listening.</p>
<p>Save the file and exit <code>nano</code>. Next, enable the file by creating a link from the file to the <code>sites-enabled</code> directory where Nginx reads the configuration files:</p>
<pre>$ sudo ln -s /etc/nginx/sites-available/XojoDemo /etc/nginx/sites-enabled/</pre>
<p>Finally, check for syntax errors in the Nginx configuration files:</p>
<pre>$ sudo nginx -t</pre>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8560 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/9-Nginx-check.png" alt="" width="486" height="44" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/9-Nginx-check.png 486w, https://blog.xojo.com/wp-content/uploads/2021/05/9-Nginx-check-300x27.png 300w" sizes="auto, (max-width: 486px) 100vw, 486px" /></p>
<p>If everything is Ok, then reload <code>Nginx</code> so it reads the configuration files again and applies the changes:</p>
<pre>$ sudo systemctl restart nginx</pre>
<h2></h2>
<h2>8. Executing the Xojo Web App</h2>
<p>It&#8217;s time to start our Xojo web app and test the access from the web browser of your choice. Change the current path to the one where you copied the web app. In this example:</p>
<pre>$ cd /var/XojoApps/XojoDemo</pre>
<p>Next, start the app by issuing the following command:</p>
<pre>$ ./XojoDemo --port=9000</pre>
<p>Open a new window/tab in the web browser and enter the IP address/web domain pointing to the web server. There is the web app up and running:</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8561 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/10-HolaMundo-1024x592.png" alt="" width="1024" height="592" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/10-HolaMundo-1024x592.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/10-HolaMundo-300x174.png 300w, https://blog.xojo.com/wp-content/uploads/2021/05/10-HolaMundo-768x444.png 768w, https://blog.xojo.com/wp-content/uploads/2021/05/10-HolaMundo.png 1070w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>Congrats! Now for the harsh truth. This way of executing web apps is not ideal. Because it started from the SSH session on the server, if we exit or interrupt the SSH connection, the web app will exit and won&#8217;t be accessible anymore for anyone. This problem also results in a 504 Gateway Time-Out page served by Nginx:</p>
<p><img loading="lazy" decoding="async" class="size-large wp-image-8562 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/11-TimeOut-1024x592.png" alt="" width="1024" height="592" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/11-TimeOut-1024x592.png 1024w, https://blog.xojo.com/wp-content/uploads/2021/05/11-TimeOut-300x174.png 300w, https://blog.xojo.com/wp-content/uploads/2021/05/11-TimeOut-768x444.png 768w, https://blog.xojo.com/wp-content/uploads/2021/05/11-TimeOut.png 1070w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></p>
<p>In order to fix this problem, create a <code>Service</code>.  A service will allow the app to run without any intervention, even if there is a server interruption, for example, if the server is restarted or the app crashes.</p>
<h2>9. Creating a Service</h2>
<p>Type the following in the current SSH session:</p>
<pre>$ sudo nano /lib/systemd/XojoDemoApp.service</pre>
<p>Next, type the following snippet of text in the new, opened document (make sure to save the changes once you exit nano).</p>
<pre>[Service]
Type=simple
Restart=always
RestartSec=3
User=root
ExecStart=/var/XojoApps/XojoDemo/XojoDemo --port=9000
[Install]
WantedBy=multi-user.target</pre>
<p>Now that you have exited nano, and with the new service created, activate it with the following commands:</p>
<pre>$ sudo systemctl enable /lib/systemd/XojoDemoApp.service
$ sudo systemctl start XojoDemoApp.service</pre>
<p>Get the service status by typing the following command:</p>
<pre>$ sudo systemctl status XojoDemoApp.service</pre>
<p>You should get an output similar to this:</p>
<p><img loading="lazy" decoding="async" class="size-full wp-image-8570 aligncenter" src="https://blog.xojo.com/wp-content/uploads/2021/05/ServiceStatus.png" alt="" width="664" height="134" srcset="https://blog.xojo.com/wp-content/uploads/2021/05/ServiceStatus.png 664w, https://blog.xojo.com/wp-content/uploads/2021/05/ServiceStatus-300x61.png 300w" sizes="auto, (max-width: 664px) 100vw, 664px" /></p>
<p>Now, you can be confident that the Xojo web app will be running even if you close the current SSH connection with the remote server <em>and</em> that it will restart even if the remote server is restarted or the app crashes.</p>
<p>If all of this seems more complex than you care to manage, <a href="https://www.xojo.com/cloud">Xojo Cloud</a> is the easy, powerful and secure way to deploy web apps. Xojo does not provide support for configuring your web server for use with Xojo web apps. To read more about deploying Xojo web apps, visit the Xojo Docs <a href="https://documentation.xojo.com/topics/application_deployment/web/deployment_overview.html">Web Deployment Overview</a> and the <a href="https://documentation.xojo.com/topics/application_deployment/web/deployment_details.html">Web Deployment Details</a> pages.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Pump Up Your Xojo Development</title>
		<link>https://blog.xojo.com/2021/05/03/the-xojo-extras-store/</link>
		
		<dc:creator><![CDATA[Dana Brown]]></dc:creator>
		<pubDate>Mon, 03 May 2021 09:12:00 +0000</pubDate>
				<category><![CDATA[Community]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Networking]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[AprendeXojo]]></category>
		<category><![CDATA[Monkeybread Software]]></category>
		<category><![CDATA[Ohanaware]]></category>
		<category><![CDATA[Third Party]]></category>
		<category><![CDATA[xDev Magazine]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7746</guid>

					<description><![CDATA[During this week's May Sale all Xojo licenses and everything in the Xojo Extras Store are discounted 20%! What kind of deals and extras are out there? Let's check them out! There are 5 categories of Xojo Extras: Developer Tools, User Interface, Database, Distribution and Learning.]]></description>
										<content:encoded><![CDATA[
<p>During this week&#8217;s May Sale all Xojo licenses and everything in the Xojo Extras Store are discounted 20%! What kind of deals and extras are out there? Let&#8217;s check them out. There are 5 categories of Xojo Extras: Developer Tools, User Interface, Database, Distribution and Learning.</p>



<h2 class="wp-block-heading"><strong>Developer Tools</strong></h2>



<p><strong>piDog DataView</strong> is a fast and flexible list viewer and includes one year of updates.</p>



<p><strong>Markdown Parser</strong> for Xojo is a class that allows you to implement the ability to parse Markdown source text into HTML + the provided CSS styles, so it can be presented on the fly over an HTML control for its use &#8220;as-is&#8221;, as a starting point for invoices, reports, templates or document conversion. </p>



<p>If you don&#8217;t have anything from Monkeybread Software, then this is a great deal for you! Everything is 20% off from the <strong>Complete Plugin Set</strong>, which includes 54,000+ functions, to <strong>DynaPDF</strong> for creating and editing PDF documents and more.</p>



<p><strong>Mime Parser</strong> is a class for parsing emails.</p>



<p>The <strong>OMP Plugin</strong> allows you to easily parse Microsoft Outlook Structured Storage (.MSG) files cross-platform from Xojo.</p>



<p>Also offered is a <strong>Spell Checker Class</strong> to easily spell check text.</p>



<h2 class="wp-block-heading">User Interface</h2>



<p><strong>ARWaitingView</strong> is a class to prevent the user from navigating the interface while something is downloading or doing a long process. </p>



<p><strong>AXControlGrid</strong> is a complete and powerful Xojo desktop UI component for macOS and Windows that it makes possible to put Canvas-based controls in a Page or a series of Pages of a given size and, optionally, their associated captions.</p>



<p><strong>AXImageCanvas </strong>greatly simplifies the task of displaying a Picture with the ability to correctly display the image maintaining its original aspect ratio, and keeping the full resolution of the picture and reference to the original FolderItem.</p>



<p><strong>AXNumValidatedTF</strong> is a Xojo TextField subclass (32/64 bits) for Windows and macOS allowing the input validation of a defined numeric range, using the system Locale settings for decimal and grouping text formatting.</p>



<p>Antonio Rinaldi offers <strong>Doughnut</strong>, which is an extension for iOSGraphics to draw circular graphs. Additionally, <strong>iOSTableViewExtended</strong> is a subclass that adds useful features including: swipe to reload, table header and footer, customer section header and footer, contextual menus, side index, TextEdit fix and more.</p>



<p><strong>GraffitiSuite</strong> All Access, Desktop and Web are on sale! They are a collection of custom components for Xojo Desktop and Web. </p>



<p>MBS <strong>ChartDirector</strong> lets you create professional charts in Xojo, with 30 chart and gauge types.</p>



<p><strong>RubberViews</strong> from Match Software maintains the place and relative size of every control when a Window or Container Control is resized. They also offer Window Placement and Screen Extensions that are modules that let you manage windows with greater control.</p>



<h2 class="wp-block-heading">Database</h2>



<p><strong>DataViewer Component </strong>is a collection of objects for Xojo that can easily incorporate into your own projects to give SQL Query and DML functionality for SQLite and MySQL databases along with Data Export facilities. Full source code edition also available.</p>



<p>The<strong> MBS SQL Plugin</strong> is an alternative database interface to Xojo that gives access to SQL databases including Oracle, Microsoft SQL Server, DB2, Sybase, Informix, InterBase/Firebird, SQLBase, MySQL, PostgreSQL, ODBC and SQLite. Also available is the <strong>MBS SQLite Extension</strong> is a plug-in for cubeSQL Server, a plug-in for SQLite Manager (sqlabs) and an extension for SQLite that you can use in all SQLite-based database engines, including the SQLiteDatabase class in Xojo.</p>



<p><strong>SQLVue</strong> is the fast and easy way to manage your SQLite databases.</p>



<h2 class="wp-block-heading">Distribution</h2>



<p><strong>App Wrapper </strong>from Ohanaware simplified the process of preparing applications for submission to the Mac App Store and deploying on websites. Get a 30-day or a 1 year single user or team update plan during this limited time offer.</p>



<p><strong>BoxedApp Packer</strong> helps Xojo developers prepare a single executable file that contains all required files a Xojo application needs.</p>



<p>The <strong>GuancheMOS</strong> plug-in is a serial number creation and validation Engine. Also available is <strong>GuancheID</strong>, the easiest way to get a unique ID for macOS and Windows based computers, so you can use it in combination with GuancheMOS or your own software licensing scheme to make sure your software only runs on the computer the license has been generated for.</p>



<p><strong>Quick License Manager</strong> protects your Xojo Windows application with licensing for trials, perpetual or subscription-based licenses.</p>



<h2 class="wp-block-heading"><strong>Learning</strong></h2>



<p><strong>AprendeXojo</strong> has 2 Spanish-language ebooks in the store available for $20 each during the sale:&nbsp;<em>Programación Multiplataforma Xojo</em>&nbsp;and&nbsp;<em>SQLite</em>.</p>



<p><strong>xDev Magazine</strong> is an&nbsp;independent bimonthly publication focused on educating Xojo users through instruction, tutorials and programming. Score a 1 year subscription during the sale for just $40!</p>



<h2 class="wp-block-heading">Shop Now</h2>



<p>The <a href="https://www.xojo.com/store">Xojo Extras store</a> has something for every kind of Xojo developer, whether you are learning something new or looking to save some time implementing something tricky. Take a look now to see what can help make your development life easier! The Xojo May Sale runs until midnight (CT) Friday, May 7th.  </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>Backwards SQLite Backups</title>
		<link>https://blog.xojo.com/2021/03/09/backwards-sqlite-backups/</link>
		
		<dc:creator><![CDATA[Greg O'Lone]]></dc:creator>
		<pubDate>Tue, 09 Mar 2021 16:54:16 +0000</pubDate>
				<category><![CDATA[Cross-Platform]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Backups]]></category>
		<category><![CDATA[SQLite]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=8121</guid>

					<description><![CDATA[If you use SQLite databases in your apps you may or may not be aware of the Backup method which allows you to quickly and asynchronously create a backup of an existing connected database. This is especially great if you have an in-memory database and you want to store that data on disk for later reference. ]]></description>
										<content:encoded><![CDATA[
<p>If you use SQLite databases in your apps you may or may not be aware of the Backup method which allows you to quickly and asynchronously create a backup of an existing connected database. This is especially great if you have an in-memory database and you want to store that data on disk for later reference. I am using the simpler synchronous calls for this example:</p>



<p><code>memoryDB.Backup(fileDB, Nil, -1)&nbsp;</code></p>



<p>Something that&#8217;s often overlooked is that you can use the Backup method to go the other way&#8230; that is, it can be used to load a disk-based database <em>back into memory</em> by simply swapping the parameters:</p>



<pre class="wp-block-preformatted">// Connect to the database file on disk
Var fileDB as New SQLiteDatabase
fileDB.DatabaseFile = SpecialFolder.Resources.Child("template.db")
fileDB.Connect

// Create the database in memory
Var memoryDB as New SQLiteDatabase
memoryDB.Connect

// "Backup" the file database into memory
fileDB.Backup(memoryDB, Nil, -1)

// Close the file database
fileDB.Close</pre>



<p>And voila! You&#8217;ve restored the database back into memory!</p>



<p>For more information about this command, please see <a rel="noreferrer noopener" href="https://documentation.xojo.com/api/databases/sqlitedatabase.html#sqlitedatabase-backup" target="_blank">SQLiteDatabase.Backup on https://documentation.xojo.com</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Setting up puTTY to create a SSH tunnel from Windows to Xojo Cloud</title>
		<link>https://blog.xojo.com/2020/10/29/setting-up-putty-to-create-a-ssh-tunnel-from-windows-to-xojo-cloud/</link>
		
		<dc:creator><![CDATA[Wayne Golding ]]></dc:creator>
		<pubDate>Thu, 29 Oct 2020 10:00:52 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Windows]]></category>
		<category><![CDATA[Xojo Cloud]]></category>
		<category><![CDATA[Cloud]]></category>
		<category><![CDATA[SSH]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7644</guid>

					<description><![CDATA[Here’s the configuration document for getting puTTY to connect to the Xojo Cloud database.  You might want to note that while Windows 10 now includes a SSH client it doesn’t support SSH tunnels very well due to always executing a connection command.]]></description>
										<content:encoded><![CDATA[
<p>There are just a few steps to get puTTY to connect to your Xojo Cloud database.&nbsp; You might want to note that while Windows 10 now includes a SSH client, it doesn’t support SSH tunnels very well due to always executing a connection command.</p>



<p>First, expand the SSH tree in the categories list and select tunnels.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="678" height="662" src="https://blog.xojo.com/wp-content/uploads/2020/10/image.png" alt="" class="wp-image-7645" srcset="https://blog.xojo.com/wp-content/uploads/2020/10/image.png 678w, https://blog.xojo.com/wp-content/uploads/2020/10/image-300x293.png 300w" sizes="auto, (max-width: 678px) 100vw, 678px" /></figure>



<p>Add a new forwarded port, here we are using port 5432 for Postgres, but you could also use 3306 for mySQL.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="678" height="664" src="https://blog.xojo.com/wp-content/uploads/2020/10/image-1.png" alt="" class="wp-image-7646" srcset="https://blog.xojo.com/wp-content/uploads/2020/10/image-1.png 678w, https://blog.xojo.com/wp-content/uploads/2020/10/image-1-300x294.png 300w" sizes="auto, (max-width: 678px) 100vw, 678px" /></figure>



<p>Press the &#8220;Add&#8221; button to save the forward and tick the &#8220;Local ports accept connections from other hosts&#8221; checkbox.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="678" height="664" src="https://blog.xojo.com/wp-content/uploads/2020/10/image-2.png" alt="" class="wp-image-7650" srcset="https://blog.xojo.com/wp-content/uploads/2020/10/image-2.png 678w, https://blog.xojo.com/wp-content/uploads/2020/10/image-2-300x294.png 300w" sizes="auto, (max-width: 678px) 100vw, 678px" /></figure>



<p>Select the SSH tree and tick the “Don’t start a shell or command at all&#8221; checkbox. This is the bit missing from the Windows native SSH client.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="678" height="664" src="https://blog.xojo.com/wp-content/uploads/2020/10/image-3.png" alt="" class="wp-image-7651" srcset="https://blog.xojo.com/wp-content/uploads/2020/10/image-3.png 678w, https://blog.xojo.com/wp-content/uploads/2020/10/image-3-300x294.png 300w" sizes="auto, (max-width: 678px) 100vw, 678px" /></figure>



<p>Select &#8220;Session&#8221; at the very top of the categories list and enter your Xojo Cloud IP address along with a session name and Save so you’ll have this configuration available to you next time.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="678" height="664" src="https://blog.xojo.com/wp-content/uploads/2020/10/image-4.png" alt="" class="wp-image-7652" srcset="https://blog.xojo.com/wp-content/uploads/2020/10/image-4.png 678w, https://blog.xojo.com/wp-content/uploads/2020/10/image-4-300x294.png 300w" sizes="auto, (max-width: 678px) 100vw, 678px" /></figure>



<p>Now you can open the connection where you will be prompted for your SSH Username (dbadmin) &amp; password.&nbsp; If this is successful, you will be left with a terminal window that appears to do nothing – leave it open until you want to disconnect.</p>



<p>Once the tunnel is established you can use localhost as the host address of your Postgres or MySQL database. </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>Easily Switch Databases with Xojo API 2.0</title>
		<link>https://blog.xojo.com/2020/10/15/easily-switch-databases-with-api-2-0/</link>
		
		<dc:creator><![CDATA[Wayne Golding]]></dc:creator>
		<pubDate>Thu, 15 Oct 2020 15:43:47 +0000</pubDate>
				<category><![CDATA[Database]]></category>
		<category><![CDATA[Guest Post]]></category>
		<category><![CDATA[Learning]]></category>
		<category><![CDATA[Tips]]></category>
		<category><![CDATA[Xojo API 2.0]]></category>
		<category><![CDATA[Xojo Programming Language]]></category>
		<guid isPermaLink="false">https://blog.xojo.com/?p=7586</guid>

					<description><![CDATA[Xojo has built in database classes for accessing SQLite, Postgres, MySQL, Microsoft SQL Server, Oracle &#038; ODBC. API 2.0 sets the bind types for you and that means you can switch engines by just changing the Super of your database class and updating the connection settings.]]></description>
										<content:encoded><![CDATA[
<p>Xojo has built in database classes for accessing <a href="https://documentation.xojo.com/api/databases/sqlitedatabase.html">SQLite</a>, <a href="https://documentation.xojo.com/api/databases/postgresqldatabase.html">Postgres</a>, <a href="https://documentation.xojo.com/api/databases/mysqlcommunityserver.html">MySQL</a>, <a href="https://documentation.xojo.com/api/databases/mssqlserverdatabase.html">Microsoft SQL Server</a>, <a href="https://documentation.xojo.com/api/code_execution/or.htmlacleDatabase">Oracle</a> &amp; <a href="https://documentation.xojo.com/api/databases/odbcdatabase.html">ODBC</a>. All these classes are sub classes of the <a href="https://documentation.xojo.com/api/databases/database.html">Database class</a> which means aside from connection details the same code can be used to access any of these engines. Prior to API 2.0 when using prepared statements, it was necessary to use the bind types specific to that engine. API 2.0 sets the bind types for you and that means you can switch engines by just changing the Super of your database class and updating the connection settings.</p>



<p>When I’m working with a project that will use a database the first thing I do is create my own database class. I do this by inserting a class, giving it a name and setting its super to the engine I am going to use, for example MSSQLServerDatabase. Next, I will add a method called <strong>Constructor</strong> and make it private – I only want to be able to create an instance of this class by passing the connection parameters required by the engine. Then, I will add a second constructor that will have the connection parameters for the chosen engine. For MSSQLServerDatabases a Host, DatabaseName and optionally a Username and Password.</p>



<pre class="wp-block-code"><code>Public Sub Constructor(Host As String, DatabaseName As String, Optional Username As String, Optional Password As String)
  Me.Host = Host
  Me.DatabaseName = DatabaseName
  Me.UserName = Username
  Me.Password = Password
  
  Connect()
  EddiesDatabase.VersionControl(me)
End Sub</code></pre>



<p>Username and Password are optional for MSSQLServerDatabases because when they are empty, Network Credentials are used.</p>



<p>Then I will add a Shared Method VersionControl that takes a parameter db.</p>



<pre class="wp-block-code"><code>Public Shared Sub VersionControl(db As Database)
  Const SelectVersion = "SELECT version FROM versioncontrol WHERE id = 1;"
  
  Var VersionRow As RowSet
  
  #Pragma BreakOnExceptions Off
  Try
    VersionRow = db.SelectSQL(SelectVersion)
  Catch DatabaseException
    // This will be because the versioncontrol table doesn't exist
    // So Create &amp; Populate the table
    db.ExecuteSQL("CREATE TABLE versioncontrol (id INTEGER NOT NULL PRIMARY KEY, version INTEGER NOT NULL);")
    db.ExecuteSQL("INSERT INTO versioncontrol (id, version) VALUES (1, 0);")
    // And get the newly inserted row
    VersionRow = db.SelectSQL(SelectVersion)
  End Try
  #Pragma BreakOnExceptions Default
  
  Do
    Select Case VersionRow.Column("version").IntegerValue
    Case 0
      db.BeginTransaction
      db.ExecuteSQL("CREATE TABLE Customers (" _
      + "ID INTEGER NOT NULL, " _
      + "FirstName VARCHAR(30), " _
      + "LastName VARCHAR(30), " _
      + "Address VARCHAR(200), " _
      + "City VARCHAR(30), " _
      + "State VARCHAR(2), " _
      + "Zip VARCHAR(30), " _
      + "Phone VARCHAR(30), " _
      + "Email VARCHAR(100), " _
      + "Photo IMAGE, " _
      + "Taxable INTEGER, " _
      + "PRIMARY KEY(ID)" _
      + ");")
      db.ExecuteSQL("CREATE TABLE InvoiceItems (" _
      + "ID INTEGER NOT NULL, " _
      + "InvoiceNo INTEGER, " _
      + "ProductCode VARCHAR(10), " _
      + "Quantity INTEGER, " _
      + "PRIMARY KEY(ID)" _
      + ");")
      db.ExecuteSQL("CREATE TABLE Invoices (" _
      + "InvoiceNo INTEGER NOT NULL, " _
      + "CustomerID INTEGER, " _
      + "InvoiceDate DATE, " _
      + "InvoiceAmount FLOAT, " _
      + "PRIMARY KEY(InvoiceNo)" _
      + ");")
      db.ExecuteSQL("CREATE TABLE Products (" _
      + "Code VARCHAR(10) NOT NULL, " _
      + "Name VARCHAR(30), " _
      + "Price FLOAT, " _
      + "PRIMARY KEY(Code)" _
      + ");")
      db.CommitTransaction
    Case 1
      // Insert Schema Updates &amp; SQL Commands before this line and add a New Case statement below this line
      Exit Do
    Case Else
      Var err As New RuntimeException
      err.Message = "Please upgrade your application to use this database"
      Raise err
      Quit()
    End Select
    db.ExecuteSQL("UPDATE versioncontrol SET version = version + 1 WHERE id = 1;")
    VersionRow = db.SelectSQL(SelectVersion)
  Loop
End Sub</code></pre>



<p>This code creates Eddie’s Electronics tables in the Database and maintains the database schema or structure. This method is shared so it can be called from other objects.</p>



<p>Let us say, for example, I want to add the ability to use SQLite as the database engine. I would create the class the same way but name it EddiesSQLiteDatabase, setting its super to SQLiteDatabase, add the empty constructor making it private and add the second constructor passing the folder item for the database file and optionally the encryption key. This code will either connect to the existing database file or create a new file.</p>



<pre class="wp-block-code"><code>Public Sub Constructor(DatabaseFile As FolderItem, Optional EncryptionKey As String)
  // Calling the overridden superclass constructor.
  Super.Constructor()
  
  Me.DatabaseFile = DatabaseFile
  
  If DatabaseFile.Exists Then
    If EncryptionKey > "" Then
      Me.EncryptionKey = EncryptionKey
    End If
    Connect()
  Else
    CreateDatabase()
    If EncryptionKey > "" Then
      Encrypt(EncryptionKey)
    End If
  End If
  
  EddiesDatabase.VersionControl(me)
  
End Sub</code></pre>



<p>You will notice I am calling the shared method EddiesDatabase.VersionControl on the EddiesDatabase class for this engine too.</p>



<p>The big issue with doing this in the classic framework was the use of prepared statements. I would need to update every bind type for every prepared statement in the code to allow for both engines. Of course while the Xojo code remains 100% compatible, I still need to test to ensure all the SQL statements work with the new engine and make adjustments where necessary, but that is an awful lot less work.</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>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>
	</channel>
</rss>
