<?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>SQLcl Archives - Philipp Salvisberg&#039;s Blog</title>
	<atom:link href="https://www.salvis.com/blog/tag/sqlcl/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.salvis.com/blog/tag/sqlcl/</link>
	<description>Database-centric development</description>
	<lastBuildDate>Sun, 26 Nov 2023 17:57:40 +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>

<image>
	<url>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</url>
	<title>SQLcl Archives - Philipp Salvisberg&#039;s Blog</title>
	<link>https://www.salvis.com/blog/tag/sqlcl/</link>
	<width>32</width>
	<height>32</height>
</image> 
<atom:link rel="hub" href="https://pubsubhubbub.appspot.com"/>
<atom:link rel="hub" href="https://pubsubhubbub.superfeedr.com"/>
<atom:link rel="hub" href="https://websubhub.com/hub"/>
<atom:link rel="self" href="https://www.salvis.com/blog/tag/sqlcl/feed/"/>
	<item>
		<title>Installing MLE Modules in the Oracle Database</title>
		<link>https://www.salvis.com/blog/2023/11/26/installing-mle-modules-in-the-oracle-database/</link>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 26 Nov 2023 17:56:09 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[MLE]]></category>
		<category><![CDATA[Oracle 26ai]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQLcl]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=12931</guid>

					<description><![CDATA[<p>Introduction In my previous blog post, I&#8217;ve shown how you can deploy an npm module from a URL and a custom ESM module from a local file into a remote Oracle Database 23c using JavaScript and SQLcl. This works well. However, for two MLE modules, I had to write 22 lines of<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2023/11/26/installing-mle-modules-in-the-oracle-database/">Installing MLE Modules in the Oracle Database</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>In my <a href="https://www.salvis.com/blog/2023/11/12/mle-typescript-javascript-modules/#deployment">previous blog post</a>, I&#8217;ve shown how you can deploy an npm module from a URL and a custom ESM module from a local file into a remote Oracle Database 23c using JavaScript and SQLcl. This works well. However, for two MLE modules, I had to write 22 lines of code with duplications. I do not like that. I have therefore developed a small SQLcl custom command that greatly simplifies the installation of MLE modules in the Oracle Database.</p>



<h2 class="wp-block-heading">Installing the <code>mle</code> Custom Command</h2>



<p>Start SQLcl and run the following command to install the custom command <code>mle</code> in the current session.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="script https://raw.githubusercontent.com/PhilippSalvisberg/mle-sqlcl/main/mle.js register" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">script https://raw.githubusercontent.com/PhilippSalvisberg/mle-sqlcl/main/mle.js register</span></span></code></pre></div>



<p>The SQLcl script command can read a JavaScript file from the local file system or from a URL. If you feel uncomfortable running JavaScript files directly from a URL, you can have a look at the <a href="https://github.com/PhilippSalvisberg/mle-sqlcl">GitHub repo</a> first and download and run a chosen version of the script from the local file system.</p>



<p>The <code>register</code> subcommand registers the <code>mle</code> script as an SQLcl command. However, this registration is not permanent. It will be lost after closing SQLcl. To make the custom command available in every new SQLcl session add the command above to your <code>login.sql</code> or <code>startup.sql</code>. SQLcl executes these files on start-up or after establishing a new connection. Just make sure that you have configured the <code>SQLPATH</code> environment variable accordingly. </p>



<h2 class="wp-block-heading">Providing Help</h2>



<p>Now you can run the <code>mle</code> command like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="mle" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">mle</span></span></code></pre></div>



<p>Without parameters, an error message is displayed along with information on how to use this command.</p>



<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-2.png"><img fetchpriority="high" decoding="async" width="650" height="498" src="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-2.png" alt="Output of mle command without parameters" class="wp-image-12934" srcset="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-2.png 650w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-2-300x230.png 300w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-2-98x75.png 98w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-2-480x368.png 480w" sizes="(max-width:767px) 480px, 650px" /></a></figure>



<h2 class="wp-block-heading">Installing Validator</h2>



<p>Now we know the syntax to install an MLE module from a URL. However, what&#8217;s the URL for an npm module? We use the free OpenSource CDN <a href="https://www.jsdelivr.com/?docs=esm">jsDelivr</a> for that. They provide a service returning an npm module as an ECMAScript module. The result can be used in a browser and also in an Oracle Database. The URL looks like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="https://esm.run/npm-package-name@npm-package-version" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">https://esm.run/npm-package-name@npm-package-version</span></span></code></pre></div>



<p>We want to install the current version 13.11.0 of the npm module <a href="https://www.npmjs.com/package/validator">validator</a>. Based on the information provided above our SQLcl command for that looks like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="mle install validator_mod https://esm.run/validator@13.11.0 13.11.0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">mle install validator_mod https://esm.run/validator@13.</span><span style="color: #B5CEA8">11</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">13</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">11</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">0</span></span></code></pre></div>



<p>And here is the result in SQLcl :</p>



<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-9.png"><img decoding="async" width="642" height="194" src="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-9.png" alt="Output of successfully executed mle command to install the validator module from npm" class="wp-image-12945" srcset="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-9.png 642w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-9-300x91.png 300w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-9-150x45.png 150w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-9-480x145.png 480w" sizes="(max-width:767px) 480px, 642px" /></a></figure>



<p>Please note that the response message by SQLcl 23.3 is not 100% correct for MLE modules. However, our module is installed correctly. We verify that later.</p>



<p>Maybe you&#8217;d like to know what the SQL statement looks like to install this module. The last statement is still in SQLcl&#8217;s buffer. Therefore we can type <code>l</code> followed by <code>enter</code> to see the content of the buffer.</p>


<div class="accordion"><div class="mfn-acc accordion_wrapper  toggle"><br />
<div class="question"><div class="title"><i class="icon-plus acc-icon-plus" aria-hidden="true"></i><i class="icon-minus acc-icon-minus" aria-hidden="true"></i>SQLcl's buffer</div><div class="answer"></p>



<p>The first line contains the start of the SQL statement. Lines 2 to 7 are comments generated by jsDelivr. Line 8 contains the complete module. Yes, as a single line. The code is minified. All unnecessary whitespace is gone and internally used identifiers are shortened to save space. On line 9 we would see a JavaScript comment with a pointer to a map file that points to the original, nicely formatted source code. This is interesting when debugging in other environments. It&#8217;s currently not used in the database.</p>



<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-7.png"><img decoding="async" width="1050" height="17704" src="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-7.png" alt="SQLcl buffer containing the SQL command to install the validator module" class="wp-image-12937"/></a></figure>


<p></div></div>
<br />
</div></div>




<h2 class="wp-block-heading">Querying MLE Modules</h2>



<p>The following SQL statement shows some data regarding the previously deployed MLE module:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="set sqlformat ansiconsole
select module_name, version, language_name, length(module)
  from user_mle_modules;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">set</span><span style="color: #D4D4D4"> sqlformat ansiconsole</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> module_name, </span><span style="color: #569CD6">version</span><span style="color: #D4D4D4">, language_name, </span><span style="color: #569CD6">length</span><span style="color: #D4D4D4">(module)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> user_mle_modules;</span></span></code></pre></div>



<p>The result in SQLcl looks like this:</p>



<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-8.png"><img loading="lazy" decoding="async" width="642" height="171" src="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-8.png" alt="" class="wp-image-12944" srcset="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-8.png 642w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-8-300x80.png 300w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-8-150x40.png 150w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-8-480x128.png 480w" sizes="auto, (max-width:767px) 480px, 642px" /></a></figure>



<p>We see the version of the module and also the size in bytes of the blob column where the module is stored. It is one byte larger than the result of the URL since It contains a final line feed character due to the way we built the SQL statement.</p>



<p>IMO it is helpful to provide the version of the external ESM as long as there is no proper package registry within the Oracle Database.</p>



<h2 class="wp-block-heading">Verifying Installation</h2>



<p>Let&#8217;s write a call specification in order to verify the successful installation of the validator module.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="create or replace function is_email(
   in_email in varchar2
) return boolean as mle module validator_mod signature 'default.isEmail(string)';
/" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">create or replace</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">is_email</span><span style="color: #D4D4D4">(</span></span>
<span class="line"><span style="color: #D4D4D4">   in_email </span><span style="color: #569CD6">in</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">varchar2</span></span>
<span class="line"><span style="color: #D4D4D4">) </span><span style="color: #569CD6">return</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">boolean</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> mle module validator_mod </span><span style="color: #569CD6">signature</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;default.isEmail(string)&#39;</span><span style="color: #D4D4D4">;</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<p>Now we can run the following query to verify e-mail addresses and the installation of the validator module:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="select is_email('jane.doe@example.org') as jane_doe,
       is_email('john.doe@example') as john_doe;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> is_email(</span><span style="color: #CE9178">&#39;jane.doe@example.org&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> jane_doe,</span></span>
<span class="line"><span style="color: #D4D4D4">       is_email(</span><span style="color: #CE9178">&#39;john.doe@example&#39;</span><span style="color: #D4D4D4">) </span><span style="color: #569CD6">as</span><span style="color: #D4D4D4"> john_doe;</span></span></code></pre></div>



<p>In SQLcl 23.3 the result looks like this (boolean values as <code>1</code> and <code>0</code>):</p>



<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-10.png"><img loading="lazy" decoding="async" width="642" height="189" src="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-10.png" alt="Result of calling the is_email validator function in SQLcl" class="wp-image-12949" srcset="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-10.png 642w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-10-300x88.png 300w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-10-150x44.png 150w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-10-480x141.png 480w" sizes="auto, (max-width:767px) 480px, 642px" /></a></figure>



<p>And in SQL*Plus 23.3 the result looks like this (boolean values as <code>TRUE</code> and <code>FALSE</code>):</p>



<figure class="wp-block-image size-full"><a href="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-12.png"><img loading="lazy" decoding="async" width="642" height="193" src="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-12.png" alt="Result of calling the is_email validator function in SQL*Plus" class="wp-image-12952" srcset="https://www.salvis.com/blog/wp-content/uploads/2023/11/image-12.png 642w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-12-300x90.png 300w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-12-150x45.png 150w, https://www.salvis.com/blog/wp-content/uploads/2023/11/image-12-480x144.png 480w" sizes="auto, (max-width:767px) 480px, 642px" /></a></figure>



<h2 class="wp-block-heading">Installing More Modules</h2>



<p>Let&#8217;s install some other modules I find useful. You find them on <a href="https://www.npmjs.com/">npm</a> if you want to know what they do.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E"><svg xmlns="http://www.w3.org/2000/svg" width="54" height="14" viewBox="0 0 54 14"><g fill="none" fill-rule="evenodd" transform="translate(1 1)"><circle cx="6" cy="6" r="6" fill="#FF5F56" stroke="#E0443E" stroke-width=".5"></circle><circle cx="26" cy="6" r="6" fill="#FFBD2E" stroke="#DEA123" stroke-width=".5"></circle><circle cx="46" cy="6" r="6" fill="#27C93F" stroke="#1AAB29" stroke-width=".5"></circle></g></svg></span><span role="button" tabindex="0" data-code="mle install sentiment_mod https://esm.run/sentiment@5.0.2 5.0.22
mle install jimp_mod https://esm.run/jimp@0.22.10/browser/lib/jimp.js 0.22.10
mle install sql_assert_mod https://esm.run/sql-assert@1.0.3 1.0.3
mle install lodash_mod https://esm.run/lodash@4.17.21 4.17.21
mle install js_yaml_mod https://esm.run/js-yaml@4.1.0 4.1.0
mle install minimist_mod https://esm.run/minimist@1.2.8 1.2.8
mle install typeorm_mod https://esm.run/typeorm@0.3.17 0.3.17" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">mle install sentiment_mod https://esm.run/sentiment@5.</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">5</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">22</span></span>
<span class="line"><span style="color: #D4D4D4">mle install jimp_mod https://esm.run/jimp@0.</span><span style="color: #B5CEA8">22</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">10</span><span style="color: #D4D4D4">/browser/lib/jimp.js </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">22</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">10</span></span>
<span class="line"><span style="color: #D4D4D4">mle install sql_assert_mod https://esm.run/</span><span style="color: #569CD6">sql</span><span style="color: #D4D4D4">-assert@1.</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">3</span></span>
<span class="line"><span style="color: #D4D4D4">mle install lodash_mod https://esm.run/lodash@4.</span><span style="color: #B5CEA8">17</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">21</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">17</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">21</span></span>
<span class="line"><span style="color: #D4D4D4">mle install js_yaml_mod https://esm.run/js-yaml@4.</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">4</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">0</span></span>
<span class="line"><span style="color: #D4D4D4">mle install minimist_mod https://esm.run/minimist@1.</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">8</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">1</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">2</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">8</span></span>
<span class="line"><span style="color: #D4D4D4">mle install typeorm_mod https://esm.run/typeorm@0.</span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">17</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">0</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">3</span><span style="color: #D4D4D4">.</span><span style="color: #B5CEA8">17</span></span></code></pre></div>



<p>Installing all modules is just a matter of a few seconds. </p>



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



<p>Using the SQLcl custom <code>mle</code> command to install ECMAScript modules from a file or from a URL is not only easy and fast, but it is also an excellent way to provide tested functionality within the database. </p>



<p>Technically it should be possible to generate the PL/SQL call specifications based on the information that is provided for IDEs to better support code completion (type definitions). I hope that Oracle will provide such a feature in one of the coming releases of SQLcl or as part of a dedicated MLE tool (similar to <code>dbjs</code> which was part of the experimental version of the MLE back in 2017). Even if I do not want to provide access to all underlying functionality of an MLE module within the database or provide the functionality with the same signature, a PL/SQL package with all call specifications would simplify the work for a wrapper PL/SQL package that exposes just the relevant subset in a suitable way for the use in PL/SQL or SQL.</p>
<p>The post <a href="https://www.salvis.com/blog/2023/11/26/installing-mle-modules-in-the-oracle-database/">Installing MLE Modules in the Oracle Database</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Patching SQL Developer 20.2 with SQLcl&#8217;s Formatter</title>
		<link>https://www.salvis.com/blog/2020/11/01/patching-sql-developer-20-2-with-sqlcls-formatter/</link>
					<comments>https://www.salvis.com/blog/2020/11/01/patching-sql-developer-20-2-with-sqlcls-formatter/#comments</comments>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Sun, 01 Nov 2020 15:37:09 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Arbori]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Developer]]></category>
		<category><![CDATA[SQLcl]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=10802</guid>

					<description><![CDATA[<p>Introduction SQLcl 20.3.0 was released on October 29, 2020. It&#8217;s the first time I remember that we have a SQLcl version without the corresponding SQL Developer version. This is a pity because this SQLcl version also contains formatter fixes. And formatting code is something I do more often in the full-blown IDE<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2020/11/01/patching-sql-developer-20-2-with-sqlcls-formatter/">Patching SQL Developer 20.2 with SQLcl&#8217;s Formatter</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>SQLcl 20.3.0 was released on October 29, 2020. It&#8217;s the first time I remember that we have a SQLcl version without the corresponding SQL Developer version. This is a pity because this SQLcl version also contains formatter fixes. And formatting code is something I do more often in the full-blown IDE than in the stripped-down command line interface. In this blog post, I show you how you can patch your SQL Developer installation and make the formatter fixes available there as well.</p>



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



<p>What I do here is an experiment and most probably not really legal. It&#8217;s nothing I suggest you should do in your production environment. If you feel uneasy, don&#8217;t do it. What you do might destroy your SQL Developer installation.</p>



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



<p>For this experiment you need</p>



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



<li>SQL Developer 20.2.0</li>



<li>JDK8 or JDK11</li>
</ul>



<p>These software components are all installed on your computer. I do not explain in this blog post how to do it.</p>



<h2 class="wp-block-heading">Solution Approach</h2>



<p>SQLcl and SQL Developer provide a <code>dbtools-common.jar</code> file. This file contains the formatter (besides other things). We copy this file from the SQLcl installation to the SQL Developer installation.</p>



<p>That would be all if SQL Developer would load the Guava library before opening a connection. But it does not because it was not required for version 20.2 of <code>dbtools-common.jar</code>. Therefore we put the <code>VersionTracker.class</code> and the <code>SetServerOutput.class</code> (which do not use Guava) from the original SQL Developer installation into the <code>dbtools-common.jar</code> file.</p>



<p>Another option would be to embed the classes from the&nbsp;<code>guava.jar</code>.</p>



<h2 class="wp-block-heading">Step by Step Instruction</h2>



<h3 class="wp-block-heading">Step 1 &#8211; Quit SQL Developer</h3>



<p>We are going to patch SQL Developer. This is not possible on Windows if SQL Developer is running. On other OS this might have strange effects. Therefore quit SQL Developer.</p>



<h3 class="wp-block-heading">Step 2 &#8211; Rename SQLDev&#8217;s <code>dbtools-common.jar</code></h3>



<p>Find the <code>dbtools-common.jar</code> in your SQL Developer installation. In my case the file is in this directory: <code>/Applications/SQLDeveloper20.2.0.app/Contents/Resources/sqldeveloper/sqldeveloper/lib</code>. Rename this file to <code>dbtools-common.original.jar</code>.</p>


<div class="jq-tabs tabs_wrapper tabs_horizontal"><ul><li><a href="#tab-6a00b77a1ba69-1">macOS</a></li><li><a href="#tab-6a00b77a1ba69-2">Windows</a></li></ul><div id="tab-6a00b77a1ba69-1" ></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Rename SQLDev&#8217;s dbtools-common.jar</span><span role="button" tabindex="0" data-code="cd /Applications/SQLDeveloper20.2.0.app/Contents/Resources/sqldeveloper/sqldeveloper/lib
mv dbtools-common.jar dbtools-common.original.jar" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">cd</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/Applications/SQLDeveloper20.2.0.app/Contents/Resources/sqldeveloper/sqldeveloper/lib</span></span>
<span class="line"><span style="color: #DCDCAA">mv</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">dbtools-common.jar</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">dbtools-common.original.jar</span></span></code></pre></div>


<p></div><div id="tab-6a00b77a1ba69-2" ></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Rename SQLDev&#8217;s dbtools-common.jar</span><span role="button" tabindex="0" data-code="cd C:\app\sqldeveloper20.2.0\sqldeveloper\lib
ren dbtools-common.jar dbtools-common.original.jar" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">cd C:\app\sqldeveloper20.</span><span style="color: #B5CEA8">2.0</span><span style="color: #D4D4D4">\sqldeveloper\lib</span></span>
<span class="line"><span style="color: #D4D4D4">ren dbtools-common.jar dbtools-common.original.jar</span></span></code></pre></div>


<p></div></div>



<h3 class="wp-block-heading">Step 3 &#8211; Copy SQLcl&#8217;s <code>dbtools-common.jar</code></h3>



<p>Find the <code>dbtools-common.jar</code> in your SQLcl installation. In my case, the file is in this directory: <code>/usr/local/bin/sqlcl/lib</code>. Copy the file to the SQLDev&#8217;s directory (where the <code>dbtools-common.original.jar</code> is located).</p>


<div class="jq-tabs tabs_wrapper tabs_horizontal"><ul><li><a href="#tab-6a00b77a1bbc6-1">macOS</a></li><li><a href="#tab-6a00b77a1bbc6-2">Windows</a></li></ul><div id="tab-6a00b77a1bbc6-1" ></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Copy SQLcl’s dbtools-common.jar</span><span role="button" tabindex="0" data-code="cd /usr/local/bin/sqlcl/lib
cp dbtools-common.jar /Applications/SQLDeveloper20.2.0.app/Contents/Resources/sqldeveloper/sqldeveloper/lib" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">cd</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/usr/local/bin/sqlcl/lib</span></span>
<span class="line"><span style="color: #DCDCAA">cp</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">dbtools-common.jar</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/Applications/SQLDeveloper20.2.0.app/Contents/Resources/sqldeveloper/sqldeveloper/lib</span></span></code></pre></div>


<p></div><div id="tab-6a00b77a1bbc6-2" ></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Copy SQLcl’s dbtools-common.jar</span><span role="button" tabindex="0" data-code="cd C:\app\sqlcl\lib
copy dbtools-common.jar C:\app\sqldeveloper20.2.0\sqldeveloper\lib" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">cd C:\app\sqlcl\lib</span></span>
<span class="line"><span style="color: #D4D4D4">copy dbtools-common.jar C:\app\sqldeveloper20.</span><span style="color: #B5CEA8">2.0</span><span style="color: #D4D4D4">\sqldeveloper\lib</span></span></code></pre></div>


<p></div></div>



<p></p>



<h3 class="wp-block-heading">Step 4 &#8211; Patch <code>dbtools-common.jar</code></h3>



<p>Open a terminal window and change to the directory of the <code>dbtools-common.original.jar</code> file. Run there the following commands to create a patched version of <code>dbtools-common.jar</code>:</p>


<div class="jq-tabs tabs_wrapper tabs_horizontal"><ul><li><a href="#tab-6a00b77a1bd2c-1">macOS</a></li><li><a href="#tab-6a00b77a1bd2c-2">Windows</a></li></ul><div id="tab-6a00b77a1bd2c-1" ></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Patch dbtools-common.jar</span><span role="button" tabindex="0" data-code="cd /Applications/SQLDeveloper20.2.0.app/Contents/Resources/sqldeveloper/sqldeveloper/lib
jar -xvf dbtools-common.original.jar oracle/dbtools/db/VersionTracker.class
jar -xvf dbtools-common.original.jar oracle/dbtools/raptor/newscriptrunner/commands/SetServerOutput.class
jar -u0vMf dbtools-common.jar oracle/dbtools
rm -rf oracle" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #DCDCAA">cd</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">/Applications/SQLDeveloper20.2.0.app/Contents/Resources/sqldeveloper/sqldeveloper/lib</span></span>
<span class="line"><span style="color: #DCDCAA">jar</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-xvf</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">dbtools-common.original.jar</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">oracle/dbtools/db/VersionTracker.class</span></span>
<span class="line"><span style="color: #DCDCAA">jar</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-xvf</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">dbtools-common.original.jar</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">oracle/dbtools/raptor/newscriptrunner/commands/SetServerOutput.class</span></span>
<span class="line"><span style="color: #DCDCAA">jar</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-u0vMf</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">dbtools-common.jar</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">oracle/dbtools</span></span>
<span class="line"><span style="color: #DCDCAA">rm</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-rf</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">oracle</span></span></code></pre></div>


<p></div><div id="tab-6a00b77a1bd2c-2" ></p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">Patch dbtools-common.jar</span><span role="button" tabindex="0" data-code="cd C:\app\sqldeveloper20.2.0\sqldeveloper\lib
jar -xvf dbtools-common.original.jar oracle/dbtools/db/VersionTracker.class
jar -xvf dbtools-common.original.jar oracle/dbtools/raptor/newscriptrunner/commands/SetServerOutput.class
jar -u0vMf dbtools-common.jar oracle/dbtools
rmdir /s /q oracle" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #D4D4D4">cd C:\app\sqldeveloper20.</span><span style="color: #B5CEA8">2.0</span><span style="color: #D4D4D4">\sqldeveloper\lib</span></span>
<span class="line"><span style="color: #D4D4D4">jar -xvf dbtools-common.original.jar oracle/dbtools/db/VersionTracker.class</span></span>
<span class="line"><span style="color: #D4D4D4">jar -xvf dbtools-common.original.jar oracle/dbtools/raptor/newscriptrunner/commands/SetServerOutput.class</span></span>
<span class="line"><span style="color: #D4D4D4">jar -u0vMf dbtools-common.jar oracle/dbtools</span></span>
<span class="line"><span style="color: #D4D4D4">rmdir /s /q oracle</span></span></code></pre></div>


<p></div></div>



<p>Here is some explanation:</p>



<ul class="wp-block-list">
<li>First, we change to the directory where the files dbtools-common.original.jar (version 20.2.0) and dbtools-common.jar (version 20.3.0)  are stored. In your case, the directory name may differ.</li>



<li>On the second and third line, we extract the <code>VersionTracker.class</code> and the <code>SetServerOutput.class</code> from the <code>dbtools-common.original.jar</code> file. The classes are stored in a newly created directory <code>oracle</code>.</li>



<li>On the fourth line, we copy the previously extracted classes into the <code>dbtools-common.jar</code> file.</li>



<li>And on the last line, we remove the <code>oracle</code> directory and its subdirectories.</li>
</ul>



<h3 class="wp-block-heading">Formatter Improvements</h3>



<p>An example is the best to show the difference between version 20.2 and 20.3. I use the default formatter settings with just one change. &#8220;No breaks&#8221; for &#8220;Line Breaks On Boolean connectors&#8221;.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs.png"><img loading="lazy" decoding="async" width="349" height="567" src="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs.png" alt="" class="wp-image-10821" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs.png 349w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs-185x300.png 185w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs-90x146.png 90w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs-31x50.png 31w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs-46x75.png 46w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev_formatter_prefs-1x2.png 1w" sizes="auto, (max-width:767px) 349px, 349px" /></a></figure>



<p>And here are the results after formatting the code once.</p>


<div class="jq-tabs tabs_wrapper tabs_horizontal"><ul><li><a href="#tab-6a00b77a1be1b-1">SQLDev 20.2 (patched)</a></li><li><a href="#tab-6a00b77a1be1b-2">SQLDev 20.2 (original)</a></li></ul><div id="tab-6a00b77a1be1b-1" ></p>
<p><a href="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-10822" src="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched.png" alt="" width="801" height="200" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched.png 801w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched-300x75.png 300w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched-768x192.png 768w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched-260x65.png 260w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched-50x12.png 50w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-patched-150x37.png 150w" sizes="auto, (max-width:767px) 480px, (max-width:801px) 100vw, 801px" /></a></p>
<p></div><div id="tab-6a00b77a1be1b-2" ></p>
<p><a href="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-10824" src="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original.png" alt="" width="801" height="202" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original.png 801w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original-300x76.png 300w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original-768x194.png 768w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original-260x66.png 260w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original-50x13.png 50w, https://www.salvis.com/blog/wp-content/uploads/2020/11/sqldev-20.2-original-150x38.png 150w" sizes="auto, (max-width:767px) 480px, (max-width:801px) 100vw, 801px" /></a></p>
<p></div></div>



<p>There are two significant improvements to the formatter. Both are related to comment and whitespace handling and therefore are independent of an Arbori program.</p>



<ul class="wp-block-list">
<li>The line of code after a comment is no longer indented additionally.</li>



<li>The line break after a single-line comment is no longer lost. As a result, the formatter will no longer comment out code.</li>
</ul>



<p>While the first bug leads to badly formatted code, the second bug is really nasty. It breaks your code. This happens when you use single-line comments on consecutive lines. In most cases, this will lead to compile errors. However, I showed that the resulting code may be syntactically correct and a wrong formatting result could go unnoticed.</p>



<p><em>Updated on 2020-11-03, fixed typo in jar file names (<code>db-common...</code> to <code>dbtools-common...</code>).</em></p>



<p><em>Updated on 2020-11-05, added <code>SetServerOutput.class</code> to the patched jar file. Otherwise, no SQL can be processed in a worksheet. Mentioned an alternative option to embed the classes from the <code>guava.jar</code>. Renamed chapter &#8220;Overview&#8221; to &#8220;Solution Approach&#8221;.</em></p>
<p>The post <a href="https://www.salvis.com/blog/2020/11/01/patching-sql-developer-20-2-with-sqlcls-formatter/">Patching SQL Developer 20.2 with SQLcl&#8217;s Formatter</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.salvis.com/blog/2020/11/01/patching-sql-developer-20-2-with-sqlcls-formatter/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Formatting SQL Code Blocks in Markdown Files</title>
		<link>https://www.salvis.com/blog/2020/08/28/formatting-sql-code-blocks-in-markdown-files/</link>
		
		<dc:creator><![CDATA[Philipp Salvisberg]]></dc:creator>
		<pubDate>Fri, 28 Aug 2020 13:53:57 +0000</pubDate>
				<category><![CDATA[Oracle]]></category>
		<category><![CDATA[Arbori]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[PL/SQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[SQL Developer]]></category>
		<category><![CDATA[SQLcl]]></category>
		<guid isPermaLink="false">https://www.salvis.com/blog/?p=10477</guid>

					<description><![CDATA[<p>Introduction Everything Changes. Our Trivadis SQL &#38; PL/SQL Coding Guidelines are no exceptions. We plan to change rule #1 of our coding styles. From &#8220;Keywords are written uppercase, names are written in lowercase.&#8221;&#160; to &#8220;Keywords and names are written in lowercase.&#8220;. We have 103 Markdown files and most of them contain several<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2020/08/28/formatting-sql-code-blocks-in-markdown-files/">Formatting SQL Code Blocks in Markdown Files</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Introduction</h2>



<p>Everything Changes. Our <a href="https://github.com/trivadis/plsql-and-sql-coding-guidelines">Trivadis SQL &amp; PL/SQL Coding Guidelines</a> are no exceptions. We plan to change rule #1 of our <a href="https://trivadis.github.io/plsql-and-sql-coding-guidelines/v3.6/3-coding-style/coding-style/#rules">coding styles</a>. From &#8220;<em>Keywords are written uppercase, names are written in lowercase.&#8221;</em>&nbsp; to &#8220;<em>Keywords and names are written in lowercase.</em>&#8220;. We have 103 Markdown files and most of them contain several SQL code blocks complying to our current (old) rule #1. Should we change these files manually? Nah, this is boring and error-prone. It&#8217;s a perfect case to automate it and to show how you can format SQL code blocks in Markdown with SQLcl.</p>



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



<p>For this task, we use <a href="https://www.oracle.com/tools/downloads/sqlcl-downloads.html">SQLcl 20.2.0</a>. If you work with Oracle databases, you have most likely already installed it.</p>



<p>SQLcl is basically <a href="https://docs.oracle.com/en/database/oracle/oracle-database/19/sqpug/index.html">SQL*Plus</a> on steroids. One of the most underestimated features of SQLcl is the ability to execute JavaScript and provide them as custom SQLcl commands (read <a href="https://twitter.com/evrocs_nl">Erik van Roon</a>&#8216;s excellent <a href="https://www.evrocs.nl/being-in-command/?lang=en">blog post</a> to learn more about it). We use the custom command <a href="https://github.com/Trivadis/plsql-formatter-settings/tree/main/sqlcl#register-script-formatjs-as-sqlcl-command-tvdformat">tvdformat</a>. To install it, save <a href="https://raw.githubusercontent.com/Trivadis/plsql-formatter-settings/main/sqlcl/format.js">format.js</a> locally in a folder of your choice. Then start SQLcl (no connection required), go to the folder where you&#8217;ve saved <code>format.js</code> and run <code>script format.js -r</code>. This will register the command <code>tvdformat</code>. You get the usage help, when you enter the command without arguments.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat.png"><img loading="lazy" decoding="async" width="1020" height="775" src="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat.png" alt="" class="wp-image-10480" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat.png 1020w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat-300x228.png 300w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat-768x584.png 768w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat-192x146.png 192w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat-50x38.png 50w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat-99x75.png 99w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat-1x1.png 1w" sizes="auto, (max-width:767px) 480px, (max-width:1020px) 100vw, 1020px" /></a></figure>



<h2 class="wp-block-heading">Formatting a Single Markdown File</h2>



<p>Let&#8217;s create a simple Markdown file to see how the formatter behaves.</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">example.md (unformatted)</span><span role="button" tabindex="0" data-code="## SQL to be formated

``` sql
SELECT * FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO;
```

## SQL to be ignored

```
SELECT * FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO;
```

## JavaScript to be ignored

``` js
var foo = function (bar) {
  return bar++;
};
```" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6; font-weight: bold">## SQL to be formated</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">``` sql</span></span>
<span class="line"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> EMP </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> DEPT </span><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> EMP.DEPTNO = DEPT.DEPTNO;</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6; font-weight: bold">## SQL to be ignored</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"><span style="color: #D4D4D4">SELECT * FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO;</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6; font-weight: bold">## JavaScript to be ignored</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">``` js</span></span>
<span class="line"><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">foo</span><span style="color: #D4D4D4"> = </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">bar</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">bar</span><span style="color: #D4D4D4">++;</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span></code></pre></div>



<p>Save the content in a file named <code>example.md</code>. And then run <code>tvdformat example.md</code>. This will format this file with default settings. Default means with the embedded advanced settings (xml) and the default custom settings (arbori).</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md.png"><img loading="lazy" decoding="async" width="1020" height="229" src="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md.png" alt="" class="wp-image-10483" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md.png 1020w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md-300x67.png 300w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md-768x172.png 768w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md-260x58.png 260w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md-50x11.png 50w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md-150x34.png 150w" sizes="auto, (max-width:767px) 480px, (max-width:1020px) 100vw, 1020px" /></a></figure>



<p>The result should look like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">example.md (formatted)</span><span role="button" tabindex="0" data-code="## SQL to be formated
 
``` sql
SELECT *
  FROM EMP
  JOIN DEPT
ON EMP.DEPTNO = DEPT.DEPTNO;
```
 
## SQL to be ignored
 
```
SELECT * FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO;
```
 
## JavaScript to be ignored
 
``` js
var foo = function (bar) {
  return bar++;
};
```" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6; font-weight: bold">## SQL to be formated</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">``` sql</span></span>
<span class="line cbp-line-highlight"><span style="color: #569CD6">SELECT</span><span style="color: #D4D4D4"> *</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">FROM</span><span style="color: #D4D4D4"> EMP</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">JOIN</span><span style="color: #D4D4D4"> DEPT</span></span>
<span class="line cbp-line-highlight"><span style="color: #569CD6">ON</span><span style="color: #D4D4D4"> EMP.DEPTNO = DEPT.DEPTNO;</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6; font-weight: bold">## SQL to be ignored</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"><span style="color: #D4D4D4">SELECT * FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO;</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #569CD6; font-weight: bold">## JavaScript to be ignored</span></span>
<span class="line"><span style="color: #D4D4D4"> </span></span>
<span class="line"><span style="color: #D4D4D4">``` js</span></span>
<span class="line"><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">foo</span><span style="color: #D4D4D4"> = </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">bar</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">bar</span><span style="color: #D4D4D4">++;</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span></code></pre></div>



<p>As you see only the first SQL statement is formatted. The other code blocks are left as is. Only code blocks with <code>sql</code> syntax highlighting are formatted.</p>



<p>The indentation of line 7 is wrong. It&#8217;s an issue of the default Arbori program. It&#8217;s addressed in <code>trivadis_custom_format.arbori</code>. However,&nbsp; we do not want to format the code blocks anyway. We just want to change the keywords and identifiers to lowercase.</p>



<h2 class="wp-block-heading">Changing Keywords and Identifiers to Lowercase</h2>



<p>You can export the advanced format settings in SQL Developer. When you look at the options in the resulting XML file, the first option is <code>adjustCaseOnly</code>. This option cannot be set in the Advanced Format preferences. It&#8217;s set to <code>false</code> by default. When changed to <code>true</code> the formatter still executes some part of the Arbori program, but basically skips all actions that deal with whitespace before a node. Knowing that we can create the following <code>options.xml</code> file:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">options.xml</span><span role="button" tabindex="0" data-code="&lt;options&gt;
    &lt;adjustCaseOnly&gt;true&lt;/adjustCaseOnly&gt;
    &lt;idCase&gt;oracle.dbtools.app.Format.Case.lower&lt;/idCase&gt;
    &lt;kwCase&gt;oracle.dbtools.app.Format.Case.lower&lt;/kwCase&gt;
&lt;/options&gt;" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #808080">&lt;</span><span style="color: #569CD6">options</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">adjustCaseOnly</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">true</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">adjustCaseOnly</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">idCase</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">oracle.dbtools.app.Format.Case.lower</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">idCase</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #D4D4D4">    </span><span style="color: #808080">&lt;</span><span style="color: #569CD6">kwCase</span><span style="color: #808080">&gt;</span><span style="color: #D4D4D4">oracle.dbtools.app.Format.Case.lower</span><span style="color: #808080">&lt;/</span><span style="color: #569CD6">kwCase</span><span style="color: #808080">&gt;</span></span>
<span class="line"><span style="color: #808080">&lt;/</span><span style="color: #569CD6">options</span><span style="color: #808080">&gt;</span></span></code></pre></div>



<p>Let&#8217;s reset the content of <code>example.md</code> to the unformatted one. And then run <code>tvdformat example.md xml=options.xml</code>.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options.png"><img loading="lazy" decoding="async" width="1020" height="179" src="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options.png" alt="" class="wp-image-10488" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options.png 1020w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options-300x53.png 300w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options-768x135.png 768w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options-260x46.png 260w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options-50x9.png 50w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_example_md_with_options-150x26.png 150w" sizes="auto, (max-width:767px) 480px, (max-width:1020px) 100vw, 1020px" /></a></figure>



<p>Now, the result should look like this:</p>



<div class="wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers" data-code-block-pro-font-family="Code-Pro-JetBrains-Mono" style="font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span style="display:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7">example.md (formatted with options.xml)</span><span role="button" tabindex="0" data-code="## SQL to be formated

``` sql
select * from emp join dept on emp.deptno = dept.deptno;
```

## SQL to be ignored

```
SELECT * FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO;
```

## JavaScript to be ignored

``` js
var foo = function (bar) {
  return bar++;
};
```
" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><svg xmlns="http://www.w3.org/2000/svg" style="width:24px;height:24px" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2"><path class="with-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4"></path><path class="without-check" stroke-linecap="round" stroke-linejoin="round" d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2"></path></svg></span><pre class="shiki dark-plus" style="background-color: #1E1E1E" tabindex="0"><code><span class="line"><span style="color: #569CD6; font-weight: bold">## SQL to be formated</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">``` sql</span></span>
<span class="line"><span style="color: #569CD6">select</span><span style="color: #D4D4D4"> * </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> emp </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> dept </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> emp.deptno = dept.deptno;</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6; font-weight: bold">## SQL to be ignored</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"><span style="color: #D4D4D4">SELECT * FROM EMP JOIN DEPT ON EMP.DEPTNO = DEPT.DEPTNO;</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"></span>
<span class="line"><span style="color: #569CD6; font-weight: bold">## JavaScript to be ignored</span></span>
<span class="line"></span>
<span class="line"><span style="color: #D4D4D4">``` js</span></span>
<span class="line"><span style="color: #569CD6">var</span><span style="color: #D4D4D4"> </span><span style="color: #DCDCAA">foo</span><span style="color: #D4D4D4"> = </span><span style="color: #569CD6">function</span><span style="color: #D4D4D4"> (</span><span style="color: #9CDCFE">bar</span><span style="color: #D4D4D4">) {</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #C586C0">return</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">bar</span><span style="color: #D4D4D4">++;</span></span>
<span class="line"><span style="color: #D4D4D4">};</span></span>
<span class="line"><span style="color: #D4D4D4">```</span></span>
<span class="line"></span></code></pre></div>



<p>As before, only the first code block changed. In this case, everything is in lowercase. However, the processing is more complicated behind the scenes. For example: comments, strings, and quoted identifiers are left untouched. So, it&#8217;s more than just a simple .toLowerCase() call and for sure worth using Oracle&#8217;s formatter for this task.</p>



<h2 class="wp-block-heading">Is it Safe to Change the Case in PL/SQL &amp; SQL?</h2>



<p>PL/SQL &amp; SQL are case-insensitive languages. So you might be tempted to answer this question with &#8220;Yes&#8221;. But it is not that easy. For keywords, it&#8217;s 100% true. However, this is not true for identifiers. <a href="https://twitter.com/RogerTroller">Roger Troller</a> was the first who showed me examples of unquoted, case-sensitive identifiers in SQL. One is documented <a href="https://github.com/Trivadis/plsql-formatter-settings/issues/1">here</a>.  For example, if you use JSON columns the items in the JSON document are case-sensitive. Changing the case will break the code. That&#8217;s bad. This is also the reason, why we do not change the case of identifiers in our <a href="https://github.com/Trivadis/plsql-formatter-settings/blob/main/settings/sql_developer/trivadis_advanced_format.xml#L19">formatter configuration</a>.</p>



<p>Therefore, be careful, if you change the case of identifiers. This might break your code. Depending on your test coverage you might detect this problem very late, because the program might still compile, but not produce the expected results anymore (as in the mentioned example).</p>



<h2 class="wp-block-heading">Bulk Processing</h2>



<p>In our case, we know that we do not have JSON-based code snippets in our Markdown files. Therefore it is safe to change the case of identifiers in all files.</p>



<p>To process all files in the <code>docs</code> directory including all subdirectories I run <code>tvdformat docs&nbsp;xml=options.xml arbori=default</code>. I pass the arbori option only to avoid the warning message.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2.png"><img loading="lazy" decoding="async" width="1036" height="793" src="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2.png" alt="" class="wp-image-10507" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2.png 1036w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2-300x230.png 300w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2-1024x784.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2-768x588.png 768w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2-191x146.png 191w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2-50x38.png 50w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2-98x75.png 98w, https://www.salvis.com/blog/wp-content/uploads/2020/08/tvdformat_bulk2-1x1.png 1w" sizes="auto, (max-width:767px) 480px, (max-width:1036px) 100vw, 1036px" /></a></figure>



<p>In this case, the code is based on a Git repository. Therefore I can browse through the changes before committing them. Here&#8217;s an excerpt of the <code>g-1050.md</code> file.</p>



<figure class="wp-block-image"><a href="https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case.png"><img loading="lazy" decoding="async" width="1372" height="644" src="https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case.png" alt="" class="wp-image-10494" srcset="https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case.png 1372w, https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case-300x141.png 300w, https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case-1024x481.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case-768x360.png 768w, https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case-260x122.png 260w, https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case-50x23.png 50w, https://www.salvis.com/blog/wp-content/uploads/2020/08/g-1050-changed-case-150x70.png 150w" sizes="auto, (max-width:767px) 480px, (max-width:1372px) 100vw, 1372px" /></a></figure>



<p>You see that the original whitespace is preserved. Only keywords and identifiers are changed to lowercase. The string &#8216;AD_PERS&#8217; is still in uppercase. This looks good. Ready to be checked in.</p>



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



<p>The current formatter settings are probably not good enough for all code. There are for sure some cases where the original code base is formatted so badly, that an imperfect formatting configuration leads to a huge improvement. But generally, this is not good enough. You can use the formatter when writing code. That includes changing existing code when the current formatting style makes it difficult to read. You can always select a portion of code (a subquery, a function, etc.), format it and then change the things you don&#8217;t like. It&#8217;s easy to undo the changes in the IDE. This is also possible if you apply the formatter for a large number of files, especially if you use a version control system such as Git. It is simple to undo everything. However, when you change hundreds of files you will easily overlook some uglified code.</p>



<p>For bulk processing, changing the case of keywords is safe. Changing the case of identifiers is possible. But be careful, if you are using case-sensitive SQL, this will break your code.</p>



<p>Whatever you do, make sure you keep the version before applying the formatter. And do not forget to test and review the result.</p>
<p>The post <a href="https://www.salvis.com/blog/2020/08/28/formatting-sql-code-blocks-in-markdown-files/">Formatting SQL Code Blocks in Markdown Files</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
