From 36894e63fb84ee6a8179009a99c5023a6994b533 Mon Sep 17 00:00:00 2001 From: kgs <kgs@dcc99617-32d9-48b4-a31d-7c20da2025e4> Date: Fri, 8 May 2009 19:54:37 +0000 Subject: [PATCH] setting up guides sync git-svn-id: svn://svn.open-ils.org/ILS/trunk@13102 dcc99617-32d9-48b4-a31d-7c20da2025e4 --- docs/Guides/compugrammar.xpr | 259 +++++++++++++++ docs/Guides/grammar.html | 151 +++++++++ docs/Guides/grammar.xml | 291 +++++++++++++++++ docs/Guides/grammar2.html | 56 ++++ docs/Guides/grammar2.pdf | Bin 0 -> 15319 bytes docs/Guides/grammar2.xml | 227 +++++++++++++ docs/Guides/grammar3.xml | 755 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 1739 insertions(+) create mode 100644 docs/Guides/compugrammar.xpr create mode 100644 docs/Guides/grammar.html create mode 100644 docs/Guides/grammar.xml create mode 100644 docs/Guides/grammar2.html create mode 100644 docs/Guides/grammar2.pdf create mode 100644 docs/Guides/grammar2.xml create mode 100644 docs/Guides/grammar3.xml diff --git a/docs/Guides/compugrammar.xpr b/docs/Guides/compugrammar.xpr new file mode 100644 index 0000000000..6235c751e1 --- /dev/null +++ b/docs/Guides/compugrammar.xpr @@ -0,0 +1,259 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project> + <meta> + <filters directoryPatterns="CVS" filePatterns="" + positiveFilePatterns="" showHiddenFiles="false"/> + <options/> + </meta> + <projectTree name="compugrammar.xpr"> + <folder name="css"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/css/sample1.css"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/css/sample1.xhtml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/css/sample2.css"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/css/sample2.xhtml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/css/sample3.css"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/css/sample3.xhtml" + /> + </folder> + <folder name="fo"> + <folder name="Basic Font Attributes"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Basic%20Font%20Attributes/bold.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Basic%20Font%20Attributes/bold.xml" + /> + </folder> + <folder name="Block Properties"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Block%20Properties/borders.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Block%20Properties/borders.xml" + /> + </folder> + <folder name="Character Sets"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Character%20Sets/adobe-standard.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Character%20Sets/adobe-standard.xml" + /> + </folder> + <folder name="Extended Font Attributes"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Extended%20Font%20Attributes/aspect.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Extended%20Font%20Attributes/aspect.xml" + /> + </folder> + <folder name="Invoice"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Invoice/invoice.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Invoice/invoice.xsd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Invoice/invoice.xsl" + /> + </folder> + <folder name="Miscellaneous"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Miscellaneous/fontAttributes.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Miscellaneous/helloWorld.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Miscellaneous/leaders.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Miscellaneous/pageLayout.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Miscellaneous/table.fo" + /> + </folder> + <folder name="Paragraph Attributes"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Paragraph%20Attributes/pagebreak.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Paragraph%20Attributes/pagebreak.xml" + /> + </folder> + <folder name="Text Block Attributes"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Text%20Block%20Attributes/align.fo"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/Text%20Block%20Attributes/align.xml" + /> + </folder> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/fo/macro.xsl" + /> + </folder> + <folder name="nvdl"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/nvdl/xhtml-xforms.nvdl"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/nvdl/xhtml-xforms.xml" + /> + </folder> + <folder name="relaxng"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/relaxng/personal.rnc"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/relaxng/personal.rng"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/relaxng/personal.xml" + /> + </folder> + <folder name="schematron"> + <folder name="1.5"> + <folder name="attributes"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/followed-bad.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/followed-good.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/followed.dtd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/followed.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/length-bad.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/length-bad1.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/length-bad2.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/length-good.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/length.dtd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/length.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/name-bad.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/name.dtd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/name.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/present-bad.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/present.dtd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/present.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/required-bad1.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/required-bad2.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/required-good.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/required.dtd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/attributes/required.sch" + /> + </folder> + <folder name="author"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/author/author.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/author/source1.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/author/source2.xml" + /> + </folder> + <folder name="paragraph"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/paragraph/paragraph.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/paragraph/source1.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/paragraph/source2.xml" + /> + </folder> + <folder name="percent"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/percent/percent-bad1.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/percent/percent-bad2.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/percent/percent-good.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/percent/percent.dtd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/percent/percent.sch" + /> + </folder> + <folder name="po"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/po/po-bad.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/po/po-schema.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/po/po.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/po/po.xsd" + /> + </folder> + <folder name="tournament"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/tournament/tournament-schema.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/tournament/Tournament.rng"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/tournament/Tournament.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/1.5/tournament/Tournament.xsd" + /> + </folder> + </folder> + <folder name="iso"> + <folder name="tournament"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/iso/tournament/tournament-schema.sch"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/iso/tournament/Tournament.rng"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/iso/tournament/Tournament.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/schematron/iso/tournament/Tournament.xsd" + /> + </folder> + </folder> + </folder> + <folder name="svg"> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/svg/batik3D.svg"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/svg/sales.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/svg/sales.xsl" + /> + </folder> + <folder + path="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/dita/"/> + <folder + path="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/docbook/"/> + <folder + path="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/ooxml/"/> + <folder + path="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/tei/"/> + <folder + path="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/xhtml/"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/personal-schema.css"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/personal-schema.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/personal.css"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/personal.dtd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/personal.xml"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/personal.xsd"/> + <file + name="../../Documents%20and%20Settings/KAREN%20SCHNEIDER/OxygenXMLAuthor/samples/personal.xsl" + /> + </projectTree> +</project> diff --git a/docs/Guides/grammar.html b/docs/Guides/grammar.html new file mode 100644 index 0000000000..36587da957 --- /dev/null +++ b/docs/Guides/grammar.html @@ -0,0 +1,151 @@ +<html><head><meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><title>Grammar of JSON Queries</title><meta name="generator" content="DocBook XSL Stylesheets V1.74.3"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" lang="en"><div class="titlepage"><div><div><h1 class="title"><a name="id1165551"></a>Grammar of JSON Queries</h1></div><div><div class="author"><h3 class="author"><span class="firstname">Scott</span> <span class="surname">McKellar</span></h3></div></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#id1165745">Introduction</a></span></dt><dt><span class="sect1"><a href="#id1165792">Primitives</a></span></dt><dt><span class="sect1"><a href="#id1165795">Query</a></span></dt></dl></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1165745"></a>Introduction</h2></div></div></div><p> + The format of this grammar approximates Extended Backus-Naur notation. However it + is intended as input to human beings, not to parser generators such as Lex or + Yacc. Do not expect formal rigor. Sometimes narrative text will explain things + that are clumsy to express in formal notation. More often, the text will restate + or summarize the formal productions. + </p><p> + Conventions: + </p><div class="orderedlist"><ol type="1"><li> + The grammar is a series of productions. + </li><li> + A production consists of a name, followed by "::=", followed by a + definition for the name. The name identifies a grammatical construct that can + appear on the right side of another production. + </li><li> + Literals (including punctuation) are enclosed in single quotes, or in double + quotes if case is not significant. + </li><li> + A single quotation mark within a literal is escaped with a preceding backslash. + </li><li> + If a construct can be defined more than one way, then the alternatives may appear + in separate productions; or, they may appear in the same production, separated by + pipe symbols. The choice between these representations is of only cosmetic + significance. + </li><li> + A construct enclosed within square brackets is optional. + </li><li> + A construct enclosed within curly braces may be repeated zero or more times. + </li><li> + JSON allows arbitrary white space between tokens. To avoid ugly clutter, this + grammar ignores the optional white space. + </li><li> + In many cases a production defines a JSON object, i.e. a list of name-value pairs, + separated by commas. Since the order of these name/value pairs is not significant, + the grammar will not try to show all the possible sequences. In general it will + present the required pairs first, if any, followed by any optional elements. + </li></ol></div><p> + Since both EBNF and JSON use curly braces and square brackets, pay close attention to + whether these characters are in single quotes. If they're in single quotes, they are + literal elements of the JSON notation. Otherwise they are elements of the EBNF notation. + </p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1165792"></a>Primitives</h2></div></div></div><p> + We'll start by defining some primitives, to get them out of the way. They're + mostly just what you would expect. + </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[1]</td><td align="right" valign="top" width="10%"> + string + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + '”' chars '”' + </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[2]</td><td align="right" valign="top" width="10%"> + chars + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + any valid sequence of UTF-8 characters, with certain special characters + escaped according to JSON rules + </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[3]</td><td align="right" valign="top" width="10%"> + integer_literal + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + [ sign ] digit { digit } + </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[4]</td><td align="right" valign="top" width="10%"> + sign + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + '+' | '-' + </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[5]</td><td align="right" valign="top" width="10%"> + digit + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[6]</td><td align="right" valign="top" width="10%"> + integer_string + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + '”' integer_literal '”' + </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[7]</td><td align="right" valign="top" width="10%"> + integer + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + integer_literal | integer_string + </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[8]</td><td align="right" valign="top" width="10%"> + number + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + any valid character sequence that is numeric according to JSON rules + </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> + When json_query requires an integral value, it will usually accept a quoted string and + convert it to an integer by brute force – to zero if necessary. Likewise it may + truncate a floating point number to an integral value. Scientific notation will be + accepted but may not give the intended results. + </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[9]</td><td align="right" valign="top" width="10%"> + boolean + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + 'true' | 'false' | string | number + </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> + The preferred way to encode a boolean is with the JSON reserved word true or false, + in lower case without quotation marks. The string “<code class="literal">trueK</code>”, in + upper, lower, or mixed case, is another way to encode true. Any other string + evaluates to false. + </p><p> + As an accommodation to perl, numbers may be used as booleans. A numeric value of 1 + means true, and any other numeric value means false. + </p><p> + Any other valid JSON value, such as an array, will be accepted as a boolean but interpreted + as false. + </p><p> + The last couple of primitives aren't really very primitive, but we introduce them here + for convenience: + </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[10]</td><td align="right" valign="top" width="10%"> + class_name + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + string + </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> + A class_name is a special case of a string: the name of a class as defined + by the IDL. The class may refer either to a database table or to a + source_definition, which is a subquery. + </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[11]</td><td align="right" valign="top" width="10%"> + field_name + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + string + </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> + A field_name is another special case of a string: the name of a non-virtual + field as defined by the IDL. A field_name is also a column name for the + table corresponding to the relevant class. + </p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="id1165795"></a>Query</h2></div></div></div><p> + The following production applies not only to the main query but also to + most subqueries. + </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[12]</td><td align="right" valign="top" width="10%"> + query + </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> + '{'<br> + '”from”' ':' from_list<br> + [ ',' '”select”' ':' select_list ]<br> + [ ',' '”where”' ':' where_condition ]<br> + [ ',' '”having”' ':' where_condition ]<br> + [ ',' '”order_by”' ':' order_by_list ]<br> + [ ',' '”limit”' ':' integer ]<br> + [ ',' '”offset”' ':' integer ]<br> + [ ',' '”distinct”' ':' boolean ]<br> + [ ',' '”no_i18n”' ':' boolean ]<br> + '}' + </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> + Except for the <code class="literal">“distinct”</code> and <code class="literal">“no_i18n”</code> + entries, each name/value pair represents a major clause of the SELECT statement. + The name/value pairs may appear in any order. + </p><p> + There is no name/value pair for the GROUP BY clause, because json_query + generates it automatically according to information encoded elsewhere. + </p><p> + The <code class="literal">“distinct”</code> entry, if present and true, tells json_query + that it may have to create a GROUP BY clause. If not present, it defaults to false. + </p><p> + The <code class="literal">“no_i18n”</code> entry, if present and true, tells json_query to + suppress internationalization. If not present, it defaults to false. (Note that + <code class="literal">“no_i18n”</code> contains the digit one, not the letter ell.) + </p><p> + The values for <code class="literal">“limit”</code> and <code class="literal">“offset”</code> + provide the arguments of the LIMIT and OFFSET clauses, respectively, of the + SQL statement. Each value should be non-negative, if present, or else the + SQL won't work. + </p></div></div></body></html> diff --git a/docs/Guides/grammar.xml b/docs/Guides/grammar.xml new file mode 100644 index 0000000000..2601682f90 --- /dev/null +++ b/docs/Guides/grammar.xml @@ -0,0 +1,291 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> + +<article xmlns="http://docbook.org/ns/docbook"> + + <artheader> + <title>Grammar of JSON Queries</title> + <author> + <firstname>Scott</firstname> + <surname>McKellar</surname> + </author> + </artheader> + + <sect1><title>Introduction</title> + <para> + The format of this grammar approximates Extended Backus-Naur notation. However it + is intended as input to human beings, not to parser generators such as Lex or + Yacc. Do not expect formal rigor. Sometimes narrative text will explain things + that are clumsy to express in formal notation. More often, the text will restate + or summarize the formal productions. + </para> + <para> + Conventions: + </para> + <orderedlist> + <listitem> + The grammar is a series of productions. + </listitem> + <listitem> + A production consists of a name, followed by "::=", followed by a + definition for the name. The name identifies a grammatical construct that can + appear on the right side of another production. + </listitem> + <listitem> + Literals (including punctuation) are enclosed in single quotes, or in double + quotes if case is not significant. + </listitem> + <listitem> + A single quotation mark within a literal is escaped with a preceding backslash. + </listitem> + <listitem> + If a construct can be defined more than one way, then the alternatives may appear + in separate productions; or, they may appear in the same production, separated by + pipe symbols. The choice between these representations is of only cosmetic + significance. + </listitem> + <listitem> + A construct enclosed within square brackets is optional. + </listitem> + <listitem> + A construct enclosed within curly braces may be repeated zero or more times. + </listitem> + <listitem> + JSON allows arbitrary white space between tokens. To avoid ugly clutter, this + grammar ignores the optional white space. + </listitem> + <listitem> + In many cases a production defines a JSON object, i.e. a list of name-value pairs, + separated by commas. Since the order of these name/value pairs is not significant, + the grammar will not try to show all the possible sequences. In general it will + present the required pairs first, if any, followed by any optional elements. + </listitem> + </orderedlist> + + <para> + Since both EBNF and JSON use curly braces and square brackets, pay close attention to + whether these characters are in single quotes. If they're in single quotes, they are + literal elements of the JSON notation. Otherwise they are elements of the EBNF notation. + </para> + </sect1> + + <sect1><title>Primitives</title> + <para> + We'll start by defining some primitives, to get them out of the way. They're + mostly just what you would expect. + </para> + + <productionset> + <production> + <lhs> + string + </lhs> + <rhs> + 'â' chars 'â' + </rhs> + </production> + + <production> + <lhs> + chars + </lhs> + <rhs> + any valid sequence of UTF-8 characters, with certain special characters + escaped according to JSON rules + </rhs> + </production> + + <production> + <lhs> + integer_literal + </lhs> + <rhs> + [ sign ] digit { digit } + </rhs> + </production> + + <production> + <lhs> + sign + </lhs> + <rhs> + '+' | '-' + </rhs> + </production> + + <production> + <lhs> + digit + </lhs> + digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + <rhs> + </rhs> + </production> + + <production> + <lhs> + integer_string + </lhs> + <rhs> + 'â' integer_literal 'â' + </rhs> + </production> + + <production> + <lhs> + integer + </lhs> + <rhs> + integer_literal | integer_string + </rhs> + </production> + + <production> + <lhs> + number + </lhs> + <rhs> + any valid character sequence that is numeric according to JSON rules + </rhs> + </production> + + </productionset> + + <para> + When json_query requires an integral value, it will usually accept a quoted string and + convert it to an integer by brute force â to zero if necessary. Likewise it may + truncate a floating point number to an integral value. Scientific notation will be + accepted but may not give the intended results. + </para> + + <productionset> + + <production> + <lhs> + boolean + </lhs> + <rhs> + 'true' | 'false' | string | number + </rhs> + </production> + + </productionset> + + <para> + The preferred way to encode a boolean is with the JSON reserved word true or false, + in lower case without quotation marks. The string â<literal>true</literal>â, in + upper, lower, or mixed case, is another way to encode true. Any other string + evaluates to false. + </para> + <para> + As an accommodation to perl, numbers may be used as booleans. A numeric value of 1 + means true, and any other numeric value means false. + </para> + <para> + Any other valid JSON value, such as an array, will be accepted as a boolean but interpreted + as false. + </para> + <para> + The last couple of primitives aren't really very primitive, but we introduce them here + for convenience: + </para> + + <productionset> + + <production> + <lhs> + class_name + </lhs> + <rhs> + string + </rhs> + </production> + + </productionset> + + <para> + A class_name is a special case of a string: the name of a class as defined + by the IDL. The class may refer either to a database table or to a + source_definition, which is a subquery. + </para> + + <productionset> + + <production> + <lhs> + field_name + </lhs> + <rhs> + string + </rhs> + </production> + + </productionset> + + <para> + A field_name is another special case of a string: the name of a non-virtual + field as defined by the IDL. A field_name is also a column name for the + table corresponding to the relevant class. + </para> + + </sect1> + + <sect1><title>Query</title> + + <para> + The following production applies not only to the main query but also to + most subqueries. + </para> + + <productionset> + + <production> + <lhs> + query + </lhs> + <rhs> + '{'<sbr/> + 'âfromâ' ':' from_list<sbr/> + [ ',' 'âselectâ' ':' select_list ]<sbr/> + [ ',' 'âwhereâ' ':' where_condition ]<sbr/> + [ ',' 'âhavingâ' ':' where_condition ]<sbr/> + [ ',' 'âorder_byâ' ':' order_by_list ]<sbr/> + [ ',' 'âlimitâ' ':' integer ]<sbr/> + [ ',' 'âoffsetâ' ':' integer ]<sbr/> + [ ',' 'âdistinctâ' ':' boolean ]<sbr/> + [ ',' 'âno_i18nâ' ':' boolean ]<sbr/> + '}' + </rhs> + </production> + + </productionset> + + <para> + Except for the <literal>âdistinctâ</literal> and <literal>âno_i18nâ</literal> + entries, each name/value pair represents a major clause of the SELECT statement. + The name/value pairs may appear in any order. + </para> + <para> + There is no name/value pair for the GROUP BY clause, because json_query + generates it automatically according to information encoded elsewhere. + </para> + <para> + The <literal>âdistinctâ</literal> entry, if present and true, tells json_query + that it may have to create a GROUP BY clause. If not present, it defaults to false. + </para> + <para> + The <literal>âno_i18nâ</literal> entry, if present and true, tells json_query to + suppress internationalization. If not present, it defaults to false. (Note that + <literal>âno_i18nâ</literal> contains the digit one, not the letter ell.) + </para> + <para> + The values for <literal>âlimitâ</literal> and <literal>âoffsetâ</literal> + provide the arguments of the LIMIT and OFFSET clauses, respectively, of the + SQL statement. Each value should be non-negative, if present, or else the + SQL won't work. + </para> + + </sect1> + +</article> diff --git a/docs/Guides/grammar2.html b/docs/Guides/grammar2.html new file mode 100644 index 0000000000..163431bf89 --- /dev/null +++ b/docs/Guides/grammar2.html @@ -0,0 +1,56 @@ +<html><head> + <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> + <title>Grammar of JSON Queries</title><meta name="generator" content="DocBook XSL-NS Stylesheets V1.74.3-pre"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="article" lang="en"><div class="titlepage"><div><div><h2 class="title"><a name="d0e1"></a>Grammar of JSON Queries</h2></div></div><hr></div><div class="toc"><p><b>Table of Contents</b></p><dl><dt><span class="sect1"><a href="#d0e28">Introduction</a></span></dt><dt><span class="sect1"><a href="#d0e65">Primitives</a></span></dt><dt><span class="sect1"><a href="#d0e194">Query</a></span></dt></dl></div><p> + <span class="author"><span class="firstname">Scott</span> <span class="surname">McKellar</span></span> + </p><p> + + </p><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e28"></a>Introduction</h2></div></div></div><p> The format of this grammar approximates Extended Backus-Naur notation. However it is + intended as input to human beings, not to parser generators such as Lex or Yacc. Do not + expect formal rigor. Sometimes narrative text will explain things that are clumsy to + express in formal notation. More often, the text will restate or summarize the formal + productions. </p><p> Conventions: </p><div class="orderedlist"><ol type="1"><li><p>The grammar is a series of productions.</p></li><li><p>A production consists of a name, followed by "::=", followed by a definition + for the name. The name identifies a grammatical construct that can appear on the + right side of another production.</p></li><li><p>Literals (including punctuation) are enclosed in 'single quotes', or in + "double quotes" if case is not significant.</p></li><li><p>A single quotation mark within a literal is escaped with a preceding + backslash: 'dog\'s tail'.</p></li><li><p>If a construct can be defined more than one way, then the alternatives may + appear in separate productions; or, they may appear in the same production, + separated by pipe symbols. The choice between these representations is of only + cosmetic significance.</p></li><li><p>A construct enclosed within square brackets is optional.</p></li><li><p>A construct enclosed within curly braces may be repeated zero or more + times.</p></li><li><p>JSON allows arbitrary white space between tokens. To avoid ugly clutter, this + grammar ignores the optional white space. </p></li><li><p>In many cases a production defines a JSON object, i.e. a list of name-value + pairs, separated by commas. Since the order of these name/value pairs is not + significant, the grammar will not try to show all the possible sequences. In + general it will present the required pairs first, if any, followed by any + optional elements.</p></li></ol></div><p> Since both EBNF and JSON use curly braces and square brackets, pay close attention to + whether these characters are in single quotes. If they're in single quotes, they are + literal elements of the JSON notation. Otherwise they are elements of the EBNF notation. + </p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e65"></a>Primitives</h2></div></div></div><p> We'll start by defining some primitives, to get them out of the way. They're mostly + just what you would expect. </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[1]</td><td align="right" valign="top" width="10%"><a name="ebnf.string"></a> string </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> '"' chars '"' </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[2]</td><td align="right" valign="top" width="10%"><a name="ebnf.chars"></a> chars </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> any valid sequence of UTF-8 characters, with certain special characters + escaped according to JSON rules </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[3]</td><td align="right" valign="top" width="10%"><a name="ebnf.int_literal"></a> integer_literal </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> [ sign ] digit { digit } </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[4]</td><td align="right" valign="top" width="10%"><a name="ebnf.sign"></a> sign </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> '+' | '-' </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[5]</td><td align="right" valign="top" width="10%"><a name="ebnf.digits"></a> digit </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%">digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'</td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[6]</td><td align="right" valign="top" width="10%"><a name="ebnf.int_string"></a> integer_string </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> '"' integer_literal '"' </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[7]</td><td align="right" valign="top" width="10%"><a name="ebnf.int"></a> integer </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> integer_literal | integer_string </td><td align="left" valign="top" width="30%"> </td></tr><tr><td align="left" valign="top" width="3%">[8]</td><td align="right" valign="top" width="10%"><a name="ebnf.num"></a> number </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> any valid character sequence that is numeric according to JSON rules </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> When json_query requires an integral value, it will usually accept a quoted string + and convert it to an integer by brute force – to zero if necessary. Likewise it may + truncate a floating point number to an integral value. Scientific notation will be + accepted but may not give the intended results. </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[9]</td><td align="right" valign="top" width="10%"><a name="ebnf.bool"></a> boolean </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> 'true' | 'false' | string | number </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> The preferred way to encode a boolean is with the JSON reserved word true or false, + in lower case without quotation marks. The string <code class="literal">true</code>, in upper, + lower, or mixed case, is another way to encode true. Any other string evaluates to + false. </p><p> As an accommodation to perl, numbers may be used as booleans. A numeric value of 1 + means true, and any other numeric value means false. </p><p> Any other valid JSON value, such as an array, will be accepted as a boolean but + interpreted as false. </p><p> The last couple of primitives aren't really very primitive, but we introduce them + here for convenience: </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[10]</td><td align="right" valign="top" width="10%"><a name="ebnf.classname"></a> class_name </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> string </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> A class_name is a special case of a string: the name of a class as defined by the + IDL. The class may refer either to a database table or to a source_definition, which is + a subquery. </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[11]</td><td align="right" valign="top" width="10%"><a name="ebnf.field_name"></a> field_name </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> string </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> A field_name is another special case of a string: the name of a non-virtual field as + defined by the IDL. A field_name is also a column name for the table corresponding to + the relevant class. </p></div><div class="sect1" lang="en"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="d0e194"></a>Query</h2></div></div></div><p> The following production applies not only to the main query but also to most + subqueries. </p><table width="100%" cellpadding="5" bgcolor="#F5DCB3" border="1" class="productionset" summary="EBNF"><tr><td><table border="0" width="99%" cellpadding="0" bgcolor="#F5DCB3" class="productionset" summary="EBNF productions"><tr><td align="left" valign="top" width="3%">[12]</td><td align="right" valign="top" width="10%"><a name="ebnf.query"></a> query </td><td valign="top" width="5%" align="center"><code>::=</code></td><td valign="top" width="52%"> '{'<br> '"from"' ':' from_list<br> [ ',' '"select"' ':' select_list + ]<br> [ ',' '"where"' ':' where_condition ]<br> [ ',' '"having"' ':' + where_condition ]<br> [ ',' '"order_by"' ':' order_by_list ]<br> [ ',' + '"limit"' ':' integer ]<br> [ ',' '"offset"' ':' integer ]<br> [ ',' + '"distinct"' ':' boolean ]<br> [ ',' '"no_i18n"' ':' boolean ]<br> '}' + </td><td align="left" valign="top" width="30%"> </td></tr></table></td></tr></table><p> Except for the <code class="literal">"distinct"</code> and <code class="literal">no_i18n</code> entries, + each name/value pair represents a major clause of the SELECT statement. The name/value + pairs may appear in any order. </p><p> There is no name/value pair for the GROUP BY clause, because json_query generates it + automatically according to information encoded elsewhere. </p><p> The <code class="literal">"distinct"</code> entry, if present and true, tells json_query that + it may have to create a GROUP BY clause. If not present, it defaults to false. </p><p> The <code class="literal">"no_i18n"</code> entry, if present and true, tells json_query to + suppress internationalization. If not present, it defaults to false. (Note that + <code class="literal">"no_i18n"</code> contains the digit one, not the letter ell.) </p><p> The values for <code class="literal">limit</code> and <code class="literal">offset</code> provide the + arguments of the LIMIT and OFFSET clauses, respectively, of the SQL statement. Each + value should be non-negative, if present, or else the SQL won't work. </p></div></div></body></html> \ No newline at end of file diff --git a/docs/Guides/grammar2.pdf b/docs/Guides/grammar2.pdf new file mode 100644 index 0000000000000000000000000000000000000000..cc42294a17bd5c000aa045fc3919e6bea3963786 GIT binary patch literal 15319 zcmd6OcRbbK|F|NgkdcwfB}B%Z?nOpsvNze{8o6BK+99&CitN2dLLxJSkYvl=J2N4x z^t+dK@6YG^{yiSw$K&_&$MHDNbIx;}=Xu`qd_K>MRY^jM8_WYEVSSwUB%cHZ00Gdq zZj%TKk^t2#FeoH|{kolzm6eel0Bs78QB_m`C_5nSERgmbBtTIIj5*p4z^-bH#$W*Q z#<EBh%E%5oAZ~{=!r(?E(8gkDv?V}GRSuwvaX}&N&5=lqJ;2EVV-66tF)}ts0;Cj` zuuGKe&?XMXNbH)QV1NeF&fWrT4FK`*^L|H*?MoP8uzX1fKtLdV5HAP;0fYH@`ME)` z%OKEY4iaHu5~Q^WP72<i(f|NJ1pt%;`%eyOZHA=|hF}L(Z~!R_6b4HeD22k}l|UM! zO^`So_86=bRwT{|iBV2!s)IEC9o2|xrSLO>5uKLiD#xWstEIzuu7FRTk$L$Lj~OnZ zW+R~-mPHI<pSYVY9#+I0=zC1LXo-McqSw}jnjz|jNk0Af3zxOF_;JQ<56k50j#0BU z_r6NJhoA4AsF%|^dG~ax7WL$OV?aodnIX}!(;x8gQFs$J#l>PYJ5tAEkKY*xM#WO? z&{kKH0e1JV^oRu4;eAbxsJO`t##4$3p8vQrs7p`V!Y8Dez*?r*5>pD3ZwJY=GvD-v zXgsq2$fa}VQ!J94e*@wpNZ)GTK85@+Gje%4grBk|ILwfqcAj{r0#d_fd=GQO?^+Xj zrilKI0vwM$e1vDtUeyG}Z5+-H@#da(!JCk7G5F98)Oy=N)k@yj{#KiZk|jHUo=sQP zFXRzb&}2u4{CrU3TM!u{<kA#)AeR2-`AIuG(~i$Ksa>q-pD|w@;N#~5S#ev{u=jfE zeU1;`c8t>Z@m!^sVBBf=r0Ee$iuW`N`FwEC-^$`Fp5D?irK&IfZH7R+z-KiMWbU>X zEAQy5yqe-N<IEcw(Um=xY{>y!Slde`^AtC@)1gu`x;AU%yzz)H90L~DM_8M>W=Xty z-9BZrdwMR}e}|Fiz~Led#b=h90APfqL~E8DKrZUJ&TFcG6R~1`*LITQcE}qJG6pN6 z?hoxybVg|%&ty7x&Ep~-`xOenNjDSD&NcT_P1o^v+k(1cV-oi}ybs(p%jFJU)3A7k z8ef-ylv66VFUNh>J`MxmNnXQWyvDGAPxX?Z^d&_(9{B|RaZ&aF0$W4ygg5oWV-f&b z>buWV=pwxH4KL>qI;2p*?!j&7FkZ$JFg_w4uU12Xkz*<#vZT8lA4uL_JLBW~`pj7s ze+)qU_4#MMS`Qg!@K1<SD4mZWW)&BcK7RJvQi@8>`Nw{Xsiq4$3+$M4m3XA$Whu($ zlzV4gi7tUoX4Ppwr9ho1HdN#z4)vj}Yxw}-W90EJdl_kif9K4qk77gg1cerfh*vhn z-7^#dX+a<gntCa*FlUyN6ij&!DKm~+TpN0LF@v!pP&zF8wGK6*q$F5LF5=W1#<RXt zX;G;fsqpm2%0x<uIl{f_z3jJ1wkYJKEYsS$+86LJTmtloK|E5LDe;{b7K#@rHu?6> z65dNS4hDzPdCHw<J6n9bn7){yCzRipzA4x!t4QmKK;QYLK+;CLr?*hxQWCc_Zj^2( zu7<kbyEKKdDdjWJ6;ue|e5F32ZFAX1(}t>?{sraOnYCc@#*GiH>&P9cJLDe3BB9Al z>{P)g3w)%-t{8ErhIdNw$(GAHi?UE|1t`3-NxNI_r*%V6LQwHMYYnTiv?&Xm!;6K< zifQF?BJ(J7HQ-T;lnJ?=;7z$PF>AJDrt!<Q$|+a0t`M+)pw{5*Wyf66Rd&t_(1fXN zs_8z7Dbz}Jmavsx&!yCFk-ne*N?AKoEghrw-mkj^qCP0auf{L#QfwFW@x<(PYOcnB zDe+0=K=yrhGj?M&pT~+w)rww+Ua7^Ki+rTw(5w@kDi)a~X!Cm|9A^Uq6J<(dl4L^O z*q-IMkjl`7zwmw&vS+mCuy<9RTU}ATW|8e3{2k}x!gq5yE;;M(WO|3*N%fB9LVMkN zdwR=qopQ%}u35xb_*l-|Uhd+{TgQ-Dg|?nwO$g`rpC9S-;cbImf@zws_MGob=<DwL z*z>0QakoJFmRfwlN^0WcYVm!aPZ?zD&GOe%ipA$M+Kv548XkqU=a_7QvoO34UmRE~ zw<_;dLS36&m0f*ZS6sI@PwsJjVfk`luX<0FP=Jt$@C0E#VHxSVA6El)gPz|Pzrv8< zkXylUItO|ohz67l)Q+&`t+5n?+ahk7b{pEYQ5(O3$U{f1TnA6XixINmJTL>qzwN@? z6LVE<{@k533N&Itgh32)ls%7P8&Jql?QZUS+^4v!xRP(uYc=Xv6)%?UnOmU~tw+t> zoBeK4nX8)j7;og|$8z_VHhmh>{ir)$kvH$y;cjha-CQ<o?9`KVoAFj{T}}VNy?g2R zUZ=Jhb$7i4cNO)m69zSr7+aYpI*DC%;m>yznA_|dth>2<XJD6>HcK{6HmEh-rD<bl z<J^2m#bSk>?vh@n_31K+vTAD;Cq1W7w|o2e<nH82*B>?eWapYao)_&f)9=$~E+i}L zN11(+`NV;KHQZ74%B|CXifUGM#eQ6~12I_k&go6Z7}|H7!?VQm;aB)qhGW{tM()nt z&ArzAGSbUkG$ZAN=sQtz?>2AAIw2+-X~Wl_9#(CT&Yzlh^7Zb#+qsguT_4;K<?GHE zdXoH9;Ym+ABP!)HUA1>B4O_gUP82d%Gq*CYNyJLrNOMg;n@*J$pKj3X+#Jy?ZJd8g zvq?X&CxGgeL$mR8`gHtMHtinQNQI4Hop37O<R0_1q)QMFSD#iw&CU*GBWnWdb;_>$ z;QQS7*Z5Nt2-`Qi?`A%i%`Qi+@~l!N5uu6D;cIVz^NK7LY>}6RWE|zkk_2O?l2pPz zs=cI9JC&5Zm))0Hqi{-oIQbKY5L>knesoxjt(r7N*2#UybLa-dzxZu&U~xukLiCC* zoRx%<7b!j%^sK58HrUa7_m#vmeMsDNl<K1mHiW>obdp^X2yIv~_))&~@<;cLT756= zI=wEP6rHD~hM3IxH+$-xk2CXJHJ1u`w1sM#&~0ANeV$ubda{@BZ~^aB@R;f;hG}%g zr4?;?Ea?QD4U}v|z{^oN!vRC=1AOHct67ib8D*VWX=U?eIc3JtbJjIGk!_lh2JS=Q zCCI05Q&AlnZ#5?SmWD^lF0gCzbO0HLFFvcbCo;a?5*mFqdijNtk*0E4&{NrGvfA{z zgL+7%=g$}29b~qoLp0^x@=aH=hWe{qstT9a2YNKJ)it%ZtqTp;+FWb*+6mMB0^MWW z`S&lvr4XMy+x99eZlvdyyl?QB^my+TfbZTG+SbM$$BoRl$;)u~Xjos@I_~V*Gunj8 zLuZ#oUp(&5;(yUIerIK?LDb*v!PC$Zce5QmE28J=8B~k9WBl(TyIEI4mo5sQb1o@s z&di>6YhBxB>=Dwi*PV49JXwD~jVf7TE;&Is(qZxa`<Wi&YFXE{g!@AF`M?+G52((; zjrltriSM_UMO?<VJ{O&8rw!FN(Oa&ZvB|Z6>5(!`w9hC&c!BV$|9SsP;8nd<`Xt1i zslffn9?j~)q$(PlmG0M{!zP!M`_W_4<xJHrRl5rsd-?Na_SPLEH|=TN%Vv_gs{{Ar zwi!HNUyAe=0YbuyLINKQ>+W4O9x1vkg8aJa@nV5#*Qn8_U1H<X@bzXk_sc*L{T=7e zH~JpMW;cp(e%0N7J2U81>--r4I(wD(KzH+VPhq@4PVK<g?p5R(W?=J+CVio)e)J1v zPx}e(C9AJhF-}y_inXFOPLUXog<ZPM_0{ZP#bgisZJ&*O+<o)gb@AKH6aMYysRO(r zE-q$dk2C?`E~6@X->;^K->#-=E;dL2P#%dfGBLs!;Vz}B4!1CeKrMN>UvI6@!&~dm z>#3lKGxi#7iNpYIA<ZnTg_zf>YMB8RCPK`byz(G<8*!w$g|w?3Qq@&K&Dhn_nBRn1 zL|D*Sz}d>i3QJBHiyI(lXJRU#A|Z9y`K1qVwnACk3z!%SF`HvBHUdDPje{ME2W@8t zG%*GuQAjJKHO3wY<^cnl0XQ5+x6lq4A!g?9h;X<}j0G^bKtlLG#1Vp6T;FEkcscsR ztuj6eB7}dBE)J)EANqX(R&~f<C}S}l3Z{y*{T=#!0A(SJiy*i`yxbs!8U!o=<`*~& zBLqMoK_E^Z?2MlzaLW#%zau<k=vUH5lm4?hZA?sm=+oMs#|Rs#AbE_@RzU0kR+rHK zqD$-y0c^bXEi4kohHZklRlmZ1@+){a@-3_q{tr>rxAos=eOvuMiGVepe-^>n$ObC{ z=)Z`7T`F)G9wKp3+<)7EKW6?S*pCskof;aA68@J_rXcXog@54ue*XRqXTQz;N45Q; zL@ec>2kz&I#rg^%W;^V8{M&zk!9V=N&xjQloU8m}ybAc~5S$a*v~|!Ua2k*8!ZRNs zs!#G|dWEhrc8|i$DNqOo+D2vux)Q%><-9Pq%7LxYFKce>_j^;NEoKDBMS(OTf&TLz zWVyE7L<bdilb%IuL$>EHE6)&UxW3rIOgcU)I7`ubiiq6?l}r#ieX{`l=%s-66>2Sh zgL@YPoV`WfRDp!GL=32DL$~Ip8m>E=nejheove>#8VhsvTqj$HzrgD-p!6KqH@Ndf z&#)rYp_)<a#09EmGWT1JrSmuYuP-%xl9zmNUE3XL#l2HFLQXF7;_G^H!*o@YI(=U4 zGhyw15#1Lx8YbK4n?q}1UE>^F-b)h7CRc6KDkF@;2FM6S@N+J=%u_35HFz+bcrUr| zwf*C=IoH(~<I%*L^Q&(Qs41@6jk4S~st+Y{Vh*zYI2({rMXX%i@W3q_-nyDXymw7F z&X?@M@C}+4=b9B(g>aUD^W+tq*YaZT+B13M+suaDhGZ^!7ghyKwMLJ>?fiJ*D#>eY zQH%9~Yy#j@{vN>ar=+<-1#!zyxk$-3B`3oS&TRH<IcXO8*^zdZ7^%DGwh5WEi5k3o z>}T2tV4q^#WF^Q^<Z3e)o_TH?bj;8}MiKSURJNz&iQ`RML~y){Vu*Tt2b<KYqv%tO zvZz=RXQp+{%G9!DKUqx5A{$Sing(n+R2|_$xHoxD$4*jWcekcod!&xQ!BO+{14jSa zs%0Kazxi>}f#g;ioz}V+EfeDokeyaGowVsjN4e9v>HW>&6=&Yf$6My-#MfF8u6zZ5 z9@VvqT6r3^`Qk$Tb9zCo(gw;4z-OZ`9nL%5@~@kWI!)oxe!fOS<2>;=u_|Ajtu86k zxhac)LMAUipL3KJ(odLL=*@0&9=s^tBz;L@b}~8<d7rGveLTi&DQodcTX+?qzQZZ{ zdAGGbv8p+1D&lPr)bD0h*9)U?n@poLWCK?hQ`iLxacXigAOj(VM~zXRj3vC8k;<5R zH}Yxc(1m&K83D^v`Y%vvl47sQs620{qzR2B6_aP}-NDbN(I{=z^io7k-F2eKG}5pc z3^_N~>!=-jo2&%<@}?D@sHRQ0BCXC$NAFgFM);K4Tz|zq+h;sCC~FP2HoQpX4T$}# zSAY&TNA3nbzD}T#Qu5>$uQ$7XuWvwb0@?B5l4Z);o|HQAsOjk8%1oC~CxX!;Dt*ze zjqFm?tHCsU33KMv4;XElZJUf(W2phjH<?2bOI$30?Iu^2J|9<5sI#%FbcY$L4}&g@ zMXTSw`&CvtC*4~z_{#%zLfG(<R-KAQe~D|!Rz=xh;WASmX#(*Dqh)E*<8XDIj9!*Y zya9>PC1FkV&}_=y+lC&mWh~Wh!S!dBnizWS%;(&@Rl3#_d{(}6K5TUU)w5%cvbJ33 zzBsyFeSNk3vEb5JX&P(9n<+KF?5bt`CzfPW_wCh|Sxyj_z|ptePMbX!lK{`$L?a`m z+tu#dzX~vGPMSnvbfWmv%|frME+(hm5|rE_b!O`s8W(D_ByFUZ@RmKHY&xF}D&Y~Q zx?K8&1#`Z;uu}N-?ODeY#M*f)xwqUj)KS@rLazamDW_?DL@#hT5e}*OXH;ZU89PXv zel5%Di~oqunBx_@1YX{1$TLw%-iL%&m&|Xz*E0JodykH=>*Gf+dg+V^Gg<DoGap<~ zyahfgGv1uE=L%|UQZbN}>)Kzmhe=>@FBpxtms71hRV7$!E)aPfPh5yd*OzS&6Y3mw zww}zam(8*pPf~cIGQL2aE!ItQ@AV+MyHcqBxxiqyh97nKf>*AIl;T=*cgue22lS}M z#V*(-nU|bhx2?N8ZhIKMFuhhs6`lC3Xz4{O+=_0;@l4|l%1wqE%4aT<12S9q=I0(X z+xd_BOdD6+J7z9eD={ssY!sKH<Zqn6NNB~aK5i8dO=`qb9cEnE8?slb$*i|4F>UvN zkY_HSr}4PDo@Y+p6(3<P89=vRyMaD418KUAPemOA4;@?R3JCLv@7!tQ5rPXan~hMn z5v$QGqB;xin>6I=l8lY<oN)nR-p&;B2EE1~`cl2M4YdR~i|56-x7^<cLk68g<()4# zipTVY5N09W-fTI|`Ug-5s1JfIQ~GnCb7&XcO7AHca6W$RL$zQ)Opd{ARTU_)Tjx!} z=jyWs@>}#z_muJLs5TMX%-J00ydO!0t>e$N#(rwEce#4*32I!|titoEEO$}0iEF1~ zUFDX%=mS)RdpxD5$Nndl$$s5(!TS@HpISFky~ATXXO>m#AC{z0DX5JyY0>0)NJoZ! z%$Ms-eJ&%)rf|tu;VkehYB_tasHum!QGv`s|HA5kFsDi80@&pRul<KFB4a}&HbO3< z<0W~ju6`t9jRbmyoPlUR%Hk(4m=(oFGs;w+>(B-Gu<D#~SJo@Fp{ae(((XJO8N2te zB_l~*)oygmaht_{9tNDz>m3>v>=&Y1n9mVaAuqYw@80xrG)_8M>FepR1M2shl6$Je z1;LxIim3V>bT#i|!gB(tVm{zOR-{^BP4_7$2pXB`@x$b%<0c+5%SZqpvcH*H6wZsI zL5~$Z(7&F*X)CX!WI4P&`Q$|Q+L=dvu*lSamL-eVnaHt=l2`BbEjP0Z#dz~^PrlVj zep8Pr6yV9#B9pHyS6JK#<?ax^SeqI0vdH;SuJgk+QGVNr4BG8y)k{FJ`F1&72GLuW zkCo*0n371eOafrfTowh$FtHMf*@BP!1J*-xxFjx_P_9Tf9zz8cSSZT|lyFBg%67Hi zFFC=`!OA1Dx%`mDlBz#8c{w4I&<s4iou(+gZJ#`TxkRJ^v6KC}X4f4WLOzTCa;~xF z%7c%2<8ztLQy=7$-i6ehFPU@+6^so`HbwEUM$+=~IStXh{zQd8Nw%AV#v5&`Aid~Z zYnd`WiQpg?o@w$EO1YCfJbi7A36@lRgD!bA<B8*w$_jTF>QYv_Ij3X0b@)a@fDzH` zC9nIAc4NJ>9tOp=5+e@n!!AT=X1-mKy&GBgYuv_~BwZd=*se#vrg~QyFVgX)ewM?l zsz8W%5;eJF9e!Hy#evmlHiy}v9pVA<W{&~A%2a#ics_yMuJaownn`zu*l!40Rm_Nu z#c<hE_&d`1f38H!Sb&D>)tTtbO!H^F>rOJ<e#_cNo}L!J+WcbGGX(fhU{eArnRoW; z`u;>(E?8!LLfTWA``C$E-mz{!7PXy7k?xD9miPP724BBuXY~5Pmx<$pmg<UX6f4%~ zXy4uW{0Uz@sb$=!wL65T*qIr!bu*Q5n1_Ct#P-A_QD+(^jOi*D!P!hQc{)ke^a2X@ z>T^aaLd0$xYmA<I(S9ELjHHYCwz-pKTq|v`y6o|kuHFlrTD<zzxAb7=B!;sDyV+#- z^H}v7I@6>{J3R6`NR(bvc%E2Zi){2|XtnG+%biYPd=T%Y1&>(JX}^Q=I}@kxlnT?U zxpMvC;A}&Uo{g}6XmGGW$h}q9{8I>@U=H60e(}S$Z$G|}n$F$bi|%~DNx5muFZ}_@ z%P4C0@<Tl(X?I`<V;p`2;m*dygGy3LgD&q6opnG-6HlN@-N1eFxHJ97J~n&U_@#ZO zTIp4f;Os9b|I8TM$S3^|*ILkzYc2N93{*kdqaEywk@kS2uoeqCiiDMn%#gSV@<<a4 zBQdlyKnJ&wm!B8F2ZQM0M#NA^q{%;ysM%Rq{o{a=ksUT(1>kPhhjkxuv^547zyc00 z+bX!4&-dv3usDRPAVGNf;Xi;lCUHQ1IPVYG_ktM&&d>h?_&xd;6#OobsI@g3L-I4K zm$R_8B*DsWi~;CiOHm*m5CD#V@W8+b02t2C1A_tJeAw^~+ttIC)39@J@`G?4F|?ft zwp#TIL=*r%%q@@rr2)VjB)`<Zz<l30{+EpKg86tL2<Q)1cp=cE{{I3mke^%sf1?yQ z=$lfoSq2CIj?>M*RSG{=c$L4E0{JzxIx@Hax;sZo!O=cq<wz<2OT2tHseida-z){j zccc^;jEA2e0Ov*gYo$Prs-AyY3go*T|4T-GSjsn6ept%?1}{I$wm)KD2<}Mzo7gu& z=fN<Xrg?l`mCl8pHYVqVj0ugqd6h-kHYwy<k@;Rq5wG#{(pfD#wjRaWjDn0;8J?dw z*oWf${b!gwXP8{1DD@~dI_z&Bq!Y+Ts0g$M=vt9!q6^LAZ)no%te4Q<2q$JcImvm2 zl1<Y;5*VIW%{~3uumQLsqS&9|lxI*Fs%f&d@(x|gkhl^UWA{LF20yY)y}HJAcA$?l zW;{9Ey}&o&p@h3DVa>;5W;dhGWV(MaX;fq0A2gKEi-dO+n<OpAt+VLSR(|#DG<^n& z_3_8tJ$SFR{ch#m{P^p$ta-!xV{hjjbsq(*<VUthQyYw4)TqsWZ<aT%SvGD^{eo2f zkz%%ND@XkkJuAiCz?0KlF?~ZzHgT*{62yAoI8fxEfmL>`(7eC6#{ufOeynHS{z3D0 zq33SJ*WE>xgx0iGqGq@#RP}^Ko=x1DH)Nb05f}POSBF1a8@#nVs1$%V7R4^=yab=M zh_$IFHqw(EzYuT#yc!kvOyJY3lvN_D*qJ;5PLp$P3LLTl@5_r`10_$&OW%I>%%#X= z43G7=W}Bfpblp%rG%u_Cv7b79gF0)$<KQc-rmFio>I$~%UU{ZZ9|Ov-G^?xXsy93i zpL|TI*=Ui;mrtD?IaLBl(D3VdW1~&4AUjz?jcZ^EveP9nxmJ_O#~^MgL+#*~C3L<P zV3M9&)LD&mazWr28e=~0(4MJpjaLsPAGcReI3M?YY;%NFB|#(b2rFlU1xG?uJ+5i8 zusCdDqFP?58)+xJEaCIDuqEl4!s4Zu3xdYbn1Q(4ZM4s4H`-zwRvYc(xP~&D)%K|2 zP~bdd{B(BYB$n|btUpovS)4rHLrIXuN-QU<6cd#K;uba1_O34>xMy*au!qu_OMIf} zv{y5P;9~2UIkg0t^rytd?yy^I5^+z1sRV$Mw4^!kGjofdw{<VR$-0B^qqvSNZqMl| zR{n4^w*6d~dAHQIsj^6vN$xYFESDll&yb3zkG<8c@F@DvQdH6xSoU2gXuX8#A=V37 zf+WO|vP@M{j5re@F4l!yx1pjKksv@&)X7WOJfaveAwbaAafeJqN!iF=Do0X`JR`Qg zNl?b+9UnN6#ay0CY%Sm&A3Bj`YYndtSehC^1yl4lRt&OVDhRSKww2O~o*Y4CQ1pjP zG+ioRC$<*!W_U2c#$0}%*qYfpK6rxdQu&Qmd8#*fqY)AdABjg{Vw%&HpKS58G^G}< z=xTNm>rtdK)X87B>7f|G5FkSAi^0;mwDYFv51;a2$?&n@$b=n&jKj*UzlkvYw+Qlw z{AW^(bbsStho(+m(nghHM2!G(_8SFQyZo7icmN+l)W+I-YJ{M%;$)yb74<wDUAsIe zA>Qz(l8Py0n@VJ+y?yjvhx>X5)um*LPA?7+F(%Ks&gJB&Gh9r}E6a*W)bf!7BR;DI zNybWQwyj+3h9cbL6un(ZdZ1-4a*B6d>9el4oxP|wlfxX~L;3JNY2v*=z*!klt_Uw( zcKkXezwk+R`p~0>f}P$g9NXLv55qM#lp!24Y?3V*?6Id=AElZ=B7((Q*l~?{M6eXD zA#4F14>uxUX&{#NQ+{|l9Y8N73JLZyp~G(h5r%__&MSqboAAl_rJE4QNTuMKG!vGi z<_ItK5negJaAkIS-=n6BojxSI3qY@M4U%xzgzs334N3SUHA@4Bw4dt3(`EqrcI-gv z5n8@)Xn)165+N6e<DFiHO}r%~+B0<QfZz4Y{KA*y^kaCTQh0plj!&4MzLo;U^J>B) zIER1cf9fzWMC67BHOY5C+JlOebUP1n1GY#C5$Zjgg^;f$yQu?fE3G|Nv7c5f!%cMC z4MN!FZoj5V3|oJ`^pc@%5|O%Mf9c9>&((KT2O*2|O?jJ%I^&x2;$vL14YK_OPX;5m zRQ4un2v<#KvU@6A4dNDqt`$YE#ZQ%Um$oJper!vQ-rMciWmS4#blYxt!z6Yqd9lb@ zli*E+*MYCA%0;3_G=LQ-_o~*MxUGF^c<IdhZs+i<kKt9VOd_t~RcV64y@;f@m{sG* zgpc+@p9-mjsGFw}5bp-dvTIO|Nrt9t4;tNodb`gLfa54i#gA)?>3%e8ij7UQfe z?zhj1JLvO>zZ3SF4qaVZRD#VK#lY+9l9T0~TAdoPar+qJ)TD96IMAnQz+L}hH19H3 z*j+vYjfCWA8q}v~@h>G@2EJT;v|G<|?<%i?0?B#sFVAORG1PWIn|_ivpYh$4s-eH* z15IjYF9;dTnp|%^-O$Xq802tl*1&kO=v@E7mIX%F!RA~HLte$gpnssYaZN$!TA*>> z0dt0RGC$L;4?!4Zq|BT^`l-$8z6H|0-Okj5hO-Am><3LAZfDcp4vc%A_3`D3<8<fW zWqMyaaUYS@_{{pY;zFf4f81Dh=x%EHI?MJu547M+AJv$UON$v$|IRvBP0aXaX*ux0 zY#RCYyFppRs$;KCf^&FOpB-Ksvi-s}9qX6n&wFM)n4{fF;_aXcl2_B(b|HM+W|4)6 zd)cK|wZQHZGklN9R_Ogp8D!pNt?%AxX@iWCUK}=JNDyR}&G>Tu#*jl0(d7=g_s!41 ztDYinPeJ=Nmk>=Mbebi+?QhQ}^EAubTO>BccZ>vgMLM+9Qx`0TIdL+4R*9}Gkbmb^ z*f}hVgzqjfXu_w+)YeftdaGjUf*Wr}s&eJ^-A>39_OFDNoCoGsuRm_}Pmg8vv!OCc zF;5FYs8y=ciV{LIfz2mDAu_}9ceIaNPTxK_U!6N@Zc2q2_e!WrPaB)b_L9`G(`aA5 z6n{&sx&~^N?V8+QMO!`Lsw4Em#a>8lU}p9}px0r4f<UwWpss2q^0b3{!R9DlfC{gR z7aXi(P;DcK|GcHDUjDhYae`C+0%#SfH^ik<=)Jgr6q!>*)VSIvWD2=$o4$SE^3^)5 z=k~!&F26#`qX_+c2cvf6N>cfGV4Ump>@wrm#k>iDA_Lv-A)c7{%+7(&B@qg20%9FX z*M;MjG^?ol(l0w?KI%HQ;n$9izUg#~N^zE>ceQ7-V5q+ZG7mSIGu4cYpRj?>l5XpD z3DWpZmo9bL(tg4-g$Fr?kOigdqITZdeuY`nJr|0wZh9x|94=3xs~FA_XtO_Y!&3H~ zt|CrbrJvhcwp(h5a>w<h$ZKk@#%~$GTFDYoA{*|V-NBdNu4Y$@w0cLiM;zSGjBj;0 zFK@X}F8iR^Ws{gj2`rztWzbl0t`dUEeq^sz=HzQQj*=eR@f<R!Q-6wvX1>Qa?N}-6 z@S~~~B7Apjceeo5zPoD?yH(EVpZ<)qKyjB1@X0hUzDv!MrrFkkkG@R(WrCA>g<c?# zeE+W3Tudh&qcfGcedXd+m9LN2Okx@h&AG-pVfQ#!7|$ovC6XyNB%IHB1JfEM_H};q zi3;NV)T3_UOh-kxQ$x&^>5J0)^*OP2&Doi~7r~2}d<KCu^O(zp!>^yZCREHx=T(Wk zb=WhFRc4!}*qz>5ZL?xhTKl46`k<p@e0E=!Vgae2v~-u=zHrTCl>4GvvBXf}dpQYs zWUSPqT1CyJ{<*i>d=_S&GAnW83bqe=-(N4(u6k1{o?La|S$*kcg-Q&S0_>85(7v>x zMOZE66O&37qD7R{c4yY(PP*p?>#<EaW9knY!1v0cpA;SNtR$EYZRS2+vJ+5qs;_i* z0}EHs5miw=kWG_yRA#B&1Dp4;Ca!L^IWR0-mlufdYu&(PEs+SY3$#>I1RIZ*d8}=J z*_oMFEbE@VR+>x~M`*|A|D>5!#7U^JhHqd^hEOOpcDO!?V=ts5G3Qf@k{f-2pYblh zW%pgj_)hre@~so?^=qurt{R2K2BGr&!*fJ=j*0}<qHdt_^~UTweb=hoIu_A!JjByM z%>yRM9wTQ*^_;*y986<pDo<&!I5G^;qo08plviZ3g-cr2sfV*(aGG<zUwv?&^IYL& zt2ap*g<o$ZA~v*zZ)G|?SdwU1wnM%ffglFuLuNrLbEMN;1my>fWM7T>lWZ@`UcO}3 zBu6xAp_4RMFkC-=5Lv&xeli<1GEbXqMf^2{xlOu0pjR8y=)qlZT_jzSxvJyFlO;A0 zgzUO=qm7B)rbV!Od8FF(R#RA#lsGyncACY>gk16^CDg+|v!s$h?fNH=^~_FPvqzbm zeeq2SO{tIL-3_lDl=mLvyx8m<&FTJ_Cp9)ZhUk4!<+A@H7usD$)7Py!^BeV6H)3<R zF4Tfw#2hz4hLU}8SV8RVtA*?*-r8psAXPIRCr$r!ibWxF#r7G085Ofy*%$F-HCN?| zBuxdXv>es-AX<YvDN_6Q30tQ2JiaVfGAb>d_MaV;5w{xXul0$rwR$pAsjv5ik^Rmc zDqL#h_ZJe_DE=s$qC)~c4DLt{vlS{Nhlv90zoR@2<R~+A7@w+;{CGa`GqLgiK96*m zJ-}v>a030FSb`koWqwI49mcV^91;}92l<{ag8Y=`XTW=yz4#Z!UUfaiVGy-@N8wZF zn^(Mw64&}~P<zqk+|Cff6VqSnMBUe;BzooXC83Gq#xnD#zBHBjov|hR2M;csez<qF zVbNgOn6BBDQj#4nuiM4;gEi&706bu?(%lrr<356S-KCE!d4s9%rnS+ZmKISFN!QwX zaZKdGD!}Ibh{)p@-fLIZ+C+&0*JQX88}G)GDNP$sZ3{WH&mVh9oDrM#7{*5ICwvUN zDflpIVyya!`OWUzgt{p;%suy(W=Hcc@|@F{eUjvL{h|I<+V?q5<V<voI!i$mlE_5% zKtSN5qRcY@@ad8c>fT7yyp&wlgHgz(49nDgq1W{E5nT_9EV8GK%*s?G41H|FU)?_5 zG^8+=4d+jak_&nm6<w_=a`Ai&rlInlEzK*C%#dRL$6di#Hb17*)kYsr(kk+Y?zTMX z0Mj(AP+VXQ>9?bgez%`nSJwum8rFECu|7vIYe^NM-oWL{${9H1<Js>mQk~N}IU3F^ z_r$uC`+{s{f~<z^75h4iu&<+}DfEs=i-)IjGtaL^g+HZL<V+d1v(NXfGNrd7$sJri zSw+u%JB!wdaYTpdCgZbIf!$6=Djz21tGDn84F>Ef38G#(c12Ev&)rchMkH6YCvR61 zkD+z4n^{T>Ro>?@_UhOB$4Wwzb9^bpOm5pR6M@vI*a=oSxzB0nutAh#7nl-3Y#<h8 zHwQTl?vIe@<OI@M`QYK9N3S@N$vr)N6&D&Z93qr8Om4ObGfDJTn|35n4rxsB8VtiC zH8L%>Mk3yn!;ALIHfi6C=zb}ev6{8oD|g!1{a8;^bH!Y>c&~RV{w3p9e&}#izRAIx zz%Q)t-UK-^G4>J-5N#YQ*Byy5<jyt8ztWjdm68{7fAzE_M+t>|5q#YsN{eTQ-mIf! zrKMZh`n~y`_rZIGa>2O_^PXzp(reYGemWo6cFGQDoT=V1^4+=o72inL=E2{-0`lEg zU_VRv|0ivHcx-=58$)o17I(T4kRKUhC@$lMgB@np{)bO00KjiaYUsBtHBbTRi~&Fo zUw)7PfT92>E{%#K3i$TY>~QQ4{AxzGuwQOqKiK%5;^x4v{S&j29nukS$Q{;ceWP>a zuMX)P`Q2aW{F;^f_G!osYs}%xAq@7TjQ>pHJM%}P9Qk@2iEml!Ur79xH$PI95;mJ} zfw6GJeQ@%hWcbeY5rJ=R7)RhJ1N;ktpLT@JK_3yoea_<YpK<?W_gm`p7i>S>HqI)K zQpr--q5`h><NY2E48}oluK;nQILcN?du|o9m60`WK++of$%%!v833qhVJ&KHZ}A=Q zYefS3-L#I5z`rLZjYK&jF&4%~++t{y$-kxt`<brCt@-!##IY3}3#8q@CiHhU9#{Oa z$5uVi4p?PDNr18zCiVawoU&B_;6w8V96AIQfFADM)3<Z*^O*hQR~-A85`{Ly0S=M= zto?j{z6JR4qb+BI-2rwa&W?{}%NgB5qU-@jHiU&KI$%&1*0@^Lx3hUPO&<HX5CEud zkNiIV+phgM`y{}_y+7JLDP92dP#zpDDJbA@a}Tc$Qv85J%^$iI+(%Kys@SKUI#^N? zQrO~-6;?H3-~NkZcLnDha0MbX3T>x~eFusJ91)N}ni@HvFe=x@07nLl)zeQ^{WK-) zxp%O_Di?%Zhou2v2Xo+5iq+G%KIEtm`QC>f_7C;`L-9W~|J_bRjd30UTkZk?ucOt_ zBtQv(&bOTdYTeWZU@Ki902B`8fr1eHd;n_)6iV+G{tg|(50`fM3ih8c9$Casgm5s7 z2ZVt0BmPGCtHej9{BIC~d7(TAC=6R-`IEy#FZ_ScA(lBFKE8iI_v;~$vaqwq+C5II zIL9n!gzFud=`X(L9|}kRp!7dggn(fyjS&8SP?578(v$=QfPqOsKmM?lC0-~mz!Y!< z14CgjETgzTfb|a;FBr?pA22u^%l&UKYzMcif50HPOaAXL2tVjgd{~B|SS$W*9vBRR zVRiC549bVA+x`Xv!4dF3*Mgw@{D0Af^W%O<|5(e<`xnnx^ZFA8hVmo+rpwR&CtWZY z%J=755CRPSQ(iC(#QP@<`;jBIF8c?62pH~A{l+tv1pl8f5Q3NYZy22KPyK-qd^o@Q zJ3cTR=k9)oL12IJ2L{7=|I`5(0{?4&!7!{9{fQ3-`P+sd@V{*h27&*n129%CfAI|A z`+F^fALmzpmjep=do2|Fmz{#45M22A$6DyGHi@w_vOr;f^swF+sA}Pg#GNCc3L1?8 zV3mR^Lf^19MFWm5LckkXZzw1R6~z{^#l;X{32{CN5Fei;pSUPL1SBa5g(Adw#e@O> c^OQrMX^%0o!yKMoFbsP@NmyAW6{Sf24{-KwQ~&?~ literal 0 HcmV?d00001 diff --git a/docs/Guides/grammar2.xml b/docs/Guides/grammar2.xml new file mode 100644 index 0000000000..5dd2215185 --- /dev/null +++ b/docs/Guides/grammar2.xml @@ -0,0 +1,227 @@ +<?xml version="1.0" encoding="utf-8"?> + +<article version="5.0" xmlns="http://docbook.org/ns/docbook" + xmlns:xi="http://www.w3.org/2003/XInclude" xmlns:xlink="http://www.w3.org/1999/xlink"> + + <title>Grammar of JSON Queries</title> + + <para> + <author> + <personname> + <firstname>Scott</firstname> + <surname>McKellar</surname> + </personname> + <affiliation> + <orgname>Equinox Software, Inc.</orgname> + </affiliation> + </author> + </para> + + <para> + <info> + <copyright> + <year>2009</year> + <holder>Creative Commons Attribution-Share Alike 3.0 United States License.</holder> + </copyright> + </info> + </para> + + + + <sect1> + <title>Introduction</title> + <para> The format of this grammar approximates Extended Backus-Naur notation. However it is + intended as input to human beings, not to parser generators such as Lex or Yacc. Do not + expect formal rigor. Sometimes narrative text will explain things that are clumsy to + express in formal notation. More often, the text will restate or summarize the formal + productions. </para> + <para> Conventions: </para> + <orderedlist> + <listitem> + <para>The grammar is a series of productions.</para> + </listitem> + <listitem> + <para>A production consists of a name, followed by "::=", followed by a definition + for the name. The name identifies a grammatical construct that can appear on the + right side of another production.</para> + </listitem> + <listitem> + <para>Literals (including punctuation) are enclosed in 'single quotes', or in + "double quotes" if case is not significant.</para> + </listitem> + <listitem> + <para>A single quotation mark within a literal is escaped with a preceding + backslash: 'dog\'s tail'.</para> + </listitem> + <listitem> + <para>If a construct can be defined more than one way, then the alternatives may + appear in separate productions; or, they may appear in the same production, + separated by pipe symbols. The choice between these representations is of only + cosmetic significance.</para> + </listitem> + <listitem> + <para>A construct enclosed within square brackets is optional.</para> + </listitem> + <listitem> + <para>A construct enclosed within curly braces may be repeated zero or more + times.</para> + </listitem> + <listitem> + <para>JSON allows arbitrary white space between tokens. To avoid ugly clutter, this + grammar ignores the optional white space. </para> + </listitem> + <listitem> + <para>In many cases a production defines a JSON object, i.e. a list of name-value + pairs, separated by commas. Since the order of these name/value pairs is not + significant, the grammar will not try to show all the possible sequences. In + general it will present the required pairs first, if any, followed by any + optional elements.</para> + </listitem> + </orderedlist> + + <para> Since both EBNF and JSON use curly braces and square brackets, pay close attention to + whether these characters are in single quotes. If they're in single quotes, they are + literal elements of the JSON notation. Otherwise they are elements of the EBNF notation. + </para> + </sect1> + + <sect1> + <title>Primitives</title> + <para> We'll start by defining some primitives, to get them out of the way. They're mostly + just what you would expect. </para> + + <productionset> + <production xml:id="ebnf.string"> + <lhs> string </lhs> + <rhs> '"' chars '"' </rhs> + </production> + + <production xml:id="ebnf.chars"> + <lhs> chars </lhs> + <rhs> any valid sequence of UTF-8 characters, with certain special characters + escaped according to JSON rules </rhs> + </production> + + <production xml:id="ebnf.int_literal"> + <lhs> integer_literal </lhs> + <rhs> [ sign ] digit { digit } </rhs> + </production> + + <production xml:id="ebnf.sign"> + <lhs> sign </lhs> + <rhs> '+' | '-' </rhs> + </production> + + <production xml:id="ebnf.digits"> + <lhs> digit </lhs> + <rhs>digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'</rhs> + </production> + + <production xml:id="ebnf.int_string"> + <lhs> integer_string </lhs> + <rhs> '"' integer_literal '"' </rhs> + </production> + + <production xml:id="ebnf.int"> + <lhs> integer </lhs> + <rhs> integer_literal | integer_string </rhs> + </production> + + <production xml:id="ebnf.num"> + <lhs> number </lhs> + <rhs> any valid character sequence that is numeric according to JSON rules </rhs> + </production> + + </productionset> + + <para> When json_query requires an integral value, it will usually accept a quoted string + and convert it to an integer by brute force â to zero if necessary. Likewise it may + truncate a floating point number to an integral value. Scientific notation will be + accepted but may not give the intended results. </para> + + <productionset> + + <production xml:id="ebnf.bool"> + <lhs> boolean </lhs> + <rhs> 'true' | 'false' | string | number </rhs> + </production> + + </productionset> + + <para> The preferred way to encode a boolean is with the JSON reserved word true or false, + in lower case without quotation marks. The string <literal>true</literal>, in upper, + lower, or mixed case, is another way to encode true. Any other string evaluates to + false. </para> + <para> As an accommodation to perl, numbers may be used as booleans. A numeric value of 1 + means true, and any other numeric value means false. </para> + <para> Any other valid JSON value, such as an array, will be accepted as a boolean but + interpreted as false. </para> + <para> The last couple of primitives aren't really very primitive, but we introduce them + here for convenience: </para> + + <productionset> + + <production xml:id="ebnf.classname"> + <lhs> class_name </lhs> + <rhs> string </rhs> + </production> + + </productionset> + + <para> A class_name is a special case of a string: the name of a class as defined by the + IDL. The class may refer either to a database table or to a source_definition, which is + a subquery. </para> + + <productionset> + + <production xml:id="ebnf.field_name"> + <lhs> field_name </lhs> + <rhs> string </rhs> + </production> + + </productionset> + + <para> A field_name is another special case of a string: the name of a non-virtual field as + defined by the IDL. A field_name is also a column name for the table corresponding to + the relevant class. </para> + + </sect1> + + <sect1> + <title>Query</title> + + <para> The following production applies not only to the main query but also to most + subqueries. </para> + + <productionset> + + <production xml:id="ebnf.query"> + <lhs> query </lhs> + <rhs> '{'<sbr/> '"from"' ':' from_list<sbr/> [ ',' '"select"' ':' select_list + ]<sbr/> [ ',' '"where"' ':' where_condition ]<sbr/> [ ',' '"having"' ':' + where_condition ]<sbr/> [ ',' '"order_by"' ':' order_by_list ]<sbr/> [ ',' + '"limit"' ':' integer ]<sbr/> [ ',' '"offset"' ':' integer ]<sbr/> [ ',' + '"distinct"' ':' boolean ]<sbr/> [ ',' '"no_i18n"' ':' boolean ]<sbr/> '}' + </rhs> + </production> + + </productionset> + + <para> Except for the <literal>"distinct"</literal> and <literal>no_i18n</literal> entries, + each name/value pair represents a major clause of the SELECT statement. The name/value + pairs may appear in any order. </para> + <para> There is no name/value pair for the GROUP BY clause, because json_query generates it + automatically according to information encoded elsewhere. </para> + <para> The <literal>"distinct"</literal> entry, if present and true, tells json_query that + it may have to create a GROUP BY clause. If not present, it defaults to false. </para> + <para> The <literal>"no_i18n"</literal> entry, if present and true, tells json_query to + suppress internationalization. If not present, it defaults to false. (Note that + <literal>"no_i18n"</literal> contains the digit one, not the letter ell.) </para> + <para> The values for <literal>limit</literal> and <literal>offset</literal> provide the + arguments of the LIMIT and OFFSET clauses, respectively, of the SQL statement. Each + value should be non-negative, if present, or else the SQL won't work. </para> + + </sect1> + + +</article> diff --git a/docs/Guides/grammar3.xml b/docs/Guides/grammar3.xml new file mode 100644 index 0000000000..32b6e22438 --- /dev/null +++ b/docs/Guides/grammar3.xml @@ -0,0 +1,755 @@ +<?xml version="1.0" encoding="utf-8"?> +<!DOCTYPE article PUBLIC "-//OASIS//DTD DocBook V4.5//EN" + "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd"> + +<article xmlns="http://docbook.org/ns/docbook"> + + <artheader> + <title>Grammar of JSON Queries</title> + <author> + <firstname>Scott</firstname> + <surname>McKellar</surname> + </author> + </artheader> + + <sect1><title>Introduction</title> + <para> + The format of this grammar approximates Extended Backus-Naur notation. However it + is intended as input to human beings, not to parser generators such as Lex or + Yacc. Do not expect formal rigor. Sometimes narrative text will explain things + that are clumsy to express in formal notation. More often, the text will restate + or summarize the formal productions. + </para> + <para> + Conventions: + </para> + <orderedlist> + <listitem> + The grammar is a series of productions. + </listitem> + <listitem> + A production consists of a name, followed by "::=", followed by a + definition for the name. The name identifies a grammatical construct that can + appear on the right side of another production. + </listitem> + <listitem> + Literals (including punctuation) are enclosed in single quotes, or in double + quotes if case is not significant. + </listitem> + <listitem> + A single quotation mark within a literal is escaped with a preceding backslash. + </listitem> + <listitem> + If a construct can be defined more than one way, then the alternatives may appear + in separate productions; or, they may appear in the same production, separated by + pipe symbols. The choice between these representations is of only cosmetic + significance. + </listitem> + <listitem> + A construct enclosed within square brackets is optional. + </listitem> + <listitem> + A construct enclosed within curly braces may be repeated zero or more times. + </listitem> + <listitem> + JSON allows arbitrary white space between tokens. To avoid ugly clutter, this + grammar ignores the optional white space. + </listitem> + <listitem> + In many cases a production defines a JSON object, i.e. a list of name-value pairs, + separated by commas. Since the order of these name/value pairs is not significant, + the grammar will not try to show all the possible sequences. In general it will + present the required pairs first, if any, followed by any optional elements. + </listitem> + </orderedlist> + + <para> + Since both EBNF and JSON use curly braces and square brackets, pay close attention to + whether these characters are in single quotes. If they're in single quotes, they are + literal elements of the JSON notation. Otherwise they are elements of the EBNF notation. + </para> + </sect1> + + <sect1><title>Primitives</title> + <para> + We'll start by defining some primitives, to get them out of the way. They're + mostly just what you would expect. + </para> + + <productionset> + <production> + <lhs> + string + </lhs> + <rhs> + 'â' chars 'â' + </rhs> + </production> + + <production> + <lhs> + chars + </lhs> + <rhs> + any valid sequence of UTF-8 characters, with certain special characters + escaped according to JSON rules + </rhs> + </production> + + <production> + <lhs> + integer_literal + </lhs> + <rhs> + [ sign ] digit { digit } + </rhs> + </production> + + <production> + <lhs> + sign + </lhs> + <rhs> + '+' | '-' + </rhs> + </production> + + <production> + <lhs> + digit + </lhs> + digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' + <rhs> + </rhs> + </production> + + <production> + <lhs> + integer_string + </lhs> + <rhs> + 'â' integer_literal 'â' + </rhs> + </production> + + <production> + <lhs> + integer + </lhs> + <rhs> + integer_literal | integer_string + </rhs> + </production> + + <production> + <lhs> + number + </lhs> + <rhs> + any valid character sequence that is numeric according to JSON rules + </rhs> + </production> + + </productionset> + + <para> + When json_query requires an integral value, it will usually accept a quoted string and + convert it to an integer by brute force â to zero if necessary. Likewise it may + truncate a floating point number to an integral value. Scientific notation will be + accepted but may not give the intended results. + </para> + + <productionset> + + <production> + <lhs> + boolean + </lhs> + <rhs> + 'true' | 'false' | string | number + </rhs> + </production> + + </productionset> + + <para> + The preferred way to encode a boolean is with the JSON reserved word true or false, + in lower case without quotation marks. The string â<literal>true</literal>â, in + upper, lower, or mixed case, is another way to encode true. Any other string + evaluates to false. + </para> + <para> + As an accommodation to perl, numbers may be used as booleans. A numeric value of 1 + means true, and any other numeric value means false. + </para> + <para> + Any other valid JSON value, such as an array, will be accepted as a boolean but interpreted + as false. + </para> + <para> + The last couple of primitives aren't really very primitive, but we introduce them here + for convenience: + </para> + + <productionset> + + <production> + <lhs> + class_name + </lhs> + <rhs> + string + </rhs> + </production> + + </productionset> + + <para> + A class_name is a special case of a string: the name of a class as defined + by the IDL. The class may refer either to a database table or to a + source_definition, which is a subquery. + </para> + + <productionset> + + <production> + <lhs> + field_name + </lhs> + <rhs> + string + </rhs> + </production> + + </productionset> + + <para> + A field_name is another special case of a string: the name of a non-virtual + field as defined by the IDL. A field_name is also a column name for the + table corresponding to the relevant class. + </para> + + </sect1> + + <sect1><title>Query</title> + + <para> + The following production applies not only to the main query but also to + most subqueries. + </para> + + <productionset> + + <production> + <lhs> + query + </lhs> + <rhs> + '{'<sbr/> + 'âfromâ' ':' from_list<sbr/> + [ ',' 'âselectâ' ':' select_list ]<sbr/> + [ ',' 'âwhereâ' ':' where_condition ]<sbr/> + [ ',' 'âhavingâ' ':' where_condition ]<sbr/> + [ ',' 'âorder_byâ' ':' order_by_list ]<sbr/> + [ ',' 'âlimitâ' ':' integer ]<sbr/> + [ ',' 'âoffsetâ' ':' integer ]<sbr/> + [ ',' 'âdistinctâ' ':' boolean ]<sbr/> + [ ',' 'âno_i18nâ' ':' boolean ]<sbr/> + '}' + </rhs> + </production> + + </productionset> + + <para> + Except for the <literal>âdistinctâ</literal> and <literal>âno_i18nâ</literal> + entries, each name/value pair represents a major clause of the SELECT statement. + The name/value pairs may appear in any order. + </para> + <para> + There is no name/value pair for the GROUP BY clause, because json_query + generates it automatically according to information encoded elsewhere. + </para> + <para> + The <literal>âdistinctâ</literal> entry, if present and true, tells json_query + that it may have to create a GROUP BY clause. If not present, it defaults to false. + </para> + <para> + The <literal>âno_i18nâ</literal> entry, if present and true, tells json_query to + suppress internationalization. If not present, it defaults to false. (Note that + <literal>âno_i18nâ</literal> contains the digit one, not the letter ell.) + </para> + <para> + The values for <literal>âlimitâ</literal> and <literal>âoffsetâ</literal> + provide the arguments of the LIMIT and OFFSET clauses, respectively, of the + SQL statement. Each value should be non-negative, if present, or else the + SQL won't work. + </para> + + </sect1> + + <sect1><title>FROM Clause</title> + <para> + The object identified by <literal>âfromâ</literal> encodes the FROM clause of + the SQL. The associated value may be a string, an array, or a JSON object. + </para> + + <productionset> + + <production> + <lhs> + from_list + </lhs> + <rhs> + class_name + </rhs> + </production> + + </productionset> + + <para> + If <literal>from_list</literal> is a <literal>class_name</literal>, the + json_query inserts the corresponding table name or subquery into the FROM + clause, using the <literal>class_name</literal> as an alias for the table + or subquery. The class must be defined as non-virtual in the IDL. + </para> + + <productionset> + + <production> + <lhs> + from_list + </lhs> + <rhs> + '[' string { ',' parameter } ']' + </rhs> + </production> + + <production> + <lhs> + parameter + </lhs> + <rhs> + string | number | 'null' + </rhs> + </production> + + </productionset> + + <para> + If from_list is a JSON array, then it represents a table-like function from + which the SQL statement will select rows, using a SELECT clause consisting + of âSELECT *â (regardless of the select_list supplied by the method parameter). + </para> + <para> + The first entry in the array is the name of the function. It must be a string + naming a stored function. Each subsequent entry is a function parameter. If + it is a string or a number, json_query will insert it into a comma-separated + parameter list, enclosed in quotes, with any special characters escaped as needed. + If it is the JSON reserved word <literal>null</literal>, json_query will insert + it into the parameter list as a null value. + </para> + <para> + If <literal>from_list</literal> is a JSON object, it must contain exactly one entry. + The key of this entry must be the name of a non-virtual class defined in the IDL. + This class will be the top-level class of the FROM clause, the only one named + outside of a JOIN clause. + </para> + + <productionset> + + <production> + <lhs> + from_list + </lhs> + <rhs> + '{' class_name ':' join_list '}' + </rhs> + </production> + + <production> + <lhs> + join_list + </lhs> + <rhs> + class_name + </rhs> + </production> + + <production> + <lhs> + join_list + </lhs> + <rhs> + '{' join_def { ',' join_def } '}' + </rhs> + </production> + + </productionset> + + <para> + If the associated data is a <literal>class_name</literal>, json_query will + construct an INNER JOIN clause joining the class to the top-level clause, + using the columns specified by the IDL for such a join. + </para> + <para> + Otherwise, the associated data must be a JSON object with one or more entries, + each entry defining a join: + </para> + + <productionset> + + <production> + <lhs> + join_def + </lhs> + <rhs> + class_name ':'<sbr/> + '{'<sbr/> + [ 'âtypeâ' ':' string ]<sbr/> + [ 'âfieldâ' ':' field_name ]<sbr/> + [ 'âfkeyâ' ':' field_name ]<sbr/> + [ 'âfilterâ' ':' where_condition ]<sbr/> + [ 'âfilter_opâ' ':' string ]<sbr/> + [ 'âjoinâ' ':' join_list ]<sbr/> + '}' + + </rhs> + </production> + + </productionset> + + <para> + The data portion of the <literal>âjoin_typeâ</literal> entry tells json_query + whether to use a left join, right join, full join, or inner join. The values + <literal>âleftâ</literal>, <literal>ârightâ</literal>, and <literal>âfullâ</literal>, + in upper, lower, or mixed case, have the obvious meanings. If the + <literal>âjoin_typeâ</literal> entry has any other value, or is not present, + json_query constructs an inner join. + </para> + <para> + The <literal>âfieldâ</literal> and <literal>âfkeyâ</literal> attributes specify the + columns to be equated in the join condition. The <literal>âfieldâ</literal> + attribute refers to the column in the joined table, i.e. the one named by the + <literal>join_def</literal>. The <literal>âfkeyâ</literal> attribute refers to the + corresponding column in the other table, i.e. the one named outside the + <literal>join_def</literal> â either the top-level table or a table named by some + other <literal>join_def</literal>. + </para> + <para> + It may be tempting to suppose that <literal>âfkeyâ</literal> stands for âforeign keyâ, + and therefore refers to a column in the child table that points to the key of a + parent table. Resist the temptation; the labels are arbitrary. The json_query + method doesn't care which table is the parent and which is the child. + </para> + <para> + These relationships are best explained with an example. The following <literal>from_list</literal>: + </para> + + <informalexample><programlisting language="JSON"> + { + "aou": { + "asv": { + "type" : "left", + "fkey" : "id", + "field" : "owner" + } + } + } + </programlisting></informalexample> + + <para> + ...turns into the following FROM clause: + </para> + + <informalexample><programlisting language="SQL"> + FROM + actor.org_unit AS "aou" + LEFT JOIN action.survey AS "asv" + ON ( "asv".owner = "aou".id ) + </programlisting></informalexample> + + <para> + Note in this example that <literal>âfkeyâ</literal> refers to a column of the + class <literal>âaouâ</literal>, and <literal>âfieldâ</literal> refers to a + column of the class <literal>âasvâ</literal>. + </para> + <para> + If you specify only one of the two columns, json_query will try to identify the + other one from the IDL. However, if you specify only the column from the parent + table, this attempt will probably fail. + </para> + <para> + If you specify both columns, json_query will use the column names you specify, + without verifying them with a lookup in the IDL. By this means you can perform + a join using a linkage that the IDL doesn't define. Of course, if the columns + don't exist in the database, the query will fail when json_query tries to execute it. + </para> + <para> + Using the columns specified, either explicitly or implicitly, the json_query + method constructs a join condition. With raw SQL it is possible (though + rarely useful) to join two tables by an inequality. However the json_query + method always uses a simple equality condition. + </para> + <para> + Using a <literal>âfilterâ</literal> entry in the join_def, you can apply one + or more additional conditions to the JOIN clause, typically to restrict the + join to certain rows of the joined table. The data associated with the + <literal>âfilterâ</literal> key is the same sort of + <literal>where_condition</literal> that you use for a WHERE clause + (discussed below). + </para> + <para> + If the string associated with the <literal>âfilter_opâ</literal> entry is + <literal>âORâ</literal> in upper, lower, or mixed case, then the json_query + method uses OR to connect the standard join condition to any additional + conditions supplied by a <literal>âfilterâ</literal> entry. + </para> + <para> + (Note that if the <literal>where_condition</literal> supplies multiple + conditions, they will be connected by AND. You will probably want to move + them down a layer â enclose them in parentheses, in effect â to avoid a + confusing mixture of ANDs and ORs.) + </para> + <para> + If the <literal>âfilter_opâ</literal> entry carries any other value, or if + it is absent, then the json_query method uses AND. In the absence of a + <literal>âfilterâ</literal> entry, <literal>âfilter_opâ</literal> has no effect. + </para> + <para> + A <literal>âjoinâ</literal> entry in a <literal>join_def</literal> specifies + another layer of join. The class named in the subjoin is joined to the class + named by the <literal>join_def</literal> to which it is subordinate. By this + means you can encode multiple joins in a hierarchy. + </para> + </sect1> + + <sect1><title>SELECT Clause</title> + <para> + If a query does not contain an entry for <literal>âselectâ</literal>, json_query + will construct a default SELECT clause. The default includes every non-virtual + field from the top-level class of the FROM clause, as defined by the IDL. The + result is similar to SELECT *, except: + </para> + + <itemizedlist> + <listitem> + The default includes only the fields defined in the IDL. + </listitem> + <listitem> + The columns will appear in the same order in which they appear in the IDL, + regardless of the order in which the database defines them. + </listitem> + </itemizedlist> + + <para> + There are other ways to specify a default SELECT list, as shown below. + </para> + <para> + If a <literal>âselectâ</literal> entry is present, the associated value must + be a JSON object, keyed on class names: + </para> + + <productionset> + + <production> + <lhs> + select_list + </lhs> + <rhs> + '{' class_name ':' field_list { ',' class_name ':' field_list } '}' + </rhs> + </production> + + </productionset> + + <para> + The <literal>class_name</literal> must identify either the top-level class or + a class belonging to one of the joins. Otherwise json_query will silently + ignore the <literal>select_list</literal>. + </para> + + <productionset> + + <production> + <lhs> + field_list + </lhs> + <rhs> + 'null' | 'â*â' + </rhs> + </production> + + </productionset> + + <para> + If a field_list is either the JSON reserved word <literal>null</literal> + (in lower case) or an asterisk in double quotes, json_query constructs a + default SELECT list â provided that the class is the top-level class of the + query. If the class belongs to a join somewhere, json_query ignores the + <literal>field_list</literal>. + </para> + <para> + More commonly, the <literal>field_list</literal> is a JSON array of zero or + more field specifications: + </para> + + <productionset> + + <production> + <lhs> + field_list + </lhs> + <rhs> + '[' [ field_spec { ',' field_spec } ] ']' + </rhs> + </production> + + </productionset> + + <para> + If the array is empty, json_query will construct a default SELECT list for + the class â again, provided that the class is the top-level class in the query. + </para> + <para> + In the simplest case, a field specification may name a non-virtual field + defined in the IDL: + </para> + + <productionset> + + <production> + <lhs> + field_spec + </lhs> + <rhs> + field_name + </rhs> + </production> + + </productionset> + + <para> + In some cases json_query constructs a call to the + <literal>oils_i18n_xlate</literal> function to internationalize the value of the + selected column. Specifically, it does so if all the following are true: + </para> + + <itemizedlist> + <listitem> + the settings file defines a locale; + </listitem> + <listitem> + in the field definition for the field in the IDL, the tag + <literal>âil8nâ</literal> is present and true; + </listitem> + <listitem> + the query does <emphasis>not</emphasis> include the + <literal>âno_il8nâ</literal> tag (or includes it with a value of false). + </listitem> + </itemizedlist> + + <para> + A field specification may be a JSON object: + </para> + + <productionset> + + <production> + <lhs> + field_spec + </lhs> + <rhs> + '{'<sbr/> + 'âcolumnâ' ':' <sbr/> + [ ',' 'âaliasâ' ':' string ]<sbr/> + [ ',' 'âaggregateâ' ':' boolean ]<sbr/> + [ ',' transform_spec ]<sbr/> + '}' + + </rhs> + </production> + + </productionset> + + <para> + The <literal>âcolumnâ</literal> entry provides the column name, which must + be defined as non-virtual in the IDL. + </para> + <para> + The <literal>âaliasâ</literal> entry provides a column alias. If no alias + is specified, json_query uses the column name as its own alias. + </para> + <para> + The <literal>âaggregateâ</literal> entry has no effect on the SELECT clause + itself. Rather, it affects the construction of a GROUP BY class. If there + is an <literal>âaggregateâ</literal> entry for any field, then json_query builds + a GROUP BY clause listing every column that is <emphasis>not</emphasis> tagged + for aggregation (or that carries an <literal>âaggregateâ</literal> entry with + a value of false). If <emphasis>all</emphasis> columns are tagged for + aggregation, then json_query omits the GROUP BY clause. + </para> + + <productionset> + + <production> + <lhs> + transform_spec + </lhs> + <rhs> + 'âtransformâ' ':' string ]<sbr/> + [ ',' 'âresult_fieldâ ':' string ]<sbr/> + [ ',' 'âparamsâ ':' param_list ] + </rhs> + </production> + + </productionset> + + <para> + When a <literal>transform_spec</literal> is present, json_query selects the + return value of a function instead of selecting the column directly. The entry + for <literal>âtransformâ</literal> provides the name of the function, and the + column name (as specified by the <literal>âcolumnâ</literal> tag), qualified by + the class name, is the argument to the function. For example, you might use such + a function to format a date or time, or otherwise transform a column value. + You might also use an aggregate function such as SUM, COUNT, or MAX (possibly + together with the <literal>âaggregateâ</literal> tag). + </para> + <para> + The <literal>âresult_fieldâ</literal> entry, when present, specifies a subcolumn + of the function's return value. The resulting SQL encloses the function call + in parentheses, and follows it with a period and the subcolumn name. + </para> + <para> + The <literal>âparamsâ</literal> entry, if present, provides a possibly empty + array of additional parameter values, either strings, numbers, or nulls: + </para> + + <productionset> + + <production> + <lhs> + param_list + </lhs> + <rhs> + '[' [ parameter { ',' parameter } ] ']' + </rhs> + </production> + + </productionset> + + <para> + Such parameter values are enclosed in single quotes, with any special characters + escaped as needed, and inserted after the column name as additional parameters + to the function. You might, for example, use an additional parameter to provide + a format string for a reformatting function. + </para> + </sect1> + + <sect1><title>WHERE Clause</title> + </sect1> + + <sect1><title>ORDER BY Clause</title> + </sect1> + +</article> -- 2.11.0