Skip to content

Commit

Permalink
Use language-fql instead of lang-fql.
Browse files Browse the repository at this point in the history
  • Loading branch information
janderland committed Oct 31, 2024
1 parent 4760615 commit 8fc6c39
Show file tree
Hide file tree
Showing 2 changed files with 96 additions and 96 deletions.
96 changes: 48 additions & 48 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@
</head>
<body>
<h1>FQL</h1>
<pre class="lang-fql query"><code>/user/index/surname(&quot;Johnson&quot;,&lt;userID:int&gt;)
<pre class="language-fql query"><code>/user/index/surname(&quot;Johnson&quot;,&lt;userID:int&gt;)
/user(:userID,...)</code></pre>
<pre class="lang-fql result"><code>/user(9323,&quot;Timothy&quot;,&quot;Johnson&quot;,37)=nil
<pre class="language-fql result"><code>/user(9323,&quot;Timothy&quot;,&quot;Johnson&quot;,37)=nil
/user(24335,&quot;Andrew&quot;,&quot;Johnson&quot;,42)=nil
/user(33423,&quot;Ryan&quot;,&quot;Johnson&quot;,0x0ffa83,42.2)=nil</code></pre>
<p>FQL is an <a href="https://github.com/janderland/fql">open
Expand Down Expand Up @@ -65,12 +65,12 @@ <h1 id="overview">Overview</h1>
href="https://github.com/janderland/fql/blob/main/syntax.ebnf">context-free
grammar</a>. The queries look like key-values encoded using the
directory &amp; tuple layers.</p>
<pre class="lang-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=4000</code></pre>
<pre class="language-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=4000</code></pre>
<p>FQL queries may define a single key-value to be written, as shown
above, or may define a set of key-values to be read, as shown
below.</p>
<pre class="lang-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=&lt;int&gt;</code></pre>
<pre class="lang-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=4000</code></pre>
<pre class="language-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=&lt;int&gt;</code></pre>
<pre class="language-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=4000</code></pre>
<p>The query above has a variable <code>&lt;int&gt;</code> as its
value. Variables act as placeholders for any of the supported <a
href="#data-elements">data elements</a>. In this case, the variable
Expand All @@ -79,33 +79,33 @@ <h1 id="overview">Overview</h1>
<p>FQL queries can also perform range reads &amp; filtering by
including a variable in the key’s tuple. The query below will return
all key-values which conform to the schema defined by the query.</p>
<pre class="lang-fql query"><code>/my/directory(&lt;&gt;,&quot;tuple&quot;)=nil</code></pre>
<pre class="lang-fql result"><code>/my/directory(&quot;your&quot;,&quot;tuple&quot;)=nil
<pre class="language-fql query"><code>/my/directory(&lt;&gt;,&quot;tuple&quot;)=nil</code></pre>
<pre class="language-fql result"><code>/my/directory(&quot;your&quot;,&quot;tuple&quot;)=nil
/my/directory(42,&quot;tuple&quot;)=nil</code></pre>
<p>All key-values with a certain key prefix can be range read by
ending the key’s tuple with <code>...</code>.</p>
<pre class="lang-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;,...)=&lt;&gt;</code></pre>
<pre class="lang-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=0x0fa0
<pre class="language-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;,...)=&lt;&gt;</code></pre>
<pre class="language-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=0x0fa0
/my/directory(&quot;my&quot;,&quot;tuple&quot;,47.3)=0x8f3a
/my/directory(&quot;my&quot;,&quot;tuple&quot;,false,0xff9a853c12)=nil</code></pre>
<p>A query’s value may be omitted to imply a variable, meaning the
following query is semantically identical to the one above.</p>
<pre class="lang-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;,...)</code></pre>
<pre class="lang-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=0x0fa0
<pre class="language-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;,...)</code></pre>
<pre class="language-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=0x0fa0
/my/directory(&quot;my&quot;,&quot;tuple&quot;,47.3)=0x8f3a
/my/directory(&quot;my&quot;,&quot;tuple&quot;,false,0xff9a853c12)=nil</code></pre>
<p>Including a variable in the directory tells FQL to perform the read
on all directory paths matching the schema.</p>
<pre class="lang-fql query"><code>/&lt;&gt;/directory(&quot;my&quot;,&quot;tuple&quot;)</code></pre>
<pre class="lang-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=0x0fa0
<pre class="language-fql query"><code>/&lt;&gt;/directory(&quot;my&quot;,&quot;tuple&quot;)</code></pre>
<pre class="language-fql result"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=0x0fa0
/your/directory(&quot;my&quot;,&quot;tuple&quot;)=nil</code></pre>
<p>Key-values can be cleared by using the special <code>clear</code>
token as the value.</p>
<pre class="lang-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=clear</code></pre>
<pre class="language-fql query"><code>/my/directory(&quot;my&quot;,&quot;tuple&quot;)=clear</code></pre>
<p>The directory layer can be queried by only including a directory
path.</p>
<pre class="lang-fql query"><code>/my/&lt;&gt;</code></pre>
<pre class="lang-fql result"><code>/my/directory</code></pre>
<pre class="language-fql query"><code>/my/&lt;&gt;</code></pre>
<pre class="language-fql result"><code>/my/directory</code></pre>
<h1 id="data-elements">Data Elements</h1>
<p>An FQL query contains instances of data elements. These are the
same types of elements found in the <a
Expand Down Expand Up @@ -169,15 +169,15 @@ <h1 id="data-elements">Data Elements</h1>
<p><code>bint</code> support is not yet implemented.</p>
</blockquote>
<p>Tuples &amp; values may contain any of the data elements.</p>
<pre class="lang-fql query"><code>/region/north_america(22.3,-8)=(&quot;rain&quot;,&quot;fog&quot;)
<pre class="language-fql query"><code>/region/north_america(22.3,-8)=(&quot;rain&quot;,&quot;fog&quot;)
/region/east_asia(&quot;japan&quot;,nil)=0xff</code></pre>
<p>Strings are the only data element allowed in directories. If a
directory string only contains alphanumericals, underscores, dashes,
and periods then the quotes don’t need to be included.</p>
<pre class="lang-fql query"><code>/quoteless-string_in.dir(true)=false
<pre class="language-fql query"><code>/quoteless-string_in.dir(true)=false
/&quot;other ch@r@cters must be quoted!&quot;(20)=32.3</code></pre>
<p>Quoted strings may contain quotes via backslash escapes.</p>
<pre class="lang-fql query"><code>/my/dir(&quot;I said \&quot;hello\&quot;&quot;)=nil</code></pre>
<pre class="language-fql query"><code>/my/dir(&quot;I said \&quot;hello\&quot;&quot;)=nil</code></pre>
<h1 id="value-encoding">Value Encoding</h1>
<p>The directory and tuple layers are responsible for encoding the
data elements in the key. As for the value, FDB doesn’t provide a
Expand Down Expand Up @@ -242,33 +242,33 @@ <h1 id="variables-schemas">Variables &amp; Schemas</h1>
href="#data-elements">data element</a> may be represented with a
variable. Variables are specified as a list of element types,
separated by <code>|</code>, wrapped in angled braces.</p>
<pre class="lang-fql"><code>&lt;uint|str|uuid|bytes&gt;</code></pre>
<pre class="language-fql"><code>&lt;uint|str|uuid|bytes&gt;</code></pre>
<p>The variable’s type list describes which data elements are allowed
at the variable’s position. A variable may be empty, including no
element types, meaning it represents all element types.</p>
<pre class="lang-fql query"><code>/user(&lt;int&gt;,&lt;str&gt;,&lt;&gt;)=&lt;&gt;</code></pre>
<pre class="lang-fql result"><code>/user(0,&quot;jon&quot;,0xffab0c)=nil
<pre class="language-fql query"><code>/user(&lt;int&gt;,&lt;str&gt;,&lt;&gt;)=&lt;&gt;</code></pre>
<pre class="language-fql result"><code>/user(0,&quot;jon&quot;,0xffab0c)=nil
/user(20,&quot;roger&quot;,22.3)=0xff
/user(21,&quot;&quot;,nil)=&quot;nothing&quot;</code></pre>
<p>Before the type list, a variable can be given a name. This name is
used to reference the variable in subsequent queries, allowing for <a
href="#index-indirection">index indirection</a>.</p>
<pre class="lang-fql query"><code>/index(&quot;cars&quot;,&lt;varName:int&gt;)
<pre class="language-fql query"><code>/index(&quot;cars&quot;,&lt;varName:int&gt;)
/data(:varName,...)</code></pre>
<pre class="lang-fql result"><code>/user(33,&quot;mazda&quot;)=nil
<pre class="language-fql result"><code>/user(33,&quot;mazda&quot;)=nil
/user(320,&quot;ford&quot;)=nil
/user(411,&quot;chevy&quot;)=nil</code></pre>
<h1 id="space-comments">Space &amp; Comments</h1>
<p>Whitespace and newlines are allowed within a tuple, between its
elements.</p>
<pre class="lang-fql query"><code>/account/private(
<pre class="language-fql query"><code>/account/private(
&lt;uint&gt;,
&lt;uint&gt;,
&lt;str&gt;,
)=&lt;int&gt;</code></pre>
<p>Comments start with a <code>%</code> and continue until the end of
the line. They can be used to describe a tuple’s elements.</p>
<pre class="lang-fql"><code>% private account balances
<pre class="language-fql"><code>% private account balances
/account/private(
&lt;uint&gt;, % user ID
&lt;uint&gt;, % group ID
Expand All @@ -290,7 +290,7 @@ <h2 id="mutations">Mutations</h2>
</blockquote>
<p>Mutation queries with a <a href="#data-elements">data element</a>
as their value perform a write operation.</p>
<pre class="lang-fql query"><code>/my/dir(&quot;hello&quot;,&quot;world&quot;)=42</code></pre>
<pre class="language-fql query"><code>/my/dir(&quot;hello&quot;,&quot;world&quot;)=42</code></pre>
<pre class="lang-go equiv-go"><code>db.Transact(func(tr fdb.Transaction) (interface{}, error) {
dir, err := directory.CreateOrOpen(tr, []string{&quot;my&quot;, &quot;dir&quot;}, nil)
if err != nil {
Expand All @@ -306,7 +306,7 @@ <h2 id="mutations">Mutations</h2>
})</code></pre>
<p>Mutation queries with the <code>clear</code> token as their value
perform a clear operation.</p>
<pre class="lang-fql query"><code>/my/dir(&quot;hello&quot;,&quot;world&quot;)=clear</code></pre>
<pre class="language-fql query"><code>/my/dir(&quot;hello&quot;,&quot;world&quot;)=clear</code></pre>
<pre class="lang-go equiv-go"><code>db.Transact(func(tr fdb.Transaction) (interface{}, error) {
dir, err := directory.Open(tr, []string{&quot;my&quot;, &quot;dir&quot;}, nil)
if err != nil {
Expand All @@ -331,7 +331,7 @@ <h2 id="reads">Reads</h2>
href="#variables">variable</a> as the value, and are therefore read
queries.</p>
</blockquote>
<pre class="lang-fql query"><code>/my/dir(99.8,7dfb10d1-2493-4fb5-928e-889fdc6a7136)=&lt;int|str&gt;</code></pre>
<pre class="language-fql query"><code>/my/dir(99.8,7dfb10d1-2493-4fb5-928e-889fdc6a7136)=&lt;int|str&gt;</code></pre>
<pre class="lang-go equiv-go"><code>db.ReadTransact(func(tr fdb.ReadTransaction) (interface{}, error) {
dir, err := directory.Open(tr, []string{&quot;my&quot;, &quot;dir&quot;}, nil)
if err != nil {
Expand Down Expand Up @@ -362,7 +362,7 @@ <h2 id="reads">Reads</h2>
the key-value does not match the schema.</p>
<p>If the value is specified as an empty variable, then the raw bytes
are returned.</p>
<pre class="lang-fql query"><code>/some/data(10139)=&lt;&gt;</code></pre>
<pre class="language-fql query"><code>/some/data(10139)=&lt;&gt;</code></pre>
<pre class="lang-go equiv-go"><code>db.ReadTransact(func(tr fdb.ReadTransaction) (interface{}, error) {
dir, err := directory.Open(tr, []string{&quot;some&quot;, &quot;data&quot;}, nil)
if err != nil {
Expand All @@ -378,7 +378,7 @@ <h2 id="reads">Reads</h2>
<p>Queries with <a href="#variables">variables</a> or the
<code>...</code> token in their key (and optionally in their value)
result in a range of key-values being read.</p>
<pre class="lang-fql query"><code>/people(&quot;coders&quot;,...)</code></pre>
<pre class="language-fql query"><code>/people(&quot;coders&quot;,...)</code></pre>
<pre class="lang-go equiv-go"><code>db.ReadTransact(func(tr fdb.ReadTransaction) (interface{}, error) {
dir, err := directory.Open(tr, []string{&quot;people&quot;}, nil)
if err != nil {
Expand Down Expand Up @@ -412,7 +412,7 @@ <h2 id="directories">Directories</h2>
directory as a query. These queries can only perform reads. If the
directory path contains no variables, the query will read that single
directory.</p>
<pre class="lang-fql query"><code>/root/&lt;&gt;/items</code></pre>
<pre class="language-fql query"><code>/root/&lt;&gt;/items</code></pre>
<pre class="lang-go equiv-go"><code> root, err := directory.Open(tr, []string{&quot;root&quot;}, nil)
if err != nil {
if errors.Is(err, directory.ErrDirNotExists) {
Expand Down Expand Up @@ -449,11 +449,11 @@ <h2 id="filtering">Filtering</h2>
<p>Because filtering is performed on the client side, range reads may
stream a lot of data to the client while the client filters most of it
away. For example, consider the following query:</p>
<pre class="lang-fql query"><code>/people(3392,&lt;str|int&gt;,&lt;&gt;)=(&lt;uint&gt;,...)</code></pre>
<pre class="language-fql query"><code>/people(3392,&lt;str|int&gt;,&lt;&gt;)=(&lt;uint&gt;,...)</code></pre>
<p>In the key, the location of the first variable or <code>...</code>
token determines the range read prefix used by FQL. For this
particular query, the prefix would be as follows:</p>
<pre class="lang-fql query"><code>/people(3392)</code></pre>
<pre class="language-fql query"><code>/people(3392)</code></pre>
<p>Foundation DB will stream all key-values with this prefix to the
client. As they are received, the client will filter out key-values
which don’t match the query’s schema. Below you can see a Go
Expand Down Expand Up @@ -536,25 +536,25 @@ <h2 id="indirection">Indirection</h2>
</blockquote>
<p>Suppose we have a large list of people, one key-value for each
person.</p>
<pre class="lang-fql query"><code>/people(&lt;id:uint&gt;,&lt;firstName:str&gt;,&lt;lastName:str&gt;,&lt;age:int&gt;)=nil</code></pre>
<pre class="language-fql query"><code>/people(&lt;id:uint&gt;,&lt;firstName:str&gt;,&lt;lastName:str&gt;,&lt;age:int&gt;)=nil</code></pre>
<p>If we wanted to read all records with the last name of “Johnson”,
we’d have to perform a linear search across the entire “people”
directory. To make this kind of search more efficient, we can store an
index of last names in a separate directory.</p>
<pre class="lang-fql query"><code>/index/last_name(&lt;lastName:str&gt;,&lt;id:uint&gt;)=nil</code></pre>
<pre class="language-fql query"><code>/index/last_name(&lt;lastName:str&gt;,&lt;id:uint&gt;)=nil</code></pre>
<p>FQL can forward the observed values of named variables from one
query to the next, allowing us to efficiently query for all people
with the last name of “Johnson”.</p>
<pre class="lang-fql query"><code>/index/last_name(&quot;Johnson&quot;,&lt;id:uint&gt;)
<pre class="language-fql query"><code>/index/last_name(&quot;Johnson&quot;,&lt;id:uint&gt;)
/people(:id,...)</code></pre>
<pre class="lang-fql result"><code>/people(23,&quot;Lenny&quot;,&quot;Johnson&quot;,22,&quot;Mechanic&quot;)=nil
<pre class="language-fql result"><code>/people(23,&quot;Lenny&quot;,&quot;Johnson&quot;,22,&quot;Mechanic&quot;)=nil
/people(348,&quot;Roger&quot;,&quot;Johnson&quot;,54,&quot;Engineer&quot;)=nil
/people(2003,&quot;Larry&quot;,&quot;Johnson&quot;,8,&quot;N/A&quot;)=nil</code></pre>
<p>The first query returned 3 key-values containing the IDs of 23,
348, &amp; 2003 which were then fed into the second query resulting in
3 individual <a href="#single-reads">single reads</a>.</p>
<pre class="lang-fql query"><code>/index/last_name(&quot;Johnson&quot;,&lt;id:uint&gt;)</code></pre>
<pre class="lang-fql result"><code>/index/last_name(&quot;Johnson&quot;,23)=nil
<pre class="language-fql query"><code>/index/last_name(&quot;Johnson&quot;,&lt;id:uint&gt;)</code></pre>
<pre class="language-fql result"><code>/index/last_name(&quot;Johnson&quot;,23)=nil
/index/last_name(&quot;Johnson&quot;,348)=nil
/index/last_name(&quot;Johnson&quot;,2003)=nil</code></pre>
<h2 id="aggregation">Aggregation</h2>
Expand All @@ -567,11 +567,11 @@ <h2 id="aggregation">Aggregation</h2>
href="https://apple.github.io/foundationdb/blob.html">storing large
blobs</a>, the data is usually split into 10 kB chunks stored in the
value. The respective key contain the byte offset of the chunk.</p>
<pre class="lang-fql query"><code>/blob(
<pre class="language-fql query"><code>/blob(
&quot;my file&quot;, % The identifier of the blob.
&lt;offset:int&gt;, % The byte offset within the blob.
)=&lt;chunk:bytes&gt; % A chunk of the blob.</code></pre>
<pre class="lang-fql result"><code>/blob(&quot;my file&quot;,0)=10e3_bytes
<pre class="language-fql result"><code>/blob(&quot;my file&quot;,0)=10e3_bytes
/blob(&quot;my file&quot;,10000)=10e3_bytes
/blob(&quot;my file&quot;,20000)=2.7e3_bytes</code></pre>
<blockquote>
Expand All @@ -584,20 +584,20 @@ <h2 id="aggregation">Aggregation</h2>
themselves. This can be done using aggregation queries.</p>
<p>FQL provides a pseudo data type named <code>agg</code> which
performs the aggregation.</p>
<pre class="lang-fql query"><code>/blob(&quot;my file&quot;,...)=&lt;blob:agg&gt;</code></pre>
<pre class="lang-fql result"><code>/blob(&quot;my file&quot;,...)=22.7e3_bytes</code></pre>
<pre class="language-fql query"><code>/blob(&quot;my file&quot;,...)=&lt;blob:agg&gt;</code></pre>
<pre class="language-fql result"><code>/blob(&quot;my file&quot;,...)=22.7e3_bytes</code></pre>
<p>Aggregation queries always result in a single key-value. With
non-aggregation queries, variables &amp; the <code>...</code> token
are resolved as actual data elements in the query results. For
aggregation queries, only aggregation variables are resolved.</p>
<p>A similar pseudo data type for summing integers could be provided
as well.</p>
<pre class="lang-fql query"><code>/deltas(&quot;group A&quot;,&lt;int&gt;)</code></pre>
<pre class="lang-fql result"><code>/deltas(&quot;group A&quot;,20)=nil
<pre class="language-fql query"><code>/deltas(&quot;group A&quot;,&lt;int&gt;)</code></pre>
<pre class="language-fql result"><code>/deltas(&quot;group A&quot;,20)=nil
/deltas(&quot;group A&quot;,-18)=nil
/deltas(&quot;group A&quot;,3)=nil</code></pre>
<pre class="lang-fql query"><code>/deltas(&quot;group A&quot;,&lt;sum&gt;)</code></pre>
<pre class="lang-fql result"><code>/deltas(&quot;group A&quot;,5)=&lt;&gt;</code></pre>
<pre class="language-fql query"><code>/deltas(&quot;group A&quot;,&lt;sum&gt;)</code></pre>
<pre class="language-fql result"><code>/deltas(&quot;group A&quot;,5)=&lt;&gt;</code></pre>
<h1 id="using-fql">Using FQL</h1>
<p>FQL can be used for exploring a Foundation DB cluster in a CLI
environment or programmatically as a Foundation DB <a
Expand Down
Loading

0 comments on commit 8fc6c39

Please sign in to comment.