{"id":9572,"date":"2020-04-13T00:12:31","date_gmt":"2020-04-12T22:12:31","guid":{"rendered":"https:\/\/www.salvis.com\/blog\/?p=9572"},"modified":"2023-11-12T13:51:01","modified_gmt":"2023-11-12T12:51:01","slug":"formatting-code-with-sql-developer","status":"publish","type":"post","link":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/","title":{"rendered":"Formatting Code With SQL Developer"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p>I started using SQL Developer in 2013. Back then version 4.0 was the latest and greatest. But the capabilities of the formatter were disappointing. In 2017 Oracle released version 4.2 with a new formatter and has been improving it ever since. Version 19.2 brought us dynamic JavaScript actions within the parse-tree query language Arbori. And now I must admit that I&#8217;m really impressed with the formatting capabilities of the latest versions of SQL Developer. Arbori is a hidden gem.<\/p>\n\n\n\n<p>In this blog post, I explain how the formatter works and how the output can be tweaked using two simple SQL queries.<\/p>\n\n\n\n<p>If you only want to activate the coding styles suggested by the Trivadis PL\/SQL &amp; SQL Coding Guidelines, install the settings as described <a href=\"https:\/\/github.com\/Trivadis\/plsql-formatter-settings#installation\">here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How Does Formatting Work?<\/h2>\n\n\n\n<p>Formatting is all about adding (or removing) whitespace (line breaks, spaces or tabs) between significant tokens. That sounds easy. Well, it&#8217;s not. Because the formatting requirements are very different. Ultimately, it&#8217;s all about beautifying the code. And almost every developer has their own views on what makes code look good. Furthermore, it is technically demanding to provide a tool suite that can handle different coding styles via configuration.<\/p>\n\n\n\n<p>The following figure illustrates the formatting process in SQL Developer.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png\"><img loading=\"lazy\" decoding=\"async\" width=\"695\" height=\"522\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png\" alt=\"\" class=\"wp-image-9577\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png 695w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview-300x225.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview-194x146.png 194w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview-50x38.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview-100x75.png 100w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview-1x1.png 1w\" sizes=\"auto, (max-width:767px) 480px, 695px\" \/><\/a><\/figure>\n\n\n\n<p>I will explain each step and component in the next chapters.<\/p>\n\n\n\n<p>Please note that these are conceptual components, the actual implementation might look different.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">1. Parser<\/h3>\n\n\n\n<p>The parser reads the unformatted plain SQL or PL\/SQL input and generates a parse-tree. The parse-tree is a hierarchical representation of the significant tokens of the input. In other words, there is neither whitespace nor comments in a parse-tree.<\/p>\n\n\n\n<p>Each node in the parse-tree includes the start and end position within the plain SQL input.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">2. Formatter<\/h3>\n\n\n\n<p>The formatter needs the parse-tree and the code formatting configuration as input.<\/p>\n\n\n\n<p>SQL Developer stores the configuration in the preferences.<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Under <code>Code Editor<\/code> -&gt; <code>Format<\/code> -&gt; <code>Advanced Format<\/code> for configuration properties such as <code>Line breaks on comma<\/code> (<code>after<\/code>, <code>before<\/code>, <code>none<\/code>).<\/li>\n\n\n\n<li>And under <code>Code Editor<\/code> -&gt; <code>Format<\/code> -&gt; <code>Advanced Format<\/code> -&gt; <code>Custom Format<\/code> for the Arbori program used to handle whitespace.<\/li>\n<\/ul>\n\n\n\n<h4 class=\"wp-block-heading\">2.1 Provided Java Callback Functions<\/h4>\n\n\n\n<p>The formatter provides the following Java callback functions (in the order how they are expected to be called):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>indentedNodes1<\/li>\n\n\n\n<li>indentedNodes2<\/li>\n\n\n\n<li>skipWhiteSpaceBeforeNode<\/li>\n\n\n\n<li>skipWhiteSpaceAfterNode<\/li>\n\n\n\n<li>identifiers<\/li>\n\n\n\n<li>extraBrkBefore<\/li>\n\n\n\n<li>extraBrkAfter<\/li>\n\n\n\n<li>brkX2<\/li>\n\n\n\n<li>rightAlignments<\/li>\n\n\n\n<li>paddedIdsInScope<\/li>\n\n\n\n<li>incrementalAlignments<\/li>\n\n\n\n<li>pairwiseAlignments<\/li>\n\n\n\n<li>ignoreLineBreaksBeforeNode<\/li>\n\n\n\n<li>ignoreLineBreaksAfterNode<\/li>\n\n\n\n<li>dontFormatNode<\/li>\n<\/ul>\n\n\n\n<p>Each callback functions gets the parameters <code>target<\/code> (the parse-tree) and <code>tuple<\/code> (node to be processed). As an Arbori developer you do not have to care about how to populate these parameters. It&#8217;s done automatically. <code>target<\/code> is a global variable and <code>tuple<\/code> is the result row of an Arbori query. Basically, you only need to query the nodes and call the callback functions. The position in an Arbori program defines the execution order.<\/p>\n\n\n\n<p>These provided Java callback functions have two issues.<\/p>\n\n\n\n<p>First of all, you don&#8217;t know what they do. Granted, there are some comments in the provided Arbori program, and also a description in the <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/sql-developer\/19.4\/rptug\/sql-developer-concepts-usage.html#GUID-9421DA6E-A48A-427B-88C9-4414D83EC9D1\">SQL Developer Users Guide<\/a>, but this will only give you a rough idea. For example, it leaves you in the dark why `indentedNodes` has two callback functions and both must be called.<\/p>\n\n\n\n<p>Second, you cannot process selected nodes differently. You must write an enhancement request so that the SQL Developer team can provide the necessary callback functionality in a future release. This is cumbersome.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">2.2 JavaScript Callback Functions<\/h4>\n\n\n\n<p>Thankfully, the SQL Developer team has added a JavaScript callback feature in version 19.2. This allows you to embed callback functions directly into your Arbori program. Now you can really add and remove whitespace wherever you want. The global variable <code>struct<\/code> gives you access to the instance of the formatter and the configuration properties. As a result, you can manage the whitespace before a position of a node through the methods <code>getNewline<\/code> and <code>putNewline<\/code>.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">2.3 The Result<\/h4>\n\n\n\n<p>Basically, the result of this process is a list of whitespace per position.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Serializer<\/h3>\n\n\n\n<p>The serializer loops through the leaf nodes of the parse-tree. It retrieves the leading whitespace for a node&#8217;s start position and extracts the token text from the pure SQL input using the node&#8217;s start and end position. And then the serializer writes the whitespace and the token text to the final result. The formatted SQL.<\/p>\n\n\n\n<p>In fact, the process is actually a bit more complicated. It adds whitespace to mandatory nodes, for instance.<\/p>\n\n\n\n<p>Moreover, the serializer performs some &#8220;formatting&#8221; without Arbori. For example, it converts the case of identifiers and keywords according to the configuration (properties). Therefore, it is not possible to change the case of a token with an Arbori program. It might be possible by configuring a custom Java formatter class, but that&#8217;s another story.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example Using Provided Java Callback Function<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Setup<\/h3>\n\n\n\n<p>For this example I use the <code>Advanced Format<\/code> according&nbsp; the <a href=\"https:\/\/github.com\/Trivadis\/plsql-formatter-settings\/blob\/main\/settings\/sql_developer\/trivadis_advanced_format.xml\">trivadis_advanced_format.xml<\/a> file. Here&#8217;s a screenshot of the configuration settings of my SQL Developer 19.4.0 installation:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format.png\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"768\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format.png\" alt=\"\" class=\"wp-image-9587\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format.png 1024w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format-300x225.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format-768x576.png 768w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format-195x146.png 195w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format-50x38.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format-100x75.png 100w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/advanced_format-1x1.png 1w\" sizes=\"auto, (max-width:767px) 480px, (max-width:1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p>The default is used for the <code>Custom Format<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Default Formatter Result<\/h3>\n\n\n\n<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:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"SELECT e.ename,\n       e.deptno,\n       d.dname\n  FROM dept d\n  LEFT JOIN emp e\nON d.deptno = e.deptno\n ORDER BY e.ename NULLS FIRST;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> e.ename,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       e.deptno,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       d.dname<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> dept d<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">LEFT JOIN<\/span><span style=\"color: #D4D4D4\"> emp e<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #569CD6\">ON<\/span><span style=\"color: #D4D4D4\"> d.deptno = e.deptno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> e.ename <\/span><span style=\"color: #569CD6\">NULLS<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">FIRST<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The result looks good, besides the missing indentation on line 6.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Expected Formatter Result<\/h3>\n\n\n\n<p>What we expect is this:<\/p>\n\n\n\n<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:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"SELECT e.ename,\n       e.deptno,\n       d.dname\n  FROM dept d\n  LEFT JOIN emp e\n    ON d.deptno = e.deptno\n ORDER BY e.ename NULLS FIRST;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> e.ename,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       e.deptno,<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">       d.dname<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> dept d<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">LEFT JOIN<\/span><span style=\"color: #D4D4D4\"> emp e<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">ON<\/span><span style=\"color: #D4D4D4\"> d.deptno = e.deptno<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> e.ename <\/span><span style=\"color: #569CD6\">NULLS<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">FIRST<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The <code>ON<\/code> keyword right-aligned as <code>SELECT<\/code>, <code>FROM<\/code>, <code>LEFT<\/code> and <code>ORDER<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Code Outline<\/h3>\n\n\n\n<p>SQL Developer&#8217;s code outline is in fact a representation of the full parse-tree. Disable all filters to show all nodes.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"491\" height=\"885\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1.png\" alt=\"\" class=\"wp-image-9592\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1.png 491w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1-166x300.png 166w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1-81x146.png 81w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1-28x50.png 28w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1-42x75.png 42w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/outline-example1-1x2.png 1w\" sizes=\"auto, (max-width:767px) 480px, 491px\" \/><\/a><\/figure>\n\n\n\n<p>The highlighted information is important for the next step.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Arbori Editor<\/h3>\n\n\n\n<p>Type <code>arbori<\/code> in the search field and press enter as shown below:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/open-arbori-editor.png\"><img loading=\"lazy\" decoding=\"async\" width=\"386\" height=\"107\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/open-arbori-editor.png\" alt=\"\" class=\"wp-image-9593\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/open-arbori-editor.png 386w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/open-arbori-editor-300x83.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/open-arbori-editor-260x72.png 260w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/open-arbori-editor-50x14.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/open-arbori-editor-150x42.png 150w\" sizes=\"auto, (max-width:767px) 386px, 386px\" \/><\/a><\/figure>\n\n\n\n<p>This will open the <code>Arbori Editor<\/code>. Type the following query in the editor window:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(1 * 0.6 * .875rem);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"query:\n   [node) 'ON' &amp; [node^) on_using_condition\n;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C8C8C8\">query<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">   [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #CE9178\">&#39;ON&#39;<\/span><span style=\"color: #D4D4D4\"> &amp; [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">^) <\/span><span style=\"color: #9CDCFE\">on_using_condition<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Press <code>Run<\/code> to display the query result:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-editor-example1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"549\" height=\"211\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-editor-example1.png\" alt=\"\" class=\"wp-image-9597\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-editor-example1.png 549w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-editor-example1-300x115.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-editor-example1-260x100.png 260w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-editor-example1-50x19.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-editor-example1-150x58.png 150w\" sizes=\"auto, (max-width:767px) 480px, 549px\" \/><\/a><\/figure>\n\n\n\n<p>What have we done? We query the parse-tree (outline) for all <code>ON<\/code> nodes where the parent node is an <code>on_using_condition<\/code>. A node is represented as&nbsp; <code>[node)<\/code>. And a parent node is represented as <code>[node^)<\/code>. A boolean AND is represented as <code>&amp;<\/code>.&nbsp; See <a href=\"https:\/\/github.com\/Trivadis\/plsql-formatter-settings#links\">these links<\/a> for more information about the Arbori grammar.<\/p>\n\n\n\n<p>Click on the query result cell <code>[19,20) 'ON'<\/code>&nbsp;to highlight the node in the <code>Code Outline<\/code> window and the corresponding text in the worksheet. You can do the same with the cell <code>[19,27) on_using_condition<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Change in Arbori Program<\/h3>\n\n\n\n<p>Now open the <code>Preferences<\/code>&nbsp; for <code>Custom Format<\/code> and search for the query named <code>rightAlignments<\/code> (it&#8217;s usually easier to change the Arbori program in separate editor). It looks like this:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"988\" height=\"368\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1.png\" alt=\"\" class=\"wp-image-9598\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1.png 988w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1-300x112.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1-768x286.png 768w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1-260x97.png 260w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1-50x19.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-1-150x56.png 150w\" sizes=\"auto, (max-width:767px) 480px, (max-width:988px) 100vw, 988px\" \/><\/a><\/figure>\n\n\n\n<p>Here some explanation of the query:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The predicate <code>:alignRight<\/code> means that the option <code>Right-Align Query Keywords<\/code> must be checked (true).<\/li>\n\n\n\n<li>We know the boolean AND <code>&amp;<\/code> ,&nbsp; the current node <code>[node)<\/code>&nbsp; and the parent node <code>[node^)<\/code> from the previous query.<\/li>\n\n\n\n<li>The parenthesis <code>(<\/code> and <code>)<\/code> are part of the boolean expression.<\/li>\n\n\n\n<li>The <code>|<\/code>&nbsp; is a boolean OR.<\/li>\n\n\n\n<li>The <code>-&gt;<\/code> at the end means the callback function named as the query (<code>rightAlignments<\/code>) is called for matching nodes.<\/li>\n\n\n\n<li><code>--<\/code> is used for single-line comments as in SQL and PL\/SQL.<\/li>\n<\/ul>\n\n\n\n<p>We extend the query by the predicate <code>| [node) 'ON' &amp; [node^) on_using_condition<\/code>&nbsp; to right-align the <code>ON<\/code> token.<\/p>\n\n\n\n<p>Here&#8217;s the amended query:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"967\" height=\"377\" src=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2.png\" alt=\"\" class=\"wp-image-9599\" srcset=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2.png 967w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2-300x117.png 300w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2-768x299.png 768w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2-260x101.png 260w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2-50x19.png 50w, https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-advanced-format-2-150x58.png 150w\" sizes=\"auto, (max-width:767px) 480px, (max-width:967px) 100vw, 967px\" \/><\/a><\/figure>\n\n\n\n<p>Press <code>OK<\/code> to&nbsp; save the preferences. Now, the query is formatted correctly.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Example Using JavaScript Callback Function<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Default Formatter Result<\/h3>\n\n\n\n<p>We use the same setup as for the previous example.<\/p>\n\n\n\n<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:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"SELECT *\n  FROM dept d\n WHERE EXISTS (\n   SELECT *\n     FROM emp e\n    WHERE e.deptno = d.deptno\n      AND e.sal &gt; 2900\n)\n ORDER BY d.deptno;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> dept d<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">WHERE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">EXISTS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">   <\/span><span style=\"color: #569CD6\">SELECT<\/span><span style=\"color: #D4D4D4\"> *<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">     <\/span><span style=\"color: #569CD6\">FROM<\/span><span style=\"color: #D4D4D4\"> emp e<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #569CD6\">WHERE<\/span><span style=\"color: #D4D4D4\"> e.deptno = d.deptno<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">AND<\/span><span style=\"color: #D4D4D4\"> e.sal &gt; <\/span><span style=\"color: #B5CEA8\">2900<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">)<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">ORDER BY<\/span><span style=\"color: #D4D4D4\"> d.deptno;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>The result does not look too bad. But the indentation feels wrong. Especially when I look at the missing indentation of&nbsp; the <code>)<\/code> on line 8. Therefore, I&#8217;d like to increase the indentation of the highlighted lines by 7.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Expected Formatter Result<\/h3>\n\n\n\n<p>What we expect is this:<\/p>\n\n\n\n<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:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"SELECT *\n  FROM dept d\n WHERE EXISTS (\n          SELECT *\n            FROM emp e\n           WHERE e.deptno = d.deptno\n             AND e.sal &gt; 2900\n       )\n ORDER BY d.deptno;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #4FC1FF\">SELECT<\/span><span style=\"color: #D4D4D4\"> *<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  <\/span><span style=\"color: #4FC1FF\">FROM<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">dept<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">d<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">WHERE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">EXISTS<\/span><span style=\"color: #D4D4D4\"> (<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">          <\/span><span style=\"color: #4FC1FF\">SELECT<\/span><span style=\"color: #D4D4D4\"> *<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">            <\/span><span style=\"color: #4FC1FF\">FROM<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">emp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">e<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">           <\/span><span style=\"color: #4FC1FF\">WHERE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">e<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">deptno<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">d<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">deptno<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">             <\/span><span style=\"color: #4FC1FF\">AND<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">e<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">sal<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #B5CEA8\">2900<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">       )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">ORDER<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">BY<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">d<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">deptno<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Look at the indentation on line 8. <code>)<\/code> matches now the indentation of <code>EXISTS (<\/code>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Change in Arbori Program<\/h3>\n\n\n\n<p>The highlighted code block is already indented. Therefore we cannot use the same mechanism as previously. We want an additional indentation. We can achieve that with an additional query and a JavaScript callback function.<\/p>\n\n\n\n<p>Add the following query at the end of the existing Arbori program in <code>Custom Format<\/code> of the <code>Preferences<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-kevinbatdorf-code-block-pro cbp-has-line-numbers\" data-code-block-pro-font-family=\"Code-Pro-JetBrains-Mono\" style=\"font-size:.875rem;font-family:Code-Pro-JetBrains-Mono,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,monospace;--cbp-line-number-color:#D4D4D4;--cbp-line-number-width:calc(2 * 0.6 * .875rem);--cbp-line-highlight-color:rgba(234, 191, 191, 0.2);line-height:1.25rem;--cbp-tab-width:2;tab-size:var(--cbp-tab-width, 2)\"><span style=\"display:block;padding:16px 0 0 16px;margin-bottom:-1px;width:100%;text-align:left;background-color:#1E1E1E\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"54\" height=\"14\" viewBox=\"0 0 54 14\"><g fill=\"none\" fill-rule=\"evenodd\" transform=\"translate(1 1)\"><circle cx=\"6\" cy=\"6\" r=\"6\" fill=\"#FF5F56\" stroke=\"#E0443E\" stroke-width=\".5\"><\/circle><circle cx=\"26\" cy=\"6\" r=\"6\" fill=\"#FFBD2E\" stroke=\"#DEA123\" stroke-width=\".5\"><\/circle><circle cx=\"46\" cy=\"6\" r=\"6\" fill=\"#27C93F\" stroke=\"#1AAB29\" stroke-width=\".5\"><\/circle><\/g><\/svg><\/span><span role=\"button\" tabindex=\"0\" data-code=\"indentExistsSubqueries:\n  :breakOnSubqueries &amp; (\n      [node)   subquery &amp; [node-1) '(' &amp; [node+1) ')' &amp; [node^)  exists_condition -- the subquery\n    | [node-1) subquery &amp; [node-2) '(' &amp; [node)   ')' &amp; [node^)  exists_condition -- close parenthesis\n  )\n  -&gt; {\n    var parentNode = tuple.get(&quot;node&quot;);\n    var descendants = parentNode.descendants();\n    var prevPos = 0\n    var indentSpaces = struct.options.get(&quot;identSpaces&quot;)  \/\/ read preferences for &quot;Indent spaces&quot;\n    var alignRight = struct.options.get(&quot;alignRight&quot;)     \/\/ read preferences for &quot;Right-align query keywords&quot;\n    var baseIndent\n    if (alignRight) {\n      baseIndent = &quot;SELECT &quot;.length;  \/\/ align to SELECT keyword\n    } else {\n      baseIndent = &quot;WHERE &quot;.length;   \/\/ align to WHERE keyword\n    }\n    \/\/ result of addIndent varies based on number of &quot;Indent spaces&quot;\n    var addIndent = &quot;&quot; \n    for (j = indentSpaces - baseIndent; j < indentSpaces; j++) {\n      addIndent = addIndent + &quot; &quot;;\n    }\n    \/\/ addIndent to all nodes with existing indentation\n    for (i = 0, len = descendants.length; i < len; i++) {\n      var node = descendants.get(i);\n      var pos = node.from;\n      var nodeIndent = struct.getNewline(pos);\n      if (nodeIndent != null &amp;&amp; pos &gt; prevPos) {\n        struct.putNewline(pos, nodeIndent + addIndent);\n        prevPos = pos\n      }\n    }\n  }\n;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #C8C8C8\">indentExistsSubqueries<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  :<\/span><span style=\"color: #9CDCFE\">breakOnSubqueries<\/span><span style=\"color: #D4D4D4\"> &amp; (<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">      [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">)   <\/span><span style=\"color: #9CDCFE\">subquery<\/span><span style=\"color: #D4D4D4\"> &amp; [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">-<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #CE9178\">&#39;(&#39;<\/span><span style=\"color: #D4D4D4\"> &amp; [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">+<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #CE9178\">&#39;)&#39;<\/span><span style=\"color: #D4D4D4\"> &amp; [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">^)  <\/span><span style=\"color: #9CDCFE\">exists_condition<\/span><span style=\"color: #D4D4D4\"> -- <\/span><span style=\"color: #9CDCFE\">the<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">subquery<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">    | [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">-<\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">subquery<\/span><span style=\"color: #D4D4D4\"> &amp; [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">-<\/span><span style=\"color: #B5CEA8\">2<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #CE9178\">&#39;(&#39;<\/span><span style=\"color: #D4D4D4\"> &amp; [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">)   <\/span><span style=\"color: #CE9178\">&#39;)&#39;<\/span><span style=\"color: #D4D4D4\"> &amp; [<\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">^)  <\/span><span style=\"color: #9CDCFE\">exists_condition<\/span><span style=\"color: #D4D4D4\"> -- <\/span><span style=\"color: #9CDCFE\">close<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">parenthesis<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  )<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">  -&gt; {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    var <\/span><span style=\"color: #9CDCFE\">parentNode<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">tuple<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">get<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;node&quot;<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    var <\/span><span style=\"color: #9CDCFE\">descendants<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">parentNode<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">descendants<\/span><span style=\"color: #D4D4D4\">();<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    var <\/span><span style=\"color: #9CDCFE\">prevPos<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    var <\/span><span style=\"color: #9CDCFE\">indentSpaces<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">struct<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">options<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">get<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;identSpaces&quot;<\/span><span style=\"color: #D4D4D4\">)  <\/span><span style=\"color: #6A9955\">\/\/ read preferences for &quot;Indent spaces&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    var <\/span><span style=\"color: #9CDCFE\">alignRight<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">struct<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">options<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">get<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #CE9178\">&quot;alignRight&quot;<\/span><span style=\"color: #D4D4D4\">)     <\/span><span style=\"color: #6A9955\">\/\/ read preferences for &quot;Right-align query keywords&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    var <\/span><span style=\"color: #9CDCFE\">baseIndent<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">alignRight<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">baseIndent<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;SELECT &quot;<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">length<\/span><span style=\"color: #D4D4D4\">;  <\/span><span style=\"color: #6A9955\">\/\/ align to SELECT keyword<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    } else {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">baseIndent<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;WHERE &quot;<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">length<\/span><span style=\"color: #D4D4D4\">;   <\/span><span style=\"color: #6A9955\">\/\/ align to WHERE keyword<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ result of addIndent varies based on number of &quot;Indent spaces&quot;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    var <\/span><span style=\"color: #9CDCFE\">addIndent<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #CE9178\">&quot;&quot;<\/span><span style=\"color: #D4D4D4\"> <\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">indentSpaces<\/span><span style=\"color: #D4D4D4\"> - <\/span><span style=\"color: #9CDCFE\">baseIndent<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">indentSpaces<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">j<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">addIndent<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">addIndent<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #CE9178\">&quot; &quot;<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #6A9955\">\/\/ addIndent to all nodes with existing indentation<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #DCDCAA\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #B5CEA8\">0<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">len<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">descendants<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">length<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\"> &lt; <\/span><span style=\"color: #9CDCFE\">len<\/span><span style=\"color: #D4D4D4\">; <\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">++) {<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">descendants<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">get<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">i<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">pos<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">node<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #9CDCFE\">from<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #569CD6\">var<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">nodeIndent<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">struct<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">getNewline<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">pos<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #C586C0\">if<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">nodeIndent<\/span><span style=\"color: #D4D4D4\"> != <\/span><span style=\"color: #569CD6\">null<\/span><span style=\"color: #D4D4D4\"> &amp;&amp; <\/span><span style=\"color: #9CDCFE\">pos<\/span><span style=\"color: #D4D4D4\"> &gt; <\/span><span style=\"color: #9CDCFE\">prevPos<\/span><span style=\"color: #D4D4D4\">) {<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">struct<\/span><span style=\"color: #D4D4D4\">.<\/span><span style=\"color: #DCDCAA\">putNewline<\/span><span style=\"color: #D4D4D4\">(<\/span><span style=\"color: #9CDCFE\">pos<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #9CDCFE\">nodeIndent<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #9CDCFE\">addIndent<\/span><span style=\"color: #D4D4D4\">);<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        <\/span><span style=\"color: #9CDCFE\">prevPos<\/span><span style=\"color: #D4D4D4\"> = <\/span><span style=\"color: #9CDCFE\">pos<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">  }<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p>Here are some explanation:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>On line 3 and 4 the predicates are defined, for the <code>subquery<\/code> and the closing parenthesis <code>)<\/code> of an <code>exists_condition<\/code>.<\/li>\n\n\n\n<li>The JavaScript callback starts on line 6 and ends on line 33.<\/li>\n\n\n\n<li>The current indentation of a node (position) is read on line 27 and updated on line 29.<\/li>\n<\/ul>\n\n\n\n<p>Save the preferences to enable the new formatting rules. This is a reduced example. See the <a href=\"https:\/\/github.com\/Trivadis\/plsql-formatter-settings\">PL\/SQL &amp; SQL Formatter Settings<\/a> repository on GitHub for a more complete Arbori program.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>Arbori is the flux capacitor of SQL Developer&#8217;s Formatter. Arbori is what makes highly customized code formatting possible.<\/p>\n\n\n\n<p>The Arbori Editor and Code Outline are very useful tools for developing code snippets for an Arbori program. However, it is not easy to get started with Arbori. The information in <a href=\"https:\/\/vadimtropashko.wordpress.com\/\">Vadim Tropashko&#8217;s blog<\/a> is extensive, but it is a challenging and time-consuming read. For me, it was definitely worth it. I hope this blog post helps others to understand Arbori and its potential a bit better.<\/p>\n\n\n\n<p>Any feedback is welcome. Regarding this blog post or the PL\/SQL &amp; SQL Formatter Settings on GitHub. Thank you.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction I started using SQL Developer in 2013. Back then version 4.0 was the latest and greatest. But the capabilities of the formatter were disappointing. In 2017 Oracle released version 4.2 with a new formatter and has been improving it ever since. Version 19.2 brought us dynamic JavaScript actions within the parse-tree<span class=\"excerpt-hellip\"> [\u2026]<\/span><\/p>\n","protected":false},"author":1,"featured_media":9577,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[129,135,13,85,87],"class_list":["post-9572","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle","tag-arbori","tag-javascript","tag-plsql","tag-sql","tag-sql-developer"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Formatting Code With SQL Developer - Philipp Salvisberg&#039;s Blog<\/title>\n<meta name=\"description\" content=\"SQL Developer Version 19.2 brought us dynamic JavaScript actions within the parse-tree query language Arbori. I\u2019m really impressed with the formatting capabilities. Arbori is a hidden gem. In this blog post I explain how the formatter works and how the output can be tweaked using two simple SQL queries.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Formatting Code With SQL Developer - Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"SQL Developer Version 19.2 brought us dynamic JavaScript actions within the parse-tree query language Arbori. I\u2019m really impressed with the formatting capabilities. Arbori is a hidden gem. In this blog post I explain how the formatter works and how the output can be tweaked using two simple SQL queries.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/\" \/>\n<meta property=\"og:site_name\" content=\"Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2020-04-12T22:12:31+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2023-11-12T12:51:01+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png\" \/>\n\t<meta property=\"og:image:width\" content=\"695\" \/>\n\t<meta property=\"og:image:height\" content=\"522\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Philipp Salvisberg\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:site\" content=\"@phsalvisberg\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Philipp Salvisberg\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/\"},\"author\":{\"name\":\"Philipp Salvisberg\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"headline\":\"Formatting Code With SQL Developer\",\"datePublished\":\"2020-04-12T22:12:31+00:00\",\"dateModified\":\"2023-11-12T12:51:01+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/\"},\"wordCount\":1417,\"commentCount\":34,\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/arbori-overview.png\",\"keywords\":[\"Arbori\",\"JavaScript\",\"PL\\\/SQL\",\"SQL\",\"SQL Developer\"],\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/\",\"name\":\"Formatting Code With SQL Developer - Philipp Salvisberg&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/arbori-overview.png\",\"datePublished\":\"2020-04-12T22:12:31+00:00\",\"dateModified\":\"2023-11-12T12:51:01+00:00\",\"description\":\"SQL Developer Version 19.2 brought us dynamic JavaScript actions within the parse-tree query language Arbori. I\u2019m really impressed with the formatting capabilities. Arbori is a hidden gem. In this blog post I explain how the formatter works and how the output can be tweaked using two simple SQL queries.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/arbori-overview.png\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2020\\\/04\\\/arbori-overview.png\",\"width\":695,\"height\":522},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2020\\\/04\\\/13\\\/formatting-code-with-sql-developer\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Formatting Code With SQL Developer\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\",\"name\":\"Philipp Salvisberg&#039;s Blog\",\"description\":\"Database-centric development\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\",\"name\":\"Philipp Salvisberg\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\",\"width\":400,\"height\":400,\"caption\":\"Philipp Salvisberg\"},\"logo\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2010\\\/11\\\/phs_trivadis4.jpg\"},\"sameAs\":[\"http:\\\/\\\/www.salvis.com\\\/\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Formatting Code With SQL Developer - Philipp Salvisberg&#039;s Blog","description":"SQL Developer Version 19.2 brought us dynamic JavaScript actions within the parse-tree query language Arbori. I\u2019m really impressed with the formatting capabilities. Arbori is a hidden gem. In this blog post I explain how the formatter works and how the output can be tweaked using two simple SQL queries.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/","og_locale":"en_US","og_type":"article","og_title":"Formatting Code With SQL Developer - Philipp Salvisberg&#039;s Blog","og_description":"SQL Developer Version 19.2 brought us dynamic JavaScript actions within the parse-tree query language Arbori. I\u2019m really impressed with the formatting capabilities. Arbori is a hidden gem. In this blog post I explain how the formatter works and how the output can be tweaked using two simple SQL queries.","og_url":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/","og_site_name":"Philipp Salvisberg&#039;s Blog","article_published_time":"2020-04-12T22:12:31+00:00","article_modified_time":"2023-11-12T12:51:01+00:00","og_image":[{"width":695,"height":522,"url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png","type":"image\/png"}],"author":"Philipp Salvisberg","twitter_card":"summary_large_image","twitter_creator":"@phsalvisberg","twitter_site":"@phsalvisberg","twitter_misc":{"Written by":"Philipp Salvisberg","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#article","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/"},"author":{"name":"Philipp Salvisberg","@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"headline":"Formatting Code With SQL Developer","datePublished":"2020-04-12T22:12:31+00:00","dateModified":"2023-11-12T12:51:01+00:00","mainEntityOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/"},"wordCount":1417,"commentCount":34,"publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png","keywords":["Arbori","JavaScript","PL\/SQL","SQL","SQL Developer"],"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/","url":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/","name":"Formatting Code With SQL Developer - Philipp Salvisberg&#039;s Blog","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#primaryimage"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png","datePublished":"2020-04-12T22:12:31+00:00","dateModified":"2023-11-12T12:51:01+00:00","description":"SQL Developer Version 19.2 brought us dynamic JavaScript actions within the parse-tree query language Arbori. I\u2019m really impressed with the formatting capabilities. Arbori is a hidden gem. In this blog post I explain how the formatter works and how the output can be tweaked using two simple SQL queries.","breadcrumb":{"@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#primaryimage","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2020\/04\/arbori-overview.png","width":695,"height":522},{"@type":"BreadcrumbList","@id":"https:\/\/www.salvis.com\/blog\/2020\/04\/13\/formatting-code-with-sql-developer\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.salvis.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Formatting Code With SQL Developer"}]},{"@type":"WebSite","@id":"https:\/\/www.salvis.com\/blog\/#website","url":"https:\/\/www.salvis.com\/blog\/","name":"Philipp Salvisberg&#039;s Blog","description":"Database-centric development","publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.salvis.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515","name":"Philipp Salvisberg","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg","width":400,"height":400,"caption":"Philipp Salvisberg"},"logo":{"@id":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2010\/11\/phs_trivadis4.jpg"},"sameAs":["http:\/\/www.salvis.com\/"]}]}},"_links":{"self":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/9572","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/comments?post=9572"}],"version-history":[{"count":93,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/9572\/revisions"}],"predecessor-version":[{"id":12668,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/9572\/revisions\/12668"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media\/9577"}],"wp:attachment":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media?parent=9572"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/categories?post=9572"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/tags?post=9572"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}