{"id":12238,"date":"2023-03-05T18:30:32","date_gmt":"2023-03-05T17:30:32","guid":{"rendered":"https:\/\/www.salvis.com\/blog\/?p=12238"},"modified":"2024-06-17T11:09:14","modified_gmt":"2024-06-17T09:09:14","slug":"islandsql-episode-4-expressions-2","status":"publish","type":"post","link":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/","title":{"rendered":"IslandSQL Episode 4: Expressions"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Introduction<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">In the&nbsp;<a href=\"https:\/\/www.salvis.com\/blog\/2023\/02\/19\/islandsql-episode-3-lock-table\/\">last episode<\/a>, we extended the IslandSQL grammar covering the complete <code>lock table<\/code> statement. However, the support for expressions was very limited. It was not possible to use a date literal or <code>to_date<\/code> function to determine a partition to be locked. Time to fix that. In this episode, we will have a closer look at some SQL expressions and how to deal with the complexity of the SQL language.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The full source code is available on&nbsp;<a href=\"https:\/\/github.com\/IslandSQL\/IslandSQL\/tree\/v0.4.0\">GitHub<\/a> and the binaries are on&nbsp;<a href=\"https:\/\/central.sonatype.com\/artifact\/ch.islandsql\/islandsql\/0.4.0\">Maven Central<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"lock-table-partition\">Lock Table Partition<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To lock a table partition we use the partition name like 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);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) Lock partition by name<\/span><span role=\"button\" tabindex=\"0\" data-code=\"lock table sales partition (sales_q2_2000) in exclusive mode nowait;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> (sales_q2_2000) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Or we let the Oracle Database determine the partition by passing the values of a partition key like 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);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) Lock partition by value<\/span><span role=\"button\" tabindex=\"0\" data-code=\"lock table sales partition for (date '2000-04-01') in exclusive mode nowait;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">date<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;2000-04-01&#39;<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Both statements will lock the same partition of the table <code>sales<\/code>. The latter is IMO better since it works also with system-generated partition names, which you might use with <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/vldbg\/partition-concepts.html#GUID-C121EA1B-2725-4464-B2C9-EEDE0C3C95AB\">interval partitioning<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are a lot of possibilities to specify the date. Here is a selection of sensible and less sensible alternatives:<\/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:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">3) Lock partition by value &#8211; more variants<\/span><span role=\"button\" tabindex=\"0\" data-code=\"lock table sales partition for (to_date('2000-04', 'YYYY-MM')) in exclusive mode nowait;\nlock table sales partition for (to_date('2000-092', 'YYYY-DDD')) in exclusive mode nowait;\nlock table sales partition for (timestamp '2000-04-01 08:42:42') in exclusive mode nowait;\nlock table sales partition for (add_months(trunc(to_date('2000-12-31', 'YYYY-MM-DD'), 'YYYY'), 3)) in exclusive mode nowait;\nlock table sales partition for (date '2000-01-01' + interval '3' month) in exclusive mode nowait;\nlock table sales partition for (timestamp '2000-12-31 18:00:00' + 1\/4 + -9 * interval '1' month) in exclusive mode nowait;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> (to_date(<\/span><span style=\"color: #CE9178\">&#39;2000-04&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;YYYY-MM&#39;<\/span><span style=\"color: #D4D4D4\">)) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> (to_date(<\/span><span style=\"color: #CE9178\">&#39;2000-092&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;YYYY-DDD&#39;<\/span><span style=\"color: #D4D4D4\">)) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">timestamp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;2000-04-01 08:42:42&#39;<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> (add_months(trunc(to_date(<\/span><span style=\"color: #CE9178\">&#39;2000-12-31&#39;<\/span><span style=\"color: #D4D4D4\">, <\/span><span style=\"color: #CE9178\">&#39;YYYY-MM-DD&#39;<\/span><span style=\"color: #D4D4D4\">), <\/span><span style=\"color: #CE9178\">&#39;YYYY&#39;<\/span><span style=\"color: #D4D4D4\">), <\/span><span style=\"color: #B5CEA8\">3<\/span><span style=\"color: #D4D4D4\">)) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">date<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;2000-01-01&#39;<\/span><span style=\"color: #D4D4D4\"> + interval <\/span><span style=\"color: #CE9178\">&#39;3&#39;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">month<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> sales <\/span><span style=\"color: #569CD6\">partition<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">for<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #569CD6\">timestamp<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #CE9178\">&#39;2000-12-31 18:00:00&#39;<\/span><span style=\"color: #D4D4D4\"> + <\/span><span style=\"color: #B5CEA8\">1<\/span><span style=\"color: #D4D4D4\">\/<\/span><span style=\"color: #B5CEA8\">4<\/span><span style=\"color: #D4D4D4\"> + -<\/span><span style=\"color: #B5CEA8\">9<\/span><span style=\"color: #D4D4D4\"> * interval <\/span><span style=\"color: #CE9178\">&#39;1&#39;<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #569CD6\">month<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">All these alternatives lock the partition in the <code>sales<\/code> table where the data for 1st April 2000 is stored. Using different SQL expressions, of course.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Expressions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I mentioned in my last post that expressions are the most extensive part of the SQL grammar. However, there are ways to optimise the extent of the grammar. ANTLR 4 helps because it allows defining left recursive parts of a grammar naturally. See the expressions labelled with <code>binaryExpression<\/code> in the excerpt of the <a href=\"https:\/\/github.com\/IslandSQL\/IslandSQL\/blob\/v0.4.0\/src\/main\/antlr4\/ch\/islandsql\/grammar\/IslandSqlParser.g4#L112-L134\">parser in version 0.4.0<\/a> of the grammar below.<\/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:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">4) Expressions in v0.4.0 of IslandSQL<\/span><span role=\"button\" tabindex=\"0\" data-code=\"expression:\n      expr=STRING                                               # simpleExpressionStringLiteral\n    | expr=NUMBER                                               # simpleExpressionNumberLiteral\n    | K_DATE expr=STRING                                        # dateLiteral\n    | K_TIMESTAMP expr=STRING                                   # timestampLiteral\n    | expr=intervalExpression                                   # intervalLiteral\n    | expr=sqlName                                              # simpleExpressionName\n    | LPAR exprs+=expression (COMMA exprs+=expression)* RPAR    # expressionList\n    | expr=caseExpression                                       # caseExpr\n    | operator=unaryOperator expr=expression                    # unaryExpression\n    | expr=functionExpression                                   # functionExpr\n    | expr=AST                                                  # allColumnWildcardExpression\n    | left=expression operator=(AST|SOL) right=expression       # binaryExpression\n    | left=expression\n        (\n              operator=PLUS\n            | operator=MINUS\n            | operator=VERBAR VERBAR\n        )\n      right=expression                                          # binaryExpression\n    | left=expression operator=K_COLLATE right=expression       # binaryExpression\n    | left=expression operator=PERIOD right=expression          # binaryExpression\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\">expression<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">STRING<\/span><span style=\"color: #D4D4D4\">                                               # <\/span><span style=\"color: #9CDCFE\">simpleExpressionStringLiteral<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">NUMBER<\/span><span style=\"color: #D4D4D4\">                                               # <\/span><span style=\"color: #9CDCFE\">simpleExpressionNumberLiteral<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #4FC1FF\">K_DATE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">STRING<\/span><span style=\"color: #D4D4D4\">                                        # <\/span><span style=\"color: #9CDCFE\">dateLiteral<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #4FC1FF\">K_TIMESTAMP<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">STRING<\/span><span style=\"color: #D4D4D4\">                                   # <\/span><span style=\"color: #9CDCFE\">timestampLiteral<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">intervalExpression<\/span><span style=\"color: #D4D4D4\">                                   # <\/span><span style=\"color: #9CDCFE\">intervalLiteral<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">sqlName<\/span><span style=\"color: #D4D4D4\">                                              # <\/span><span style=\"color: #9CDCFE\">simpleExpressionName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #4FC1FF\">LPAR<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">exprs<\/span><span style=\"color: #D4D4D4\">+=<\/span><span style=\"color: #DCDCAA\">expression<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #4FC1FF\">COMMA<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">exprs<\/span><span style=\"color: #D4D4D4\">+=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\">)* <\/span><span style=\"color: #4FC1FF\">RPAR<\/span><span style=\"color: #D4D4D4\">    # <\/span><span style=\"color: #9CDCFE\">expressionList<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">caseExpression<\/span><span style=\"color: #D4D4D4\">                                       # <\/span><span style=\"color: #9CDCFE\">caseExpr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">operator<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">unaryOperator<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\">                    # <\/span><span style=\"color: #9CDCFE\">unaryExpression<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">functionExpression<\/span><span style=\"color: #D4D4D4\">                                   # <\/span><span style=\"color: #9CDCFE\">functionExpr<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">expr<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">AST<\/span><span style=\"color: #D4D4D4\">                                                  # <\/span><span style=\"color: #9CDCFE\">allColumnWildcardExpression<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">left<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">operator<\/span><span style=\"color: #D4D4D4\">=(<\/span><span style=\"color: #4FC1FF\">AST<\/span><span style=\"color: #D4D4D4\">|<\/span><span style=\"color: #4FC1FF\">SOL<\/span><span style=\"color: #D4D4D4\">) <\/span><span style=\"color: #9CDCFE\">right<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\">       # <\/span><span style=\"color: #9CDCFE\">binaryExpression<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">left<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        (<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">              <\/span><span style=\"color: #9CDCFE\">operator<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">PLUS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            | <\/span><span style=\"color: #9CDCFE\">operator<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">MINUS<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">            | <\/span><span style=\"color: #9CDCFE\">operator<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">VERBAR<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">VERBAR<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">        )<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">right<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\">                                          # <\/span><span style=\"color: #9CDCFE\">binaryExpression<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">left<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">operator<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">K_COLLATE<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">right<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\">       # <\/span><span style=\"color: #9CDCFE\">binaryExpression<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">left<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">operator<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">PERIOD<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">right<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\">          # <\/span><span style=\"color: #9CDCFE\">binaryExpression<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">In line 13 we deal with multiplication and division. Both sides of the operation allow an expression. Unlike grammars based on ANTLR 3, it is no longer necessary to <a href=\"https:\/\/theantlrguy.atlassian.net\/wiki\/spaces\/ANTLR3\/pages\/2687334\/Left-Recursion+Removal\">left-factor<\/a> this <a href=\"https:\/\/github.com\/antlr\/antlr4\/blob\/master\/doc\/left-recursion.md\">left-recursion in ANTLR 4<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">ANTLR 4 solves the ambiguity by prioritizing the alternatives in the order of the definition. As a result, multiplication\/division has a higher priority than addition\/subtraction and a lower priority than the function expression on line 11.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Left-factoring still might be helpful to optimize the runtime performance of the parser. However, it&#8217;s not necessary anymore. And I&#8217;m happy with a simpler grammar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Function Expressions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">It would be a bad idea to handle each function like <code>to_date<\/code> or <code>to_char<\/code> separately in the grammar. Why? It would be more work and we still would need a solution for custom functions. As a result, we generically implement functions. The most na\u00efve grammar definition would look like 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);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) Na\u00efve functionExpression<\/span><span role=\"button\" tabindex=\"0\" data-code=\"functionExpression:\n    name=sqlName LPAR (params+=expression (COMMA params+=expression)*)? RPAR\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\">functionExpression<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">sqlName<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #DCDCAA\">LPAR<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #9CDCFE\">params<\/span><span style=\"color: #D4D4D4\">+=<\/span><span style=\"color: #DCDCAA\">expression<\/span><span style=\"color: #D4D4D4\"> (<\/span><span style=\"color: #4FC1FF\">COMMA<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">params<\/span><span style=\"color: #D4D4D4\">+=<\/span><span style=\"color: #9CDCFE\">expression<\/span><span style=\"color: #D4D4D4\">)*)? <\/span><span style=\"color: #4FC1FF\">RPAR<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">Parameterless functions that do not allow parentheses like <code>sysdate<\/code> will be treated as&nbsp;<code>simpleExpressionName<\/code>.&nbsp; This rule handles parameterless functions that require parentheses like <code>sys_guid()<\/code>. And it can handle functions with an unbounded number of parameters.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So what&#8217;s the problem? Why do I call this definition &#8220;na\u00efve&#8221;? Because the following cases are not covered:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>named parameters, e.g. <code>dbms_utility.get_hash_value(name =&gt; 'text1', base =&gt; 0, hash_size =&gt; 16)<\/code><\/li>\n\n\n\n<li>parameter prefixes, e.g. <code>distinct<\/code> or <code>all<\/code> in <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/ANY_VALUE.html\">any_value<\/a><\/li>\n\n\n\n<li>parameter suffixes, e.g. <code>deterministic<\/code> in <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/APPROX_MEDIAN.html#GUID-F6A11DF2-121A-4057-9D0B-BF1A221B5622\">approx_median<\/a> or partition_by_clause\/order_by_clause in <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/APPROX_RANK.html\">approx_rank<\/a><\/li>\n\n\n\n<li>partial analytic clauses, e.g. <code>within group<\/code> in <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/APPROX_PERCENTILE.html\">approx_percentile<\/a><\/li>\n\n\n\n<li>analytic clauses, e.g. <code>over<\/code>&nbsp;in <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/AVG.html\">avg<\/a><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">In most cases, it makes probably sense to handle them generically. However, there are cases where it&#8217;s probably better to define dedicated grammar rules for very special functions such as <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/JSON_TABLE.html\">json_table<\/a> or <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/XMLTABLE.html\">xml_table<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You find a <a href=\"https:\/\/github.com\/IslandSQL\/IslandSQL\/blob\/v0.4.0\/src\/main\/antlr4\/ch\/islandsql\/grammar\/IslandSqlParser.g4#L190-L277\">less na\u00efve implementation on GitHub<\/a>. However, it is still incomplete. IMO a good way to assess completeness is to write tests. For function expressions, this means tests for every single function according to the <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqlrf\/Functions.html\">SQL Language Reference<\/a>. My tests currently cover <code>abs<\/code> through <code>cardinality<\/code>. The next function on the to-do list is <a href=\"https:\/\/github.com\/IslandSQL\/IslandSQL\/blob\/v0.4.0\/src\/main\/antlr4\/ch\/islandsql\/grammar\/IslandSqlParser.g4#L190-L277\">cast<\/a>, which contains the following uncovered grammar constructs:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>parameter prefix <code>multiset<\/code> for a subquery expression, which is also not yet covered<\/li>\n\n\n\n<li>parameter suffix <code>as type_name<\/code><\/li>\n\n\n\n<li>parameter suffix <code>DEFAULT&nbsp;<span class=\"italic\">return_value<\/span> ON CONVERSION ERROR<\/code><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Shall we define a dedicated grammar rule for the <code>cast<\/code> function? I guess yes. However, I&#8217;d probably implement <code>multiset<\/code> as a unary operator and the <code>subquery<\/code> as part of the <code>expression<\/code> rule. For that, we need to implement the grammar for the complete <code>select<\/code> statement.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Knowing the Scope and the Limitations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A typical question I get is &#8220;Why are you writing a SQL grammar? There are already some available for ANTLR 4, right?&#8221;. That&#8217;s an excellent question. The ANLTR organisation on GitHub manages a repository with example grammars. You find the ones for SQL <a href=\"https:\/\/github.com\/antlr\/grammars-v4\/tree\/master\/sql\">here<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Most of the 3rd party grammars cover just a (large) subset of the underlying languages. They define what they cover in ANTLR or by EBNF. However, they often do not define which versions they cover and they do not define what they don&#8217;t cover. As a result, you have to try if the grammar is sufficient for your use case. Furthermore, you have to assess if it is sufficient for future use cases and if it will cover the changes in newer versions. And of course, you have to decide if you are ready to extend\/fix the grammar in areas where it does not meet your expectations. You will have to maintain a fork. This can become painful, especially if the grammar contains a lot of stuff you are not interested in and if the existing test suites are incomplete.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Furthermore, I&#8217;m not aware of an open-sourced grammar that covers the relevant portions for the Oracle Database and PostgreSQL. Yes, the goal is that IslandSQL supports the recent versions of both dialects as if they were a single dialect.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We develop the grammar iteratively. As a result, there are a lot of interim limitations like the one mentioned regarding the <code>cast<\/code> function.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">SQL*Plus Substitution Variables<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">However, some limitations are supposed to be permanent. Like the one for substitution variables. <a href=\"https:\/\/docs.oracle.com\/en\/database\/oracle\/oracle-database\/21\/sqpug\/using-substitution-variables-sqlplus.html\">Substitution variables<\/a> can contain arbitrary text. They are replaced before the execution of a script. The IslandSQL grammar provides limited support for substitution variables. They can be used in places where a <code>sqlName<\/code> is valid. This is basically everywhere you can use an <code>expression<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here&#8217;s an example of a supported usage:<\/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:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">6) Example of supported usage of substitution variables<\/span><span role=\"button\" tabindex=\"0\" data-code=\"lock table &amp;table_name in exclusive mode wait &seconds;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> &amp;table_name <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> exclusive mode wait &amp;<\/span><span style=\"color: #569CD6\">seconds<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">And here&#8217;s an example of an unsupported usage:<\/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:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">7) Example of unsupported usage of a substitution variable<\/span><span role=\"button\" tabindex=\"0\" data-code=\"lock table dept in &amp;lock_mode mode nowait;\" style=\"color:#D4D4D4;display:none\" aria-label=\"Copy\" class=\"code-block-pro-copy-button\"><svg xmlns=\"http:\/\/www.w3.org\/2000\/svg\" style=\"width:24px;height:24px\" fill=\"none\" viewBox=\"0 0 24 24\" stroke=\"currentColor\" stroke-width=\"2\"><path class=\"with-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2m-6 9l2 2 4-4\"><\/path><path class=\"without-check\" stroke-linecap=\"round\" stroke-linejoin=\"round\" d=\"M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2M9 5a2 2 0 002 2h2a2 2 0 002-2M9 5a2 2 0 012-2h2a2 2 0 012 2\"><\/path><\/svg><\/span><pre class=\"shiki dark-plus\" style=\"background-color: #1E1E1E\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color: #D4D4D4\">lock <\/span><span style=\"color: #569CD6\">table<\/span><span style=\"color: #D4D4D4\"> dept <\/span><span style=\"color: #569CD6\">in<\/span><span style=\"color: #D4D4D4\"> &amp;lock_mode mode <\/span><span style=\"color: #569CD6\">nowait<\/span><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">The grammar expects certain keywords at the position of <code>&amp;lock_mode<\/code>. Here&#8217;s the <a href=\"https:\/\/github.com\/IslandSQL\/IslandSQL\/blob\/v0.4.0\/src\/main\/antlr4\/ch\/islandsql\/grammar\/IslandSqlParser.g4#L61-L89\">excerpt<\/a> of the grammar that should make that clear:<\/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:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">8) Exerpt of IslandSqlParser.g4 &#8211; lock modes<\/span><span role=\"button\" tabindex=\"0\" data-code=\"lockTableStatementUnterminated:\n    K_LOCK K_TABLE objects+=lockTableObject (COMMA objects+=lockTableObject)*\n        K_IN lockmode=lockMode K_MODE waitOption=lockTableWaitOption?\n;\n\nlockMode:\n      K_ROW K_SHARE                 # rowShareLockMode\n    | K_ROW K_EXCLUSIVE             # rowExclusiveLockMode\n    | K_SHARE K_UPDATE              # shareUpdateLockMode\n    | K_SHARE                       # shareLockMode\n    | K_SHARE K_ROW K_EXCLUSIVE     # shareRowExclusiveLockMode\n    | K_EXCLUSIVE                   # exclusiveLockMode\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: #D4D4D4\">lockTableStatementUnterminated:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    K_LOCK K_TABLE objects+=lockTableObject (COMMA objects+=lockTableObject)*<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">        K_IN lockmode=lockMode K_MODE waitOption=lockTableWaitOption?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">lockMode:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      K_ROW K_SHARE                 # rowShareLockMode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | K_ROW K_EXCLUSIVE             # rowExclusiveLockMode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | K_SHARE K_UPDATE              # shareUpdateLockMode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | K_SHARE                       # shareLockMode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | K_SHARE K_ROW K_EXCLUSIVE     # shareRowExclusiveLockMode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | K_EXCLUSIVE                   # exclusiveLockMode<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">And the next <a href=\"https:\/\/github.com\/IslandSQL\/IslandSQL\/blob\/v0.4.0\/src\/main\/antlr4\/ch\/islandsql\/grammar\/IslandSqlParser.g4#L402-L415\">excerpt<\/a> shows how substitution variables are defined in the grammar.<\/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:flex;align-items:center;padding:10px 0px 10px 16px;margin-bottom:-2px;width:100%;text-align:left;background-color:#2b2b2b;color:#c7c7c7\">9) Exerpt of IslandSqlParser.g4 &#8211; substitution variables<\/span><span role=\"button\" tabindex=\"0\" data-code=\"sqlName:\n      unquotedId\n    | QUOTED_ID\n    | substitionVariable\n;\n\nsubstitionVariable:\n    AMP AMP? name=substitionVariableName period=PERIOD?\n;\n\nsubstitionVariableName:\n      NUMBER\n    | sqlName\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\">sqlName<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #9CDCFE\">unquotedId<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #4FC1FF\">QUOTED_ID<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">substitionVariable<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #C8C8C8\">substitionVariable<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line cbp-line-highlight\"><span style=\"color: #D4D4D4\">    <\/span><span style=\"color: #4FC1FF\">AMP<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #4FC1FF\">AMP<\/span><span style=\"color: #D4D4D4\">? <\/span><span style=\"color: #9CDCFE\">name<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #9CDCFE\">substitionVariableName<\/span><span style=\"color: #D4D4D4\"> <\/span><span style=\"color: #9CDCFE\">period<\/span><span style=\"color: #D4D4D4\">=<\/span><span style=\"color: #4FC1FF\">PERIOD<\/span><span style=\"color: #D4D4D4\">?<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span>\n<span class=\"line\"><\/span>\n<span class=\"line\"><span style=\"color: #9CDCFE\">substitionVariableName<\/span><span style=\"color: #D4D4D4\">:<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">      <\/span><span style=\"color: #4FC1FF\">NUMBER<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">    | <\/span><span style=\"color: #9CDCFE\">sqlName<\/span><\/span>\n<span class=\"line\"><span style=\"color: #D4D4D4\">;<\/span><\/span><\/code><\/pre><\/div>\n\n\n\n<p class=\"wp-block-paragraph\">A substitution variable starts with one or two <code>&amp;<\/code>. The name can be either a <code>NUMBER<\/code> (like <code>1<\/code>) or a <code>sqlName<\/code> (like <code>tableName<\/code>). And a substitution variable can optionally end on <code>.<\/code>. That&#8217;s it. This way we can provide limited support for SQL*Plus substitution variables.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"outlook\">Outlook<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The grammar evolves quite nicely. However, expressions are still incomplete. This will be covered with the full support of the <code>select<\/code>statement.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As I&#8217;m sure you&#8217;ve already found out for yourself, the version of the grammar matches the episodes in this blog post series. And these are the planned versions of IslandSQL with their main features:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>v0.5.0: Fully parse <code>select<\/code> statement, complete expressions and conditions<\/li>\n\n\n\n<li>v0.6.0: Fully parse remaining DML statements (<code>call<\/code>, <code>delete<\/code>, <code>explain plan<\/code>, <code>insert<\/code>, <code>merge<\/code>, <code>update<\/code>)<\/li>\n\n\n\n<li>v0.7.0: PostgreSQL syntax compatibility of implemented statements<\/li>\n\n\n\n<li>v0.8.0: Fully parse PL\/SQL block<\/li>\n\n\n\n<li>v0.9.0: Fully parse <code>create<\/code> statements of the Oracle Database (<code>function<\/code>, <code>package<\/code>, <code>procedure<\/code>, <code>trigger<\/code>, <code>type<\/code>, <code>view<\/code>)<\/li>\n\n\n\n<li>v0.10.0: pgPL\/SQL syntax compatibility (<code>sql<\/code> and <code>plpgsql<\/code> language in <code>create function<\/code>, <code>create procedure<\/code>, <code>create trigger<\/code>&nbsp;and <code>do<\/code>)<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">And after episode 10 the fun begins. We can start to provide value for database developers and others. A linter is one option. But there is more. Stay tuned.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In the&nbsp;last episode, we extended the IslandSQL grammar covering the complete lock table statement. However, the support for expressions was very limited. It was not possible to use a date literal or to_date function to determine a partition to be locked. Time to fix that. In this episode, we will have<span class=\"excerpt-hellip\"> [\u2026]<\/span><\/p>\n","protected":false},"author":1,"featured_media":12259,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5],"tags":[139,86,137,85],"class_list":["post-12238","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle","tag-antlr","tag-code-analysis","tag-islandsql","tag-sql"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.8 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>IslandSQL Episode 4: Expressions - Philipp Salvisberg&#039;s Blog<\/title>\n<meta name=\"description\" content=\"In this blog post we extend the support for expressions. We take a closer look at functions and how to support them with minimal effort.\" \/>\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\/2023\/03\/05\/islandsql-episode-4-expressions-2\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"IslandSQL Episode 4: Expressions - Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"og:description\" content=\"In this blog post we extend the support for expressions. We take a closer look at functions and how to support them with minimal effort.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/\" \/>\n<meta property=\"og:site_name\" content=\"Philipp Salvisberg&#039;s Blog\" \/>\n<meta property=\"article:published_time\" content=\"2023-03-05T17:30:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2024-06-17T09:09:14+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/03\/IslandSQL4.png\" \/>\n\t<meta property=\"og:image:width\" content=\"500\" \/>\n\t<meta property=\"og:image:height\" content=\"500\" \/>\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=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/\"},\"author\":{\"name\":\"Philipp Salvisberg\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"headline\":\"IslandSQL Episode 4: Expressions\",\"datePublished\":\"2023-03-05T17:30:32+00:00\",\"dateModified\":\"2024-06-17T09:09:14+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/\"},\"wordCount\":1243,\"commentCount\":2,\"publisher\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#\\\/schema\\\/person\\\/34352245c48678b1a5a05d4bc1339515\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/IslandSQL4.png\",\"keywords\":[\"ANTLR\",\"Code Analysis\",\"IslandSQL\",\"SQL\"],\"articleSection\":[\"Oracle\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/\",\"name\":\"IslandSQL Episode 4: Expressions - Philipp Salvisberg&#039;s Blog\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/IslandSQL4.png\",\"datePublished\":\"2023-03-05T17:30:32+00:00\",\"dateModified\":\"2024-06-17T09:09:14+00:00\",\"description\":\"In this blog post we extend the support for expressions. We take a closer look at functions and how to support them with minimal effort.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/IslandSQL4.png\",\"contentUrl\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/03\\\/IslandSQL4.png\",\"width\":500,\"height\":500},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/2023\\\/03\\\/05\\\/islandsql-episode-4-expressions-2\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.salvis.com\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"IslandSQL Episode 4: Expressions\"}]},{\"@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":"IslandSQL Episode 4: Expressions - Philipp Salvisberg&#039;s Blog","description":"In this blog post we extend the support for expressions. We take a closer look at functions and how to support them with minimal effort.","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\/2023\/03\/05\/islandsql-episode-4-expressions-2\/","og_locale":"en_US","og_type":"article","og_title":"IslandSQL Episode 4: Expressions - Philipp Salvisberg&#039;s Blog","og_description":"In this blog post we extend the support for expressions. We take a closer look at functions and how to support them with minimal effort.","og_url":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/","og_site_name":"Philipp Salvisberg&#039;s Blog","article_published_time":"2023-03-05T17:30:32+00:00","article_modified_time":"2024-06-17T09:09:14+00:00","og_image":[{"width":500,"height":500,"url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/03\/IslandSQL4.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":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#article","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/"},"author":{"name":"Philipp Salvisberg","@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"headline":"IslandSQL Episode 4: Expressions","datePublished":"2023-03-05T17:30:32+00:00","dateModified":"2024-06-17T09:09:14+00:00","mainEntityOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/"},"wordCount":1243,"commentCount":2,"publisher":{"@id":"https:\/\/www.salvis.com\/blog\/#\/schema\/person\/34352245c48678b1a5a05d4bc1339515"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/03\/IslandSQL4.png","keywords":["ANTLR","Code Analysis","IslandSQL","SQL"],"articleSection":["Oracle"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/","url":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/","name":"IslandSQL Episode 4: Expressions - Philipp Salvisberg&#039;s Blog","isPartOf":{"@id":"https:\/\/www.salvis.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#primaryimage"},"image":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#primaryimage"},"thumbnailUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/03\/IslandSQL4.png","datePublished":"2023-03-05T17:30:32+00:00","dateModified":"2024-06-17T09:09:14+00:00","description":"In this blog post we extend the support for expressions. We take a closer look at functions and how to support them with minimal effort.","breadcrumb":{"@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#primaryimage","url":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/03\/IslandSQL4.png","contentUrl":"https:\/\/www.salvis.com\/blog\/wp-content\/uploads\/2023\/03\/IslandSQL4.png","width":500,"height":500},{"@type":"BreadcrumbList","@id":"https:\/\/www.salvis.com\/blog\/2023\/03\/05\/islandsql-episode-4-expressions-2\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.salvis.com\/blog\/"},{"@type":"ListItem","position":2,"name":"IslandSQL Episode 4: Expressions"}]},{"@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\/12238","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=12238"}],"version-history":[{"count":35,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/12238\/revisions"}],"predecessor-version":[{"id":13428,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/posts\/12238\/revisions\/13428"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media\/12259"}],"wp:attachment":[{"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/media?parent=12238"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/categories?post=12238"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.salvis.com\/blog\/wp-json\/wp\/v2\/tags?post=12238"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}