<?xml version="1.0" encoding="UTF-8"?><feed
	xmlns="http://www.w3.org/2005/Atom"
	xmlns:thr="http://purl.org/syndication/thread/1.0"
	xml:lang="en-US"
	>
	<title type="text">Philipp Salvisberg&#039;s Blog</title>
	<subtitle type="text">Database-centric development</subtitle>

	<updated>2026-08-29T07:52:43Z</updated>

	<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/" />
	<id>https://www.salvis.com/blog/feed/atom/</id>
	<link rel="self" type="application/atom+xml" href="https://www.salvis.com/blog/feed/atom/" />

	<generator uri="https://wordpress.org/" version="7.1">WordPress</generator>
<icon>https://www.salvis.com/blog/wp-content/uploads/2014/04/favicon.png</icon>
<link rel="hub" href="https://pubsubhubbub.appspot.com" />
<link rel="hub" href="https://pubsubhubbub.superfeedr.com" />
<link rel="hub" href="https://websubhub.com/hub" />
<link rel="self" href="https://www.salvis.com/blog/feed/atom/" />
	<entry>
		<author>
			<name>Philipp Salvisberg</name>
							<uri>http://www.salvis.com/</uri>
						</author>

		<title type="html"><![CDATA[Implicit Outer Joins in Join-to-One: Feature or Flaw?]]></title>
		<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/" />

		<id>https://www.salvis.com/blog/?p=23948</id>
		<updated>2026-08-29T07:52:43Z</updated>
		<published>2026-08-29T07:52:40Z</published>
		<category scheme="https://www.salvis.com/blog/" term="Oracle" /><category scheme="https://www.salvis.com/blog/" term="Oracle 26ai" /><category scheme="https://www.salvis.com/blog/" term="SQL" />
		<summary type="html"><![CDATA[<p>Background As you probably know, I&#8217;m maintaining a parser for grammars used in SQL files for Oracle AI Database and PostgreSQL. As a result, I check for new statements and clauses in every version of those DBMSs. PostgreSQL typically adds new features only in major versions; this means yearly. Oracle, on the<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/">Implicit Outer Joins in Join-to-One: Feature or Flaw?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></summary>

					<content type="html" xml:base="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/"><![CDATA[
<h2 id="background" class="wp-block-heading">Background</h2>



<p class="wp-block-paragraph">As you probably know, I&#8217;m maintaining a parser for grammars used in SQL files for Oracle AI Database and PostgreSQL. As a result, I check for new statements and clauses in every version of those DBMSs. PostgreSQL typically adds new features only in major versions; this means yearly. Oracle, on the other hand, documents new features in every new RU; this means quarterly. </p>



<p class="wp-block-paragraph">The RU for 26.2 was a bit delayed. So, on 1 May 2026, I went through the new features in 26.2 and discovered the <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/adfns/building-queries-correct-joins-more-easily.html#GUID-FEB8218C-8FD5-47BC-BB14-4E43DDD32F35" target="_blank" rel="noreferrer noopener">join-to-one clause</a> while documenting the changes required for IslandSQL in a <a href="https://github.com/IslandSQL/IslandSQL/issues/315" data-type="link" data-id="https://github.com/IslandSQL/IslandSQL/issues/315" target="_blank" rel="noreferrer noopener">GitHub issue</a>. I tried the feature in an OCI instance and posted about it on Bluesky.</p>



<figure class="wp-block-image size-full"><a href="https://bsky.app/profile/salvis.com/post/3mkt4dj3ofc2c" target="_blank" rel=" noopener"><img fetchpriority="high" decoding="async" width="592" height="511" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky.png" alt="Join to one post on Bluesky" class="wp-image-23950" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky.png 592w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-300x259.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-87x75.png 87w, https://www.salvis.com/blog/wp-content/uploads/2026/08/join-to-one-post-on-bsky-480x414.png 480w" sizes="(max-width:767px) 480px, 592px" /></a></figure>



<p class="wp-block-paragraph">This led to some discussions in private channels. </p>



<p class="wp-block-paragraph">Back then, I hadn&#8217;t made up my mind regarding the usefulness of this feature, but the fact that a join uses outer-join semantics by default irritated me from the very first moment.</p>



<p class="wp-block-paragraph">In the meantime, I believe that this feature is useful for various use cases. I&#8217;m not going to talk about that in this blog post. However, the longer I thought about the implicit outer join in join-to-one, the more it irritated me.</p>



<h2 id="join-to-one-will-make-it-into-the-sql-standard" class="wp-block-heading">Join-To-One Will Make It Into the SQL Standard</h2>



<p class="wp-block-paragraph">According to <a href="https://peter.eisentraut.org/blog/2026/06/30/waiting-for-sql-202y-stockholm-meeting-report#join-to-one" target="_blank" rel="noreferrer noopener">Peter Eisentraut&#8217;s blog post</a>, this feature has been accepted into the next SQL standard and is now part of its working draft. I wonder whether they also discussed the default join behaviour of a join-to-one and what the consensus was. </p>



<p class="wp-block-paragraph">Anyway, since version 26.2, this feature is part of Oracle AI Database. Changing the behaviour at that stage is only feasible with a database parameter similar to <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/refrn/GROUP_BY_POSITION_ENABLED.html" data-type="link" data-id="https://docs.oracle.com/en/database/oracle/oracle-database/26/refrn/GROUP_BY_POSITION_ENABLED.html" target="_blank" rel="noreferrer noopener">group_by_position_enabled</a> to keep backward compatibility. I doubt that something like this will happen.</p>



<h2 id="what-is-the-problem" class="wp-block-heading">What Is the Problem?</h2>



<p class="wp-block-paragraph">It is the first time an outer join has become the default. For every other join variant since ANSI SQL-86, an inner join has been the default. We are used to that.</p>



<p class="wp-block-paragraph">Changing such a long-established convention is not necessarily a bad thing. However, there should be a convincing reason for doing so.</p>



<p class="wp-block-paragraph">The <a href="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-9388EBCC-9ADE-4668-AAF4-D6193B8395F2" data-type="link" data-id="https://docs.oracle.com/en/database/oracle/oracle-database/26/sqlrf/SELECT.html#GUID-CFA006CA-6FF1-4972-821E-6996142A51C6__GUID-9388EBCC-9ADE-4668-AAF4-D6193B8395F2" target="_blank" rel="noreferrer noopener">SQL Language Reference</a> provides this reason:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p class="wp-block-paragraph">&#8220;The database chose this default because <code>INNER JOIN</code>s often filter rows unintentionally.&#8221;</p>
</blockquote>



<p class="wp-block-paragraph">So, the intention is to avoid accidental filtering. That sounds reasonable. But is silently preserving rows really better than silently filtering them?</p>



<p class="wp-block-paragraph">In both cases, the omitted join type affects the result. An implicit inner join may remove rows. An implicit outer join may introduce null values that have to be considered in subsequent expressions and predicates.</p>



<p class="wp-block-paragraph">In any case, the join-to-one clause relies on integrity constraints. These constraints are already used to derive the join condition. So why not consider them fully and choose an inner join for mandatory foreign keys and an outer join for optional foreign keys?</p>



<p class="wp-block-paragraph">Of course, this would make the join type depend on the schema definition. A change to the optionality of a foreign key could then change the semantics of an existing query. That would have been a very good reason not to choose a fixed default join type, right?</p>



<p class="wp-block-paragraph">However, while the optimiser could deal with a dynamically determined join type, the query would be more challenging to read and understand. We would need to check the current optionality of each foreign key involved to determine whether nulls need to be handled.</p>



<p class="wp-block-paragraph">Ouch. This would be cumbersome without implementing an additional concept that forces us to handle null values in SQL expressions and predicates (something similar to <a href="https://jspecify.dev/docs/user-guide/" data-type="link" data-id="https://jspecify.dev/docs/user-guide/" target="_blank" rel="noreferrer noopener">JSpecify</a>). Therefore, it&#8217;s probably better not to derive the join type automatically from a foreign key&#8217;s optionality. Being explicit has its value.</p>



<p class="wp-block-paragraph">Furthermore, an outer join limits the optimiser&#8217;s solution space and can affect performance, as Andrej Pashchenko demonstrated for join-to-one in <a href="https://blog.sqlora.com/en/oracle-26ai-an-even-closer-look-at-join-to-one/" data-type="link" data-id="https://blog.sqlora.com/en/oracle-26ai-an-even-closer-look-at-join-to-one/" target="_blank" rel="noreferrer noopener">this blog post</a>.</p>



<p class="wp-block-paragraph">These performance aspects may be addressed in upcoming versions. But the unfamiliar implicit default join strategy remains.</p>



<h2 id="an-example" class="wp-block-heading">An Example</h2>



<p class="wp-block-paragraph">Let&#8217;s compare the following two queries:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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;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">1) Implicit outer joins</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          departments d,
          jobs j,
          employees mgr on e.manager_id 
                       = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><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"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          departments d,</span></span>
<span class="line"><span style="color: #D4D4D4">          jobs j,</span></span>
<span class="line"><span style="color: #D4D4D4">          employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                       = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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;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">2) Explict inner and outer joins</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          outer join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><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"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>
</div>



<p class="wp-block-paragraph">The queries are based on the HR example schema and produce the same result.</p>



<p class="wp-block-paragraph">Which one is easier to read and understand?</p>



<p class="wp-block-paragraph">Which one reveals information that might be helpful when crafting or reviewing the WHERE clause?</p>



<p class="wp-block-paragraph">IMO, the second example. For both questions.</p>



<p class="wp-block-paragraph">The second example shows that: </p>



<ul class="wp-block-list">
<li>Employees do not necessarily belong to a department. Yes, the <code>department_id</code> column in the <code>employees</code> table is optional.</li>



<li>Not every employee has a manager.</li>



<li>Every employee has a job.</li>
</ul>



<p class="wp-block-paragraph">This information helps us filter data using the department or manager columns. We have to handle null values there.</p>



<p class="wp-block-paragraph">Based on that, we can see a flaw in the query. We can either use an inner join for managers because we are not interested in counting employees without a manager, or we have to address employees without a manager in the WHERE clause.</p>



<p class="wp-block-paragraph">So, we should change the query to something like the following:</p>



<div class="wp-block-columns is-layout-flex wp-container-core-columns-is-layout-8f761849 wp-block-columns-is-layout-flex">
<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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-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">2a) Excluding emps without mgr</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          inner join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary;</textarea></pre><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"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary;</span></span></code></pre></div>
</div>



<div class="wp-block-column is-layout-flow wp-block-column-is-layout-flow">
<div class="wp-block-kevinbatdorf-code-block-pro" 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-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">2b) Including emps without mgr</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>select count(*)
  from employees e
  join to one (
          outer join departments d
          inner join jobs j
          outer join employees mgr on e.manager_id 
                                  = mgr.employee_id
       )
 where e.salary > mgr.salary
    or mgr.employee_id is null;</textarea></pre><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"> </span><span style="color: #DCDCAA">count</span><span style="color: #D4D4D4">(*)</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">from</span><span style="color: #D4D4D4"> employees e</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> to one (</span></span>
<span class="line"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> departments d</span></span>
<span class="line"><span style="color: #D4D4D4">          inner </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> jobs j</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">          outer </span><span style="color: #569CD6">join</span><span style="color: #D4D4D4"> employees mgr </span><span style="color: #569CD6">on</span><span style="color: #D4D4D4"> e.manager_id </span></span>
<span class="line"><span style="color: #D4D4D4">                                  = mgr.employee_id</span></span>
<span class="line"><span style="color: #D4D4D4">       )</span></span>
<span class="line"><span style="color: #D4D4D4"> </span><span style="color: #569CD6">where</span><span style="color: #D4D4D4"> e.salary &gt; mgr.salary</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">    </span><span style="color: #569CD6">or</span><span style="color: #D4D4D4"> mgr.employee_id </span><span style="color: #569CD6">is null</span><span style="color: #D4D4D4">;</span></span></code></pre></div>
</div>
</div>



<p class="wp-block-paragraph">Query 2a produces the same result as queries 1 and 2, but the inner join on employees makes it clear that excluding employees without a manager was intended.</p>



<p class="wp-block-paragraph">Query 2b produces additional results for employees without a manager. The outer join on employees and the null handling in the WHERE clause make it clear that this was intentional.</p>



<h2 id="summary" class="wp-block-heading">Summary</h2>



<p class="wp-block-paragraph">IMO, the implicit outer joins in the new join-to-one clause are clearly a flaw. You should always specify inner or outer joins explicitly in a join-to-one clause. This communicates the intended semantics and highlights where downstream null handling may be required.</p>



<p class="wp-block-paragraph">If you are using <a href="https://marketplace.visualstudio.com/items?itemName=Grisselbav.dblinter" target="_blank" rel="noreferrer noopener">dbLinter</a> &#8211; which you should &#8211; then you can enable the rule <a href="https://dblinter.app/ords/r/dblinter/dblinter-console/rules#P1000_SHOW_RULE=core%20g-3194" target="_blank" rel="noreferrer noopener">G-3194</a> to improve the maintainability of your join-to-one clauses.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/">Implicit Outer Joins in Join-to-One: Feature or Flaw?</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content>
		
					<link rel="replies" type="text/html" href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/#comments" thr:count="0" />
			<link rel="replies" type="application/atom+xml" href="https://www.salvis.com/blog/2026/08/29/implicit-outer-joins-in-join-to-one-feature-or-flaw/feed/atom/" thr:count="0" />
			<thr:total>0</thr:total>
			</entry>
		<entry>
		<author>
			<name>Philipp Salvisberg</name>
							<uri>http://www.salvis.com/</uri>
						</author>

		<title type="html"><![CDATA[The Checkbox That Disables TLS]]></title>
		<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/" />

		<id>https://www.salvis.com/blog/?p=23591</id>
		<updated>2026-08-24T05:38:18Z</updated>
		<published>2026-08-23T21:20:28Z</published>
		<category scheme="https://www.salvis.com/blog/" term="Oracle" /><category scheme="https://www.salvis.com/blog/" term="APEXlang" /><category scheme="https://www.salvis.com/blog/" term="Code Analysis" /><category scheme="https://www.salvis.com/blog/" term="dbLinter" /><category scheme="https://www.salvis.com/blog/" term="PL/SQL" /><category scheme="https://www.salvis.com/blog/" term="SQL" />
		<summary type="html"><![CDATA[<p>Introduction The dbLinter clients include a new setting named Allow Insecure TLS. It is disabled by default. As a result, all REST API calls verify the TLS certificate and hostname. The setting allows dbLinter to work in organisations that inspect TLS traffic using tools such as Zscaler. In larger organisations, arranging an<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/">The Checkbox That Disables TLS</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></summary>

					<content type="html" xml:base="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/"><![CDATA[
<h2 id="introduction" class="wp-block-heading">Introduction</h2>



<p class="wp-block-paragraph">The dbLinter clients include a new setting named <code>Allow Insecure TLS</code>. It is disabled by default. As a result, all REST API calls verify the TLS certificate and hostname. </p>



<p class="wp-block-paragraph">The setting allows dbLinter to work in organisations that inspect TLS traffic using tools such as <a href="https://help.zscaler.com/zia/understanding-ssltls-inspection" target="_blank" rel="noreferrer noopener">Zscaler</a>.</p>



<p class="wp-block-paragraph">In larger organisations, arranging an inspection bypass can be cumbersome and is often too much effort for an ad-hoc trial of dbLinter. The checkbox provides a temporary workaround and should be enabled only on a trusted network.</p>



<p class="wp-block-paragraph">However, allowing insecure TLS on untrusted networks, such as open Wi-Fi without client isolation, can let an attacker redirect traffic through their own machine using techniques like <a href="https://en.wikipedia.org/wiki/ARP_spoofing" target="_blank" rel="noreferrer noopener">ARP spoofing</a>. The attacker can also operate the access point themselves, for example, by creating a rogue Wi-Fi hotspot.</p>



<p class="wp-block-paragraph">In this blog post, I demonstrate the effect of this checkbox.</p>



<h2 id="allow-insecure-tls" class="wp-block-heading">Allow Insecure TLS</h2>



<p class="wp-block-paragraph">The latest version of dbLinter for VS Code has a checkbox that disables certificate and hostname verification.</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox.png"><img decoding="async" width="1024" height="833" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1024x833.png" alt="Allow Insecure TLS Checkbox in VS Code" class="wp-image-23595" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1024x833.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-300x244.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-768x624.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-1536x1249.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-2048x1665.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-92x75.png 92w, https://www.salvis.com/blog/wp-content/uploads/2026/08/allow-insecure-tls-checkbox-480x390.png 480w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">dbLinter&#8217;s <code>allowInsecureTls</code> setting is nothing unusual. Many common tools offer a similar option, including curl (<code>--insecure</code>), wget (<code>--no-check-certificate</code>), and git (<code>--config http.sslVerify false</code>).</p>



<h2 id="installing-and-configuring-a-proxy" class="wp-block-heading">Installing and Configuring a Proxy</h2>



<p class="wp-block-paragraph">I run this demo on macOS 26.6.2.</p>



<p class="wp-block-paragraph">A simple proxy is <a href="https://www.mitmproxy.org/" data-type="link" data-id="https://www.mitmproxy.org/" target="_blank" rel="noreferrer noopener">mitmweb</a>. We can install and configure it as follows:</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" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>brew install mitmproxy
networksetup -setsecurewebproxy "Wi-Fi" 127.0.0.1 8090
mitmweb --listen-port 8090 --web-port 8091 --allow-hosts '^api\.dblinter\.app'</textarea></pre><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">brew</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">install</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">mitmproxy</span></span>
<span class="line"><span style="color: #DCDCAA">networksetup</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-setsecurewebproxy</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Wi-Fi&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">127.0</span><span style="color: #CE9178">.0.1</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8090</span></span>
<span class="line"><span style="color: #DCDCAA">mitmweb</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--listen-port</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8090</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--web-port</span><span style="color: #D4D4D4"> </span><span style="color: #B5CEA8">8091</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--allow-hosts</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&#39;^api\.dblinter\.app&#39;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;20:36:20.907&#93; HTTP(S) proxy listening at *:8090.
&#91;20:36:20.908&#93; Web server listening at http://127.0.0.1:8091/?token=f83b02032aaaccd282ad3925a484fcdb</textarea></pre><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">&#91;20:36:20.907&#93; HTTP(S) proxy listening at *:8090.</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:36:20.908&#93; Web server listening at http://127.0.0.1:8091/?token=f83b02032aaaccd282ad3925a484fcdb</span></span></code></pre></div>



<p class="wp-block-paragraph">The <code>mitmweb</code> command starts the proxy and listens on port 8090 for TLS traffic between localhost and <code>api.dblinter.app</code>. All other traffic is bypassed. </p>



<p class="wp-block-paragraph">The <code>mitmweb</code> proxy also opens the following web page:</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start.png"><img decoding="async" width="1024" height="201" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-1024x201.png" alt="mitmproxy after start up" class="wp-image-23617" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-1024x201.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-300x59.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-768x150.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-150x29.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start-480x94.png 480w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-start.png 1281w" sizes="(max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<h2 id="intercepting-traffic" class="wp-block-heading">Intercepting Traffic</h2>



<p class="wp-block-paragraph">To generate traffic, we launch VS Code and open a SQL file. This produces the following in the output panel for dbLinter:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>2026-08-23 20:37:43.216 &#91;Info &#93; Starting dbLinter Language Server.
2026-08-23 20:37:43.539 &#91;Info &#93; connect.
2026-08-23 20:37:43.611 &#91;Info &#93; initialize VSCode 1.10.0.
2026-08-23 20:37:43.646 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.
2026-08-23 20:37:43.651 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.
2026-08-23 20:37:43.671 &#91;Warn &#93; TLS certificate and hostname verification are disabled for dbLinter repository API calls. Use this temporary workaround only when TLS interception cannot be bypassed.
2026-08-23 20:37:45.533 &#91;Info &#93; Configuration dbLinter of tenant Grisselbav loaded with 294 check methods.
2026-08-23 20:37:45.534 &#91;Info &#93; didChangeConfiguration.
2026-08-23 20:37:45.703 &#91;Info &#93; tests returned 43 tests.
2026-08-23 20:37:45.796 &#91;Info &#93; parseAndCheck file:///.../dbl_client_types.sql.
2026-08-23 20:37:45.910 &#91;Info &#93; hasFeature Config returned true.
2026-08-23 20:37:46.286 &#91;Info &#93; parseAndCheck completed in 0.489 sec including 0.052 sec for checks.
2026-08-23 20:37:46.289 &#91;Info &#93; diagnostics for file:///.../dbl_client_types.sql with 2 issues.</textarea></pre><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">2026-08-23 20:37:43.216 &#91;Info &#93; Starting dbLinter Language Server.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.539 &#91;Info &#93; connect.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.611 &#91;Info &#93; initialize VSCode 1.10.0.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.646 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:43.651 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">2026-08-23 20:37:43.671 &#91;Warn &#93; TLS certificate and hostname verification are disabled for dbLinter repository API calls. Use this temporary workaround only when TLS interception cannot be bypassed.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.533 &#91;Info &#93; Configuration dbLinter of tenant Grisselbav loaded with 294 check methods.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.534 &#91;Info &#93; didChangeConfiguration.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.703 &#91;Info &#93; tests returned 43 tests.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.796 &#91;Info &#93; parseAndCheck file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:45.910 &#91;Info &#93; hasFeature Config returned true.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:46.286 &#91;Info &#93; parseAndCheck completed in 0.489 sec including 0.052 sec for checks.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:37:46.289 &#91;Info &#93; diagnostics for file:///.../dbl_client_types.sql with 2 issues.</span></span></code></pre></div>



<p class="wp-block-paragraph">The log contains a warning that TLS certificate and hostname verification are disabled.</p>



<p class="wp-block-paragraph">dbLinter analyses SQL and APEXlang files locally. The captured traffic lets us verify what is sent to the dbLinter API. It contains the API key and session data, but not the contents of the analysed files. The source code therefore remains within the local network.</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-scaled.png"><img loading="lazy" decoding="async" width="1024" height="538" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1024x538.png" alt="mitmproxy request message" class="wp-image-23618" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1024x538.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-300x158.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-768x403.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-1536x807.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-2048x1076.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-143x75.png 143w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-request-480x252.png 480w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">It goes without saying that it is not good to expose the API key in plain text.</p>



<p class="wp-block-paragraph">The proxy also shows the decrypted response:</p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-scaled.png"><img loading="lazy" decoding="async" width="1024" height="292" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1024x292.png" alt="mitmproxy response message" class="wp-image-23619" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1024x292.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-300x85.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-768x219.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-1536x438.png 1536w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-2048x584.png 2048w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-150x43.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/mitmproxy-response-480x137.png 480w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">The session object in the response contains a signature. The client can therefore detect changes to the signed content, including the validators. This prevents the proxy from silently modifying the validators or injecting malicious code. However, the signature does not prevent the proxy from reading the request and response.</p>



<h2 id="enforce-tls-verification" class="wp-block-heading">Enforce TLS Verification</h2>



<p class="wp-block-paragraph">Now let&#8217;s uncheck the <code>Allow Insecure TLS</code> checkbox and execute the <code>Reload Window</code> command. </p>



<figure class="wp-block-image size-large"><a href="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2.png"><img loading="lazy" decoding="async" width="1024" height="191" src="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-1024x191.png" alt="disallow insecure TLS in VS Code" class="wp-image-23613" srcset="https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-1024x191.png 1024w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-300x56.png 300w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-768x143.png 768w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-150x28.png 150w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2-480x89.png 480w, https://www.salvis.com/blog/wp-content/uploads/2026/08/image-2.png 1354w" sizes="auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px" /></a></figure>



<p class="wp-block-paragraph">This produces the following in the output panel for dbLinter:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>2026-08-23 20:52:37.281 &#91;Info &#93; Starting dbLinter Language Server.
2026-08-23 20:52:37.550 &#91;Info &#93; connect.
2026-08-23 20:52:37.606 &#91;Info &#93; initialize VSCode 1.10.0.
2026-08-23 20:52:38.047 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.
2026-08-23 20:52:38.049 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.
2026-08-23 20:52:38.375 &#91;Error&#93; Failed to load configuration.

org.springframework.web.client.ResourceAccessException: I/O error on POST request for "https://api.dblinter.app/api/client-session/open": (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</textarea></pre><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">2026-08-23 20:52:37.281 &#91;Info &#93; Starting dbLinter Language Server.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:37.550 &#91;Info &#93; connect.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:37.606 &#91;Info &#93; initialize VSCode 1.10.0.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:38.047 &#91;Info &#93; didOpen file:///.../dbl_client_types.sql.</span></span>
<span class="line"><span style="color: #D4D4D4">2026-08-23 20:52:38.049 &#91;Info &#93; AntlrCacheCoordinator initialized with parallel degree 1 and clearCacheThreshold 2048 of 16384 MB.</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">2026-08-23 20:52:38.375 &#91;Error&#93; Failed to load configuration.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">org.springframework.web.client.ResourceAccessException: I/O error on POST request for &quot;https://api.dblinter.app/api/client-session/open&quot;: (certificate_unknown) PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</span></span></code></pre></div>



<p class="wp-block-paragraph">The proxy presented a certificate for <code>api.dblinter.app</code> which was not issued by a trusted certification authority.</p>



<p class="wp-block-paragraph">The proxy console therefore shows the following log entry:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>&#91;20:52:38.217&#93;&#91;127.0.0.1:60439&#93; server connect api.dblinter.app:443 (91.98.90.2:443)
&#91;20:52:38.360&#93;&#91;127.0.0.1:60441&#93; client connect
&#91;20:52:38.375&#93;&#91;127.0.0.1:60439&#93; Client TLS handshake failed. The client does not trust the proxy's certificate for api.dblinter.app (OpenSSL Error(&#91;('SSL routines', '', 'ssl/tls alert certificate unknown')&#93;))
&#91;20:52:38.377&#93;&#91;127.0.0.1:60439&#93; client disconnect
&#91;20:52:38.380&#93;&#91;127.0.0.1:60439&#93; server disconnect api.dblinter.app:443 (91.98.90.2:443)</textarea></pre><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">&#91;20:52:38.217&#93;&#91;127.0.0.1:60439&#93; server connect api.dblinter.app:443 (91.98.90.2:443)</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.360&#93;&#91;127.0.0.1:60441&#93; client connect</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">&#91;20:52:38.375&#93;&#91;127.0.0.1:60439&#93; Client TLS handshake failed. The client does not trust the proxy&#39;s certificate for api.dblinter.app (OpenSSL Error(&#91;(&#39;SSL routines&#39;, &#39;&#39;, &#39;ssl/tls alert certificate unknown&#39;)&#93;))</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.377&#93;&#91;127.0.0.1:60439&#93; client disconnect</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;20:52:38.380&#93;&#91;127.0.0.1:60439&#93; server disconnect api.dblinter.app:443 (91.98.90.2:443)</span></span></code></pre></div>



<p class="wp-block-paragraph">The REST API call failed before the proxy received the HTTP request. Therefore, the API key and other request data were not exposed.</p>



<h2 id="reset-network-configuration-and-unistall-proxy" class="wp-block-heading">Reset Network Configuration and Uninstall Proxy</h2>



<p class="wp-block-paragraph">Let&#8217;s stop the proxy by pressing Ctrl-C in the terminal window running it. Then run the following:</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" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>networksetup -setsecurewebproxystate "Wi-Fi" off
brew uninstall mitmproxy
rm -rf ~/.mitmproxy</textarea></pre><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">networksetup</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-setsecurewebproxystate</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;Wi-Fi&quot;</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">off</span></span>
<span class="line"><span style="color: #DCDCAA">brew</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">uninstall</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">mitmproxy</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">~/.mitmproxy</span></span></code></pre></div>



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



<p class="wp-block-paragraph">The <code>Allow Insecure TLS</code> option solves a practical problem in environments where TLS inspection cannot easily be bypassed. However, it disables certificate and hostname verification. A proxy or an attacker controlling the network can then read requests, including the API key.</p>



<p class="wp-block-paragraph">The captured traffic also confirms that dbLinter analyses SQL and APEXlang files locally. Signed server responses protect the downloaded configuration from manipulation, but they do not protect confidential request data.</p>



<p class="wp-block-paragraph">Therefore, enable this option only as a temporary workaround on a trusted network. The preferred solution is to configure a TLS inspection bypass. Disable the option again as soon as possible.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/">The Checkbox That Disables TLS</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content>
		
					<link rel="replies" type="text/html" href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/#comments" thr:count="0" />
			<link rel="replies" type="application/atom+xml" href="https://www.salvis.com/blog/2026/08/23/the-checkbox-that-disables-tls/feed/atom/" thr:count="0" />
			<thr:total>0</thr:total>
			</entry>
		<entry>
		<author>
			<name>Philipp Salvisberg</name>
							<uri>http://www.salvis.com/</uri>
						</author>

		<title type="html"><![CDATA[The Return of SQLcl&#8217;s SCRIPT Command]]></title>
		<link rel="alternate" type="text/html" href="https://www.salvis.com/blog/2026/07/25/the-return-of-sqlcls-script-command/" />

		<id>https://www.salvis.com/blog/?p=21049</id>
		<updated>2026-07-27T09:17:27Z</updated>
		<published>2026-07-25T14:02:15Z</published>
		<category scheme="https://www.salvis.com/blog/" term="Oracle" /><category scheme="https://www.salvis.com/blog/" term="JavaScript" /><category scheme="https://www.salvis.com/blog/" term="SQL Developer" /><category scheme="https://www.salvis.com/blog/" term="SQLcl" />
		<summary type="html"><![CDATA[<p>Introduction The script command was introduced with SQLcl 4.2. It is based on JSR 223, the Java Scripting API, and makes it possible to run JavaScript from SQLcl. This adds client-side control flow, file access, better control of host commands and access to Java classes and JavaScript libraries. JDK 8 was the<span class="excerpt-hellip"> […]</span></p>
<p>The post <a href="https://www.salvis.com/blog/2026/07/25/the-return-of-sqlcls-script-command/">The Return of SQLcl&#8217;s SCRIPT Command</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></summary>

					<content type="html" xml:base="https://www.salvis.com/blog/2026/07/25/the-return-of-sqlcls-script-command/"><![CDATA[
<h2 id="introduction" class="wp-block-heading">Introduction</h2>



<p class="wp-block-paragraph">The <code>script</code> command was introduced with SQLcl 4.2. It is based on JSR 223, the Java Scripting API, and makes it possible to run JavaScript from SQLcl. This adds client-side control flow, file access, better control of host commands and access to Java classes and JavaScript libraries. </p>



<p class="wp-block-paragraph">JDK 8 was the latest and greatest back in 2015 when Kris Rice promoted this feature on his <a href="https://krisrice.io/2015-10-13-sqlcl-oct-13th-edition/" target="_blank" rel="noreferrer noopener">blog</a>. The <code>script</code> command worked out of the box because JDK 8 included the Nashorn JavaScript engine. Nashorn was deprecated in JDK 11 and removed in JDK 15, but continues as a <a href="https://github.com/openjdk/nashorn" data-type="link" data-id="https://github.com/openjdk/nashorn" target="_blank" rel="noreferrer noopener">standalone OpenJDK library</a> for JDK 11 and newer. The current version 26.2 of SQLcl requires JDK 11 or newer, but does not include a JavaScript engine. Therefore, <code>script</code> no longer works with a modern standard JDK.</p>



<p class="wp-block-paragraph">The <a href="https://docs.oracle.com/en/database/oracle/sql-developer-command-line/26.2/sqcug/working-sqlcl.html" target="_blank" rel="noreferrer noopener">documented solution</a> is to use GraalVM and install its JavaScript engine using the command <code>gu install js</code>. However, <code>gu</code> has been removed from more recent GraalVM distributions. Applications requiring a JavaScript engine must therefore provide the necessary Maven dependencies themselves.</p>



<p class="wp-block-paragraph">Furthermore, the SQL Developer extension for VS Code comes with its own JDK 25. We cannot simply replace it with an older GraalVM JDK since some components require a JDK 25 and are therefore incompatible with older JDK versions.</p>



<p class="wp-block-paragraph">The <code>script</code> command does not work in SQLcl embedded in SQL Developer for VS Code.</p>



<p class="wp-block-paragraph">Let’s change that.</p>



<h2 id="patching-sqlcl-in-sql-developer-for-vs-code" class="wp-block-heading">Patching SQLcl in SQL Developer for VS Code</h2>



<p class="wp-block-paragraph">I experimented with various approaches. The result is <a href="https://github.com/PhilippSalvisberg/sqlcl-js-patch/blob/main/sqlcl-js-patch.sh" data-type="link" data-id="https://github.com/PhilippSalvisberg/sqlcl-js-patch" target="_blank" rel="noreferrer noopener">sqlcl-js-patch.sh</a>. The idea is to download the missing JavaScript engine and its dependencies from Maven Central and add them to an SQLcl installation. This shell script supports GraalJS and Nashorn on JDK 17 and newer.</p>



<p class="wp-block-paragraph">For SQL Developer for VS Code, I prefer Nashorn. It is compatible with the behaviour we had with JDK 8 and JDK 11 and produces no warnings when SQLcl starts.</p>



<p class="wp-block-paragraph">Close all SQLcl sessions in VS Code. Then run the following command in a macOS, Linux or Git Bash shell:</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">1) Patch SQLcl with Nashorn JavaScript engine</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>curl --fail --location --silent --show-error \
  https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh |
  sh -s -- add nashorn "sqlcl_home=$HOME/.vscode"</textarea></pre><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">curl</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--fail</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--location</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--silent</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--show-error</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh</span><span style="color: #D4D4D4"> |</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">sh</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-s</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">add</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">nashorn</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;sqlcl_home=</span><span style="color: #9CDCFE">$HOME</span><span style="color: #CE9178">/.vscode&quot;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Downloading nashorn-core-15.7.jar
Downloading asm-7.3.1.jar
Downloading asm-commons-7.3.1.jar
Downloading asm-analysis-7.3.1.jar
Downloading asm-tree-7.3.1.jar
Downloading asm-util-7.3.1.jar
No matching libraries found in /Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib.
Installed nashorn-core-15.7.jar
Installed asm-commons-7.3.1.jar
Installed asm-7.3.1.jar
Installed asm-analysis-7.3.1.jar
Installed asm-util-7.3.1.jar
Installed asm-tree-7.3.1.jar
No nashorn.args VM option found in macOS/Linux launcher; skipped Nashorn launcher patch.
Installed nashorn libraries in /Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib.</textarea></pre><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">Downloading nashorn-core-15.7.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading asm-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading asm-commons-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading asm-analysis-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading asm-tree-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading asm-util-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">No matching libraries found in /Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib.</span></span>
<span class="line"><span style="color: #D4D4D4">Installed nashorn-core-15.7.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed asm-commons-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed asm-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed asm-analysis-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed asm-util-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed asm-tree-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">No nashorn.args VM option found in macOS/Linux launcher; skipped Nashorn launcher patch.</span></span>
<span class="line"><span style="color: #D4D4D4">Installed nashorn libraries in /Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib.</span></span></code></pre></div>



<p class="wp-block-paragraph">The patch script locates the most recent Oracle SQL Developer extension in the <code>$HOME/.vscode/extensions</code> directory. It adds the necessary JAR files to the embedded SQLcl, whose directory structure differs from that of standalone SQLcl.</p>



<p class="wp-block-paragraph">Now start a new SQLcl session in VS Code and run:</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">2) Test script command</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>script
print('Hello from Nashorn');
/</textarea></pre><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: #9CDCFE">script</span></span>
<span class="line"><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;Hello from Nashorn&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-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 role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>SQLcl: Release 26.2 Production on Sat Jul 25 13:19:46 2026

Copyright (c) 1982, 2026, Oracle.  All rights reserved.

Connected to:
Oracle AI Database 26ai Free Release 23.26.2.0.0 - Develop, Learn, and Run for Free
Version 23.26.2.0.0

Hello from Nashorn
SQL> </textarea></pre><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">SQLcl: Release 26.2 Production on Sat Jul 25 13:19:46 2026</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Copyright (c) 1982, 2026, Oracle.  All rights reserved.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Connected to:</span></span>
<span class="line"><span style="color: #D4D4D4">Oracle AI Database 26ai Free Release 23.26.2.0.0 - Develop, Learn, and Run for Free</span></span>
<span class="line"><span style="color: #D4D4D4">Version 23.26.2.0.0</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Hello from Nashorn</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; </span></span></code></pre></div>



<p class="wp-block-paragraph">This does not work when the code is executed directly in a SQL Developer worksheet. It works when you select <strong>Run in SQLcl</strong>.</p>



<p class="wp-block-paragraph">That’s it. The <code>script</code> command is back.</p>



<p class="wp-block-paragraph">Please note that updating the SQL Developer extension installs a new embedded SQLcl. In that case, run the patch command again.</p>



<h2 id="does-it-work-with-graaljs" class="wp-block-heading">Does It Work With GraalJS?</h2>



<p class="wp-block-paragraph">Yes. </p>



<p class="wp-block-paragraph">Just pass <code>graaljs</code> instead of <code>nashorn</code>:</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);--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">3) Patch SQLcl with GraalJS JavaScript engine</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>curl --fail --location --silent --show-error \
  https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh |
  sh -s -- add graaljs "sqlcl_home=$HOME/.vscode"</textarea></pre><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">curl</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--fail</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--location</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--silent</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--show-error</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh</span><span style="color: #D4D4D4"> |</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">sh</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-s</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">add</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">graaljs</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;sqlcl_home=</span><span style="color: #9CDCFE">$HOME</span><span style="color: #CE9178">/.vscode&quot;</span></span></code></pre></div>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>Downloading collections-25.1.3.jar
Downloading icu4j-25.1.3.jar
Downloading jniutils-25.1.3.jar
Downloading js-language-25.1.3.jar
Downloading js-scriptengine-25.1.3.jar
Downloading nativeimage-25.1.3.jar
Downloading polyglot-25.1.3.jar
Downloading regex-25.1.3.jar
Downloading truffle-api-25.1.3.jar
Downloading truffle-compiler-25.1.3.jar
Downloading truffle-runtime-25.1.3.jar
Downloading word-25.1.3.jar
Downloading xz-25.1.3.jar
Deleted nashorn-core-15.7.jar
Deleted asm-commons-7.3.1.jar
Deleted asm-7.3.1.jar
Deleted asm-analysis-7.3.1.jar
Deleted asm-util-7.3.1.jar
Deleted asm-tree-7.3.1.jar
Deleted asm-commons-7.3.1.jar
Deleted asm-analysis-7.3.1.jar
Deleted asm-tree-7.3.1.jar
Deleted asm-util-7.3.1.jar
Installed collections-25.1.3.jar
Installed regex-25.1.3.jar
Installed truffle-compiler-25.1.3.jar
Installed polyglot-25.1.3.jar
Installed truffle-api-25.1.3.jar
Installed jniutils-25.1.3.jar
Installed truffle-runtime-25.1.3.jar
Installed js-language-25.1.3.jar
Installed xz-25.1.3.jar
Installed word-25.1.3.jar
Installed icu4j-25.1.3.jar
Installed js-scriptengine-25.1.3.jar
Installed nativeimage-25.1.3.jar
Installed graaljs libraries in /Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib.</textarea></pre><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">Downloading collections-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading icu4j-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading jniutils-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading js-language-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading js-scriptengine-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading nativeimage-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading polyglot-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading regex-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading truffle-api-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading truffle-compiler-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading truffle-runtime-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading word-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Downloading xz-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted nashorn-core-15.7.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-commons-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-analysis-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-util-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-tree-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-commons-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-analysis-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-tree-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Deleted asm-util-7.3.1.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed collections-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed regex-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed truffle-compiler-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed polyglot-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed truffle-api-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed jniutils-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed truffle-runtime-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed js-language-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed xz-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed word-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed icu4j-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed js-scriptengine-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed nativeimage-25.1.3.jar</span></span>
<span class="line"><span style="color: #D4D4D4">Installed graaljs libraries in /Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib.</span></span></code></pre></div>



<p class="wp-block-paragraph">Let&#8217;s start a new SQLcl session in VS Code and run:</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">4) Test script command</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>script
print('Hello from GraalJS');
/</textarea></pre><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: #9CDCFE">script</span></span>
<span class="line"><span style="color: #DCDCAA">print</span><span style="color: #D4D4D4">(</span><span style="color: #CE9178">&#39;Hello from GraalJS&#39;</span><span style="color: #D4D4D4">);</span></span>
<span class="line"><span style="color: #D4D4D4">/</span></span></code></pre></div>



<details class="wp-block-details is-layout-flow wp-block-details-is-layout-flow"><summary>Show/hide output</summary>
<div class="wp-block-kevinbatdorf-code-block-pro" 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-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>SQLcl: Release 26.2 Production on Sat Jul 25 12:20:22 2026

Copyright (c) 1982, 2026, Oracle.  All rights reserved.

WARNING: A restricted method in java.lang.System has been called
WARNING: java.lang.System::load has been called by com.oracle.truffle.polyglot.JDKSupport in module org.graalvm.truffle (file:/Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib/truffle-api-25.1.3.jar)
WARNING: Use --enable-native-access=org.graalvm.truffle to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

&#91;To redirect Truffle log output to a file use one of the following options:
* '--log.file=&lt;path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=&lt;path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.&#93;
&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.
&#91;To redirect Truffle log output to a file use one of the following options:
* '--log.file=&lt;path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=&lt;path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.&#93;
&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.
WARNING: A terminally deprecated method in sun.misc.Unsafe has been called
WARNING: sun.misc.Unsafe::objectFieldOffset has been called by com.oracle.truffle.api.strings.TStringUnsafe (file:/Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib/truffle-api-25.1.3.jar)
WARNING: Please consider reporting this to the maintainers of class com.oracle.truffle.api.strings.TStringUnsafe
WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release
&#91;To redirect Truffle log output to a file use one of the following options:
* '--log.file=&lt;path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=&lt;path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.&#93;
&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.
&#91;To redirect Truffle log output to a file use one of the following options:
* '--log.file=&lt;path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=&lt;path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.&#93;
&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.
&#91;To redirect Truffle log output to a file use one of the following options:
* '--log.file=&lt;path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=&lt;path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.&#93;
&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.
Connected to:
Oracle AI Database 26ai Free Release 23.26.2.0.0 - Develop, Learn, and Run for Free
Version 23.26.2.0.0

&#91;To redirect Truffle log output to a file use one of the following options:
* '--log.file=&lt;path>' if the option is passed using a guest language launcher.
* '-Dpolyglot.log.file=&lt;path>' if the option is passed using the host Java launcher.
* Configure logging using the polyglot embedding API.&#93;
&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.
Execution without runtime compilation will negatively impact the guest application performance.
The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.
For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.
To disable this warning use the '--engine.WarnInterpreterOnly=false' option or the '-Dpolyglot.engine.WarnInterpreterOnly=false' system property.
Hello from GraalJS
SQL> </textarea></pre><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">SQLcl: Release 26.2 Production on Sat Jul 25 12:20:22 2026</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">Copyright (c) 1982, 2026, Oracle.  All rights reserved.</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: A restricted method in java.lang.System has been called</span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: java.lang.System::load has been called by com.oracle.truffle.polyglot.JDKSupport in module org.graalvm.truffle (file:/Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib/truffle-api-25.1.3.jar)</span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: Use --enable-native-access=org.graalvm.truffle to avoid a warning for callers in this module</span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: Restricted methods will be blocked in a future release unless native access is enabled</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">&#91;To redirect Truffle log output to a file use one of the following options:</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;--log.file=&lt;path&gt;&#39; if the option is passed using a guest language launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;-Dpolyglot.log.file=&lt;path&gt;&#39; if the option is passed using the host Java launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* Configure logging using the polyglot embedding API.&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.</span></span>
<span class="line"><span style="color: #D4D4D4">Execution without runtime compilation will negatively impact the guest application performance.</span></span>
<span class="line"><span style="color: #D4D4D4">The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.</span></span>
<span class="line"><span style="color: #D4D4D4">For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.</span></span>
<span class="line"><span style="color: #D4D4D4">To disable this warning use the &#39;--engine.WarnInterpreterOnly=false&#39; option or the &#39;-Dpolyglot.engine.WarnInterpreterOnly=false&#39; system property.</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;To redirect Truffle log output to a file use one of the following options:</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;--log.file=&lt;path&gt;&#39; if the option is passed using a guest language launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;-Dpolyglot.log.file=&lt;path&gt;&#39; if the option is passed using the host Java launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* Configure logging using the polyglot embedding API.&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.</span></span>
<span class="line"><span style="color: #D4D4D4">Execution without runtime compilation will negatively impact the guest application performance.</span></span>
<span class="line"><span style="color: #D4D4D4">The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.</span></span>
<span class="line"><span style="color: #D4D4D4">For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.</span></span>
<span class="line"><span style="color: #D4D4D4">To disable this warning use the &#39;--engine.WarnInterpreterOnly=false&#39; option or the &#39;-Dpolyglot.engine.WarnInterpreterOnly=false&#39; system property.</span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: A terminally deprecated method in sun.misc.Unsafe has been called</span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: sun.misc.Unsafe::objectFieldOffset has been called by com.oracle.truffle.api.strings.TStringUnsafe (file:/Users/phs/.vscode/extensions/oracle.sql-developer-26.2.0-darwin-arm64/dbtools/sqlcl/lib/truffle-api-25.1.3.jar)</span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: Please consider reporting this to the maintainers of class com.oracle.truffle.api.strings.TStringUnsafe</span></span>
<span class="line"><span style="color: #D4D4D4">WARNING: sun.misc.Unsafe::objectFieldOffset will be removed in a future release</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;To redirect Truffle log output to a file use one of the following options:</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;--log.file=&lt;path&gt;&#39; if the option is passed using a guest language launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;-Dpolyglot.log.file=&lt;path&gt;&#39; if the option is passed using the host Java launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* Configure logging using the polyglot embedding API.&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.</span></span>
<span class="line"><span style="color: #D4D4D4">Execution without runtime compilation will negatively impact the guest application performance.</span></span>
<span class="line"><span style="color: #D4D4D4">The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.</span></span>
<span class="line"><span style="color: #D4D4D4">For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.</span></span>
<span class="line"><span style="color: #D4D4D4">To disable this warning use the &#39;--engine.WarnInterpreterOnly=false&#39; option or the &#39;-Dpolyglot.engine.WarnInterpreterOnly=false&#39; system property.</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;To redirect Truffle log output to a file use one of the following options:</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;--log.file=&lt;path&gt;&#39; if the option is passed using a guest language launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;-Dpolyglot.log.file=&lt;path&gt;&#39; if the option is passed using the host Java launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* Configure logging using the polyglot embedding API.&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.</span></span>
<span class="line"><span style="color: #D4D4D4">Execution without runtime compilation will negatively impact the guest application performance.</span></span>
<span class="line"><span style="color: #D4D4D4">The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.</span></span>
<span class="line"><span style="color: #D4D4D4">For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.</span></span>
<span class="line"><span style="color: #D4D4D4">To disable this warning use the &#39;--engine.WarnInterpreterOnly=false&#39; option or the &#39;-Dpolyglot.engine.WarnInterpreterOnly=false&#39; system property.</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;To redirect Truffle log output to a file use one of the following options:</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;--log.file=&lt;path&gt;&#39; if the option is passed using a guest language launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;-Dpolyglot.log.file=&lt;path&gt;&#39; if the option is passed using the host Java launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* Configure logging using the polyglot embedding API.&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.</span></span>
<span class="line"><span style="color: #D4D4D4">Execution without runtime compilation will negatively impact the guest application performance.</span></span>
<span class="line"><span style="color: #D4D4D4">The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.</span></span>
<span class="line"><span style="color: #D4D4D4">For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.</span></span>
<span class="line"><span style="color: #D4D4D4">To disable this warning use the &#39;--engine.WarnInterpreterOnly=false&#39; option or the &#39;-Dpolyglot.engine.WarnInterpreterOnly=false&#39; system property.</span></span>
<span class="line"><span style="color: #D4D4D4">Connected to:</span></span>
<span class="line"><span style="color: #D4D4D4">Oracle AI Database 26ai Free Release 23.26.2.0.0 - Develop, Learn, and Run for Free</span></span>
<span class="line"><span style="color: #D4D4D4">Version 23.26.2.0.0</span></span>
<span class="line"><span style="color: #D4D4D4"></span></span>
<span class="line"><span style="color: #D4D4D4">&#91;To redirect Truffle log output to a file use one of the following options:</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;--log.file=&lt;path&gt;&#39; if the option is passed using a guest language launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* &#39;-Dpolyglot.log.file=&lt;path&gt;&#39; if the option is passed using the host Java launcher.</span></span>
<span class="line"><span style="color: #D4D4D4">* Configure logging using the polyglot embedding API.&#93;</span></span>
<span class="line"><span style="color: #D4D4D4">&#91;engine&#93; WARNING: The polyglot engine uses a fallback runtime that does not support runtime compilation to native code.</span></span>
<span class="line"><span style="color: #D4D4D4">Execution without runtime compilation will negatively impact the guest application performance.</span></span>
<span class="line"><span style="color: #D4D4D4">The following cause was found: JVMCI is not enabled for this JVM. Enable JVMCI using -XX:+EnableJVMCI.</span></span>
<span class="line"><span style="color: #D4D4D4">For more information see: https://www.graalvm.org/latest/reference-manual/embed-languages/#runtime-optimization-support.</span></span>
<span class="line"><span style="color: #D4D4D4">To disable this warning use the &#39;--engine.WarnInterpreterOnly=false&#39; option or the &#39;-Dpolyglot.engine.WarnInterpreterOnly=false&#39; system property.</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">Hello from GraalJS</span></span>
<span class="line"><span style="color: #D4D4D4">SQL&gt; </span></span></code></pre></div>
</details>



<p class="wp-block-paragraph">After several warnings, the expected result appears at the end.</p>



<p class="wp-block-paragraph">I explained the <a href="https://github.com/PhilippSalvisberg/sqlcl-js-patch/tree/main#graaljs-related-warnings" target="_blank" rel="noreferrer noopener">GraalJS-related warnings</a> in my GitHub repository. The following environment setting will suppress most of the warnings. Where you define this variable depends on your operating system and shell. In any case, the environment variable must be visible before you start VS Code.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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;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">5) Non-breaking JDK_JAVA_OPTIONS to suppress warnings</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>export JDK_JAVA_OPTIONS="-Dpolyglot.engine.WarnInterpreterOnly=false -Dpolyglot.js.nashorn-compat=true"</textarea></pre><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">export</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">JDK_JAVA_OPTIONS</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;-Dpolyglot.engine.WarnInterpreterOnly=false -Dpolyglot.js.nashorn-compat=true&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">If you are only using JDK 24 or newer on your system, you can disable all warnings as follows. However, be aware that any JDK version below 24 will no longer work, because the Java runtime stops with an error when passing unknown JVM arguments.</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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;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">6) Breaking JDK_JAVA_OPTIONS to suppress warnings</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>export JDK_JAVA_OPTIONS="--illegal-native-access=allow --sun-misc-unsafe-memory-access=allow -Dpolyglot.engine.WarnInterpreterOnly=false -Dpolyglot.js.nashorn-compat=true"</textarea></pre><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">export</span><span style="color: #D4D4D4"> </span><span style="color: #9CDCFE">JDK_JAVA_OPTIONS</span><span style="color: #D4D4D4">=</span><span style="color: #CE9178">&quot;--illegal-native-access=allow --sun-misc-unsafe-memory-access=allow -Dpolyglot.engine.WarnInterpreterOnly=false -Dpolyglot.js.nashorn-compat=true&quot;</span></span></code></pre></div>



<h2 id="can-i-also-use-this-for-standalone-sqlcl" class="wp-block-heading">Can I Also Use This for Standalone SQLcl?</h2>



<p class="wp-block-paragraph">Yes.</p>



<p class="wp-block-paragraph">Pass the SQLcl installation directory instead of the VS Code configuration directory:</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);--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">7) Patch standalone SQLcl with Nashorn JavaScript engine (macOS/Linux only)</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>curl --fail --location --silent --show-error \
  https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh |
  sh -s -- add nashorn "sqlcl_home=/path/to/sqlcl"</textarea></pre><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">curl</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--fail</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--location</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--silent</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--show-error</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh</span><span style="color: #D4D4D4"> |</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">sh</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-s</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">add</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">nashorn</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;sqlcl_home=/path/to/sqlcl&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">This works very well on macOS and Linux. Besides installing the Nashorn libraries, the patch removes the following option from the <code>bin/sql</code> launcher:</p>



<div class="wp-block-kevinbatdorf-code-block-pro" 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-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)"><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>-Dnashorn.args=--no-deprecation-warning</textarea></pre><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">-</span><span style="color: #9CDCFE">Dnashorn</span><span style="color: #D4D4D4">.</span><span style="color: #9CDCFE">args</span><span style="color: #D4D4D4">=--no-deprecation-warning</span></span></code></pre></div>



<p class="wp-block-paragraph">The standalone Nashorn engine does not support this option. It throws an exception while the engine is initialised, and SQLcl consequently reports <code>JavaScript engine not found.</code></p>



<p class="wp-block-paragraph">On Windows, <code>bin/sql.exe</code> is a binary executable. The patch script cannot modify it. It can add the Nashorn libraries when run from Git Bash, but it cannot apply the necessary launcher workaround. Therefore, Nashorn does not work with standalone SQLcl on Windows. GraalJS does not need this launcher change and is therefore the only option supported by the patch script on Windows:</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);--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">8) Patch standalone SQLcl with GraalJS JavaScript engine</span><span role="button" tabindex="0" style="color:#D4D4D4;display:none" aria-label="Copy" class="code-block-pro-copy-button"><pre class="code-block-pro-copy-button-pre" aria-hidden="true"><textarea class="code-block-pro-copy-button-textarea" tabindex="-1" aria-hidden="true" readonly>curl --fail --location --silent --show-error \
  https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh |
  sh -s -- add graaljs "sqlcl_home=/path/to/sqlcl"</textarea></pre><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">curl</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--fail</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--location</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--silent</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--show-error</span><span style="color: #D4D4D4"> </span><span style="color: #D7BA7D">\</span></span>
<span class="line"><span style="color: #D4D4D4">  </span><span style="color: #CE9178">https://raw.githubusercontent.com/PhilippSalvisberg/sqlcl-js-patch/refs/heads/main/sqlcl-js-patch.sh</span><span style="color: #D4D4D4"> |</span></span>
<span class="line cbp-line-highlight"><span style="color: #D4D4D4">  </span><span style="color: #DCDCAA">sh</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">-s</span><span style="color: #D4D4D4"> </span><span style="color: #569CD6">--</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">add</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">graaljs</span><span style="color: #D4D4D4"> </span><span style="color: #CE9178">&quot;sqlcl_home=/path/to/sqlcl&quot;</span></span></code></pre></div>



<p class="wp-block-paragraph">This raises an interesting question. SQL Developer for VS Code also includes a Windows <code>bin/sql.exe</code> that the patch script cannot modify. So why does Nashorn work there?</p>



<h2 id="but-why-does-nashorn-work-in-embedded-sqlcl" class="wp-block-heading">But Why Does Nashorn Work in Embedded SQLcl?</h2>



<p class="wp-block-paragraph">I mentioned before that the embedded SQLcl version has a different folder structure (there is no <code>lib/ext</code> folder for third-party libraries). But that&#8217;s not the only difference. </p>



<p class="wp-block-paragraph">The launcher is also different. Neither <code>bin/sql</code> nor <code>bin/sql.exe</code> includes the <code>-Dnashorn.args=--no-deprecation-warning</code> JVM option.</p>



<p class="wp-block-paragraph"> As a result, the Nashorn JavaScript engine works in the embedded SQLcl version of SQL Developer for VS Code.</p>



<h2 id="outlook" class="wp-block-heading">Outlook</h2>



<p class="wp-block-paragraph">I hope this helps you bring the SQLcl <code>script</code> command back to life in your environments, especially in SQL Developer for VS Code, where using another Java runtime is not a practical option.</p>



<p class="wp-block-paragraph">However, I also hope that we will not have to run <code>sqlcl-js-patch.sh</code> for every new SQLcl or SQL Developer extension version until the end of time. The patch consists mainly of adding libraries that are available from Maven Central. It would be great if the Oracle SQL Developer team included these libraries in a future update and made the <code>script</code> command work out of the box again.</p>



<p class="wp-block-paragraph"><em>Updated on 2026-07-27, mentioned OpenJDK Nashorn in paragraph 2</em>.</p>



<p class="wp-block-paragraph"></p>
<p>The post <a href="https://www.salvis.com/blog/2026/07/25/the-return-of-sqlcls-script-command/">The Return of SQLcl&#8217;s SCRIPT Command</a> appeared first on <a href="https://www.salvis.com/blog">Philipp Salvisberg&#039;s Blog</a>.</p>
]]></content>
		
					<link rel="replies" type="text/html" href="https://www.salvis.com/blog/2026/07/25/the-return-of-sqlcls-script-command/#comments" thr:count="2" />
			<link rel="replies" type="application/atom+xml" href="https://www.salvis.com/blog/2026/07/25/the-return-of-sqlcls-script-command/feed/atom/" thr:count="2" />
			<thr:total>2</thr:total>
			</entry>
	</feed>
