mirror of
https://github.com/kristoferssolo/solorice.git
synced 2026-03-18 08:09:40 +00:00
Minor changes
This commit is contained in:
@@ -0,0 +1,620 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
|
||||
<meta charset="utf-8">
|
||||
|
||||
<style>
|
||||
|
||||
:root {
|
||||
--inputwidth: 80%;
|
||||
}
|
||||
|
||||
html * {
|
||||
font-size: 16px !important;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--vscode-editor-background);
|
||||
color: var(--vscode-editor-foreground);
|
||||
}
|
||||
|
||||
th {
|
||||
padding: 3px 8px;
|
||||
border-right: 1px solid;
|
||||
border-top: 1px solid;
|
||||
border-bottom: 1px solid;
|
||||
border-right-color: var(--vscode-window-activeBorder);
|
||||
border-top-color: var(--vscode-window-activeBorder);
|
||||
border-bottom-color: var(--vscode-window-activeBorder);
|
||||
position: sticky;
|
||||
top: 0;
|
||||
background-color: var(--vscode-editor-background);
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 3px 8px;
|
||||
background-color: var(--vscode-editor-background);
|
||||
border-right: 1px solid;
|
||||
border-bottom: 1px solid;
|
||||
border-right-color: var(--vscode-window-activeBorder);
|
||||
border-bottom-color: var(--vscode-window-activeBorder);
|
||||
}
|
||||
|
||||
table {
|
||||
display: block;
|
||||
white-space: nowrap;
|
||||
border-collapse: separate;
|
||||
background-color: var(--vscode-editor-background);
|
||||
}
|
||||
|
||||
|
||||
table th:first-child, table td:first-child {
|
||||
/* Apply a left border on the first <td> or <th> in a row */
|
||||
border-left: 1px solid;
|
||||
border-left-color: var(--vscode-window-activeBorder);
|
||||
}
|
||||
|
||||
|
||||
.padded_label {
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.code_sample {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
|
||||
#rbql_console {
|
||||
margin-top: 20px;
|
||||
}
|
||||
|
||||
.checkbox_input {
|
||||
background-color: var(--vscode-input-background);
|
||||
color: var(--vscode-input-foreground);
|
||||
margin-bottom: 6px;
|
||||
font-size: 14px !important;
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
}
|
||||
|
||||
|
||||
.select_input {
|
||||
background-color: var(--vscode-input-background);
|
||||
color: var(--vscode-input-foreground);
|
||||
margin-bottom: 6px;
|
||||
width: 300px;
|
||||
font-size: 14px !important;
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
}
|
||||
|
||||
#rbql_input {
|
||||
margin: 0px;
|
||||
height: 24px !important;
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
font-size: 14px !important;
|
||||
padding-left: 2px;
|
||||
background-color: var(--vscode-input-background);
|
||||
caret-color: var(--vscode-input-foreground);
|
||||
color: var(--vscode-input-foreground);
|
||||
display: inline-block;
|
||||
box-sizing: border-box; /* See css-submit-button-looks-smaller-than-text-input-and-textarea */
|
||||
vertical-align:middle;
|
||||
width: var(--inputwidth);
|
||||
}
|
||||
|
||||
#toggle_history_btn {
|
||||
margin: 0px;
|
||||
width: 28px;
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
height: 24px !important;
|
||||
padding: 0px;
|
||||
display: inline-block;
|
||||
border-width: 0px;
|
||||
outline:none;
|
||||
vertical-align:middle;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#toggle_history_btn:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
|
||||
#rbql_run_btn {
|
||||
margin: 0px;
|
||||
width: 70px;
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
height: 24px !important;
|
||||
padding: 0px;
|
||||
display: inline-block;
|
||||
outline:none;
|
||||
vertical-align:middle;
|
||||
box-sizing: border-box;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
#rbql_run_btn:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
|
||||
#help_btn {
|
||||
margin: 0px;
|
||||
width: 28px;
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
height: 24px !important;
|
||||
padding: 0px;
|
||||
display: inline-block;
|
||||
outline:none;
|
||||
vertical-align:middle;
|
||||
box-sizing: border-box;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
#help_btn:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
|
||||
#clear_history_btn {
|
||||
margin: 0px;
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
height: 24px !important;
|
||||
padding: 0px 5px 0px 5px;
|
||||
display: inline-block;
|
||||
float: right;
|
||||
outline:none;
|
||||
vertical-align:middle;
|
||||
border:none;
|
||||
}
|
||||
|
||||
#clear_history_btn:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.history_button {
|
||||
margin: 0px;
|
||||
width: 100%;
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
height: 24px !important;
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
font-size: 14px !important;
|
||||
border-width: 0px;
|
||||
outline: none;
|
||||
display: block;
|
||||
text-align: left;
|
||||
padding-left: 2px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.history_button:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
.navigation_button {
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
width: 28px;
|
||||
font-size: 18px !important;
|
||||
height: 28px;
|
||||
font-weight: bold;
|
||||
border-width: 0px;
|
||||
}
|
||||
|
||||
.navigation_button:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
|
||||
#udf_button {
|
||||
background-color: var(--vscode-button-secondaryBackground);
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
font-size: 14px !important;
|
||||
border-width: 0px;
|
||||
height: 24px !important;
|
||||
outline:none;
|
||||
vertical-align:middle;
|
||||
padding: 0px;
|
||||
padding-left: 12px;
|
||||
padding-right: 12px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
#udf_button:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
#enable_rfc_newlines_section {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rbql_help {
|
||||
width: 80%;
|
||||
top: 10%;
|
||||
left: 10%;
|
||||
height: 80%;
|
||||
z-index: 1000000;
|
||||
position: fixed;
|
||||
display: none;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
#close_help {
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
top: 10%;
|
||||
left: 90%;
|
||||
z-index: 1000010;
|
||||
position: fixed;
|
||||
font-size: 18px !important;
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
font-weight: bold;
|
||||
display: none;
|
||||
border-width: 0px;
|
||||
|
||||
}
|
||||
#close_help:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
|
||||
#rbql_help_text {
|
||||
margin-left: 2px;
|
||||
}
|
||||
|
||||
|
||||
#query_history {
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
font-size: 14px !important;
|
||||
width: var(--inputwidth);
|
||||
z-index: 1000000;
|
||||
background-color: var(--vscode-notifications-background);
|
||||
color: var(--vscode-notifications-foreground);
|
||||
position: fixed;
|
||||
display: none;
|
||||
border-top: 1px solid;
|
||||
border-left: 1px solid;
|
||||
border-right: 1px solid;
|
||||
border-color: var(--vscode-focusBorder);
|
||||
}
|
||||
|
||||
|
||||
#query_suggest{
|
||||
width: 200px;
|
||||
z-index: 1000010;
|
||||
background-color: var(--vscode-notifications-background);
|
||||
color: var(--vscode-notifications-foreground);
|
||||
position: fixed;
|
||||
display: none;
|
||||
border-top: 1px solid;
|
||||
border-left: 1px solid;
|
||||
border-right: 1px solid;
|
||||
border-color: var(--vscode-focusBorder);
|
||||
max-height: 300px;
|
||||
white-space: nowrap;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
#history_entries {
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
font-size: 14px !important;
|
||||
max-height: 300px;
|
||||
margin: 0px;
|
||||
overflow-x: auto;
|
||||
overflow-y: auto;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
|
||||
#query_history_header {
|
||||
font-size: 18px !important;
|
||||
height: 24px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
|
||||
#table_window {
|
||||
max-width: 95%;
|
||||
max-height: 350px;
|
||||
overflow: scroll;
|
||||
width:fit-content;
|
||||
/*border: 2px solid black;*/
|
||||
}
|
||||
|
||||
#rbql_error_message {
|
||||
width: 50%;
|
||||
top: 20%;
|
||||
left: 25%;
|
||||
z-index: 1000000;
|
||||
background-color: var(--vscode-notifications-background);
|
||||
color: var(--vscode-notifications-foreground);
|
||||
position: fixed;
|
||||
display: none;
|
||||
}
|
||||
|
||||
#rbql_error_message_header {
|
||||
background-color: var(--vscode-inputValidation-errorBackground);
|
||||
color: var(--vscode-inputValidation-errorForeground);
|
||||
font-size: 18px !important;
|
||||
height: 26px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#ack_error {
|
||||
width: 70px;
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
display: inline-block;
|
||||
border:none;
|
||||
font-size: 18px !important;
|
||||
height: 28px;
|
||||
}
|
||||
|
||||
#ack_error:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
#error_message_details {
|
||||
height: 100px;
|
||||
font-family: Consolas, Monaco, monospace;
|
||||
overflow: auto;
|
||||
border: 1px solid;
|
||||
border-color: var(--vscode-focusBorder);
|
||||
white-space: pre;
|
||||
margin: 5px;
|
||||
background-color: var(--vscode-notifications-background);
|
||||
color: var(--vscode-notifications-foreground);
|
||||
}
|
||||
|
||||
[type="checkbox"]
|
||||
{
|
||||
margin-left: 0px;
|
||||
vertical-align:middle;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
|
||||
<script src="contrib/textarea-caret-position/index.js"></script>
|
||||
<script src="rbql_suggest.js"></script>
|
||||
<script src="rbql_client.js"></script>
|
||||
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
|
||||
<div id="rbql_console">
|
||||
<div id="table_group">
|
||||
<div id="table_window">
|
||||
<table id="preview_table">
|
||||
</table>
|
||||
</div>
|
||||
<div id="navig_bar">
|
||||
<button class="navigation_button" title="Begin" id="go_begin">«</button>
|
||||
<button class="navigation_button" title="Back" id="go_backward">‹</button>
|
||||
<button class="navigation_button" title="Forward" id="go_forward">›</button>
|
||||
<button class="navigation_button" title="End" id="go_end">»</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="query_group" style="margin-top: 10px;">
|
||||
<!-- Do not remove the weird comments below, we need them to avoid spaces between inline elements, see https://css-tricks.com/fighting-the-space-between-inline-block-elements/ -->
|
||||
<input type="text" id="rbql_input" placeholder="Example: SELECT a1, a2 WHERE a2 != 'foobar' ORDER BY a1 LIMIT 10" autofocus><!--
|
||||
--><button id="toggle_history_btn" title="Query history">▲</button><!--
|
||||
--><button id="rbql_run_btn" title="Run query and open result set in a new tab">Run</button><!--
|
||||
--><button id="help_btn" title="Help">?</button>
|
||||
</div>
|
||||
<h3 style="margin-bottom: 6px; margin-top: 10px;">⚙ Query settings</h3>
|
||||
<div style="margin-left: 30px;">
|
||||
<div id="with_headers_section">
|
||||
<label style="word-wrap:break-word" title="Indicate that the input (and join) table has header in the first line"><input class="checkbox_input" id="with_headers" type="checkbox"/>Input table has header</label>
|
||||
</div>
|
||||
<div id="enable_rfc_newlines_section">
|
||||
<label style="word-wrap:break-word" title="This setting will not fix Rainbow syntax highlighting, but will allow RBQL to correctly handle multi-line (RFC-4180 - compatible) fields"><input class="checkbox_input" id="enable_rfc_newlines" type="checkbox"/>Enable double-quoted multiline fields</label>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span class="select_info">Output format</span>
|
||||
</div>
|
||||
<select class="select_input" id="select_output_format" title="Output table format">
|
||||
<option class="select_input" value="input">Same as input (Default)</option>
|
||||
<option class="select_input" value="csv">CSV</option>
|
||||
<option class="select_input" value="tsv">TSV</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span class="select_info">Encoding</span>
|
||||
</div>
|
||||
<select class="select_input" id="select_encoding" title="Input and output encoding">
|
||||
<option class="select_input" value="utf-8">UTF-8</option>
|
||||
<option class="select_input" value="latin-1">Binary/Latin-1</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
<span class="select_info">Backend language for RBQL</span>
|
||||
</div>
|
||||
<select class="select_input" id="select_backend_language">
|
||||
<option class="select_input" value="js">JavaScript</option>
|
||||
<option class="select_input" value="pyhon">Python (Requires python installed)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<button id="udf_button" title="Edit UDF (User Defined Functions) - will open a new tab with UDF file">Edit UDF...</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="query_history">
|
||||
<div id="query_history_header">
|
||||
<span class="padded_label">Query history</span>
|
||||
<button id="clear_history_btn">Clear history</button>
|
||||
</div>
|
||||
<div id="history_entries">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="query_suggest">
|
||||
</div>
|
||||
|
||||
|
||||
<div id="rbql_error_message">
|
||||
<div id="rbql_error_message_header">
|
||||
<span class="padded_label">⚠ Error while executing RBQL query!</span>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<span class="padded_label" id="error_message_header"></span>
|
||||
</div>
|
||||
<br>
|
||||
<div>
|
||||
<span class="padded_label">Details:</span>
|
||||
<br>
|
||||
<div id="error_message_details"></div>
|
||||
</div>
|
||||
<div style="display: flex; justify-content:center;">
|
||||
<button id="ack_error">OK</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<button id="close_help">X</button>
|
||||
<div id="rbql_help">
|
||||
<a href="https://rbql.org"><img src="rbql_logo.svg" alt="RBQL" width="200px" style="background-color:white;"/></a>
|
||||
<p><a href="https://github.com/mechatroner/vscode_rainbow_csv/blob/master/rbql_core/README.md#rbql-rainbow-query-language-description">Read RBQL documentation on github</a></p>
|
||||
<div id="rbql_help_text">
|
||||
<h1 id="rbql-rainbow-query-language">RBQL: Rainbow Query Language</h1>
|
||||
<p>RBQL is an eval-based SQL-like query engine for (not only) CSV file processing. It provides SQL-like language that supports SELECT queries with Python or JavaScript expressions. <br />
|
||||
RBQL is best suited for data transformation, data cleaning, and analytical queries. <br />
|
||||
RBQL is distributed with CLI apps, text editor plugins, Python and JS libraries. </p>
|
||||
<h3 id="main-features">Main Features</h3>
|
||||
<ul>
|
||||
<li>Use Python or JavaScript expressions inside <em>SELECT</em>, <em>UPDATE</em>, <em>WHERE</em> and <em>ORDER BY</em> statements</li>
|
||||
<li>Supports multiple input formats</li>
|
||||
<li>Result set of any query immediately becomes a first-class table on its own</li>
|
||||
<li>No need to provide FROM statement in the query - input table is defined by the current context</li>
|
||||
<li>Supports all main SQL keywords</li>
|
||||
<li>Supports aggregate functions and GROUP BY queries</li>
|
||||
<li>Supports user-defined functions (UDF)</li>
|
||||
<li>Provides some new useful query modes which traditional SQL engines do not have</li>
|
||||
<li>Lightweight, dependency-free, works out of the box</li>
|
||||
</ul>
|
||||
<h4 id="limitations">Limitations:</h4>
|
||||
<ul>
|
||||
<li>RBQL doesn't support nested queries, but they can be emulated with consecutive queries</li>
|
||||
<li>Number of tables in all JOIN queries is always 2 (input table and join table), use consecutive queries to join 3 or more tables</li>
|
||||
</ul>
|
||||
<h3 id="supported-sql-keywords-keywords-are-case-insensitive">Supported SQL Keywords (Keywords are case insensitive)</h3>
|
||||
<ul>
|
||||
<li>SELECT</li>
|
||||
<li>UPDATE</li>
|
||||
<li>WHERE</li>
|
||||
<li>ORDER BY … [ DESC | ASC ]</li>
|
||||
<li>[ LEFT | INNER ] JOIN</li>
|
||||
<li>DISTINCT</li>
|
||||
<li>GROUP BY</li>
|
||||
<li>TOP <em>N</em></li>
|
||||
<li>LIMIT <em>N</em></li>
|
||||
</ul>
|
||||
<p>All keywords have the same meaning as in SQL queries. You can check them <a href="https://www.w3schools.com/sql/default.asp">online</a> </p>
|
||||
<h3 id="rbql-variables">RBQL variables</h3>
|
||||
<p>RBQL for CSV files provides the following variables which you can use in your queries:</p>
|
||||
<ul>
|
||||
<li><em>a1</em>, <em>a2</em>,…, <em>a{N}</em> <br />
|
||||
Variable type: <strong>string</strong> <br />
|
||||
Description: value of i-th field in the current record in input table </li>
|
||||
<li><em>b1</em>, <em>b2</em>,…, <em>b{N}</em> <br />
|
||||
Variable type: <strong>string</strong> <br />
|
||||
Description: value of i-th field in the current record in join table B </li>
|
||||
<li><em>NR</em> <br />
|
||||
Variable type: <strong>integer</strong> <br />
|
||||
Description: Record number (1-based) </li>
|
||||
<li><em>NF</em> <br />
|
||||
Variable type: <strong>integer</strong> <br />
|
||||
Description: Number of fields in the current record </li>
|
||||
<li><em>a.name</em>, <em>b.Person_age</em>, … <em>a.{Good_alphanumeric_column_name}</em> <br />
|
||||
Variable type: <strong>string</strong> <br />
|
||||
Description: Value of the field referenced by it's "name". You can use this notation if the field in the header has a "good" alphanumeric name </li>
|
||||
<li><em>a["object id"]</em>, <em>a['9.12341234']</em>, <em>b["%$ !! 10 20"]</em> … <em>a["Arbitrary column name!"]</em> <br />
|
||||
Variable type: <strong>string</strong> <br />
|
||||
Description: Value of the field referenced by it's "name". You can use this notation to reference fields by arbitrary values in the header</li>
|
||||
</ul>
|
||||
<h3 id="update-statement">UPDATE statement</h3>
|
||||
<p><em>UPDATE</em> query produces a new table where original values are replaced according to the UPDATE expression, so it can also be considered a special type of SELECT query. This prevents accidental data loss from poorly written queries. <br />
|
||||
<em>UPDATE SET</em> is synonym to <em>UPDATE</em>, because in RBQL there is no need to specify the source table. </p>
|
||||
<h3 id="aggregate-functions-and-queries">Aggregate functions and queries</h3>
|
||||
<p>RBQL supports the following aggregate functions, which can also be used with <em>GROUP BY</em> keyword: <br />
|
||||
<em>COUNT</em>, <em>ARRAY_AGG</em>, <em>MIN</em>, <em>MAX</em>, <em>SUM</em>, <em>AVG</em>, <em>VARIANCE</em>, <em>MEDIAN</em> </p>
|
||||
<p>Limitation: aggregate functions inside Python (or JS) expressions are not supported. Although you can use expressions inside aggregate functions. <br />
|
||||
E.g. <code>MAX(float(a1) / 1000)</code> - valid; <code>MAX(a1) / 1000</code> - invalid. <br />
|
||||
There is a workaround for the limitation above for <em>ARRAY_AGG</em> function which supports an optional parameter - a callback function that can do something with the aggregated array. Example: <br />
|
||||
<code>select a2, ARRAY_AGG(a1, lambda v: sorted(v)[:5]) group by a2</code> - Python; <code>select a2, ARRAY_AGG(a1, v => v.sort().slice(0, 5)) group by a2</code> - JS</p>
|
||||
<h3 id="join-statements">JOIN statements</h3>
|
||||
<p>Join table B can be referenced either by its file path or by its name - an arbitrary string which the user should provide before executing the JOIN query. <br />
|
||||
RBQL supports <em>STRICT LEFT JOIN</em> which is like <em>LEFT JOIN</em>, but generates an error if any key in the left table "A" doesn't have exactly one matching key in the right table "B". <br />
|
||||
Limitation: <em>JOIN</em> statements can't contain Python/JS expressions and must have the following form: <em><JOIN_KEYWORD> (/path/to/table.tsv | table_name ) ON a… == b… [AND a… == b… [AND … ]]</em></p>
|
||||
<h3 id="select-except-statement">SELECT EXCEPT statement</h3>
|
||||
<p>SELECT EXCEPT can be used to select everything except specific columns. E.g. to select everything but columns 2 and 4, run: <code>SELECT * EXCEPT a2, a4</code> <br />
|
||||
Traditional SQL engines do not support this query mode.</p>
|
||||
<h3 id="unnest-operator">UNNEST() operator</h3>
|
||||
<p>UNNEST(list) takes a list/array as an argument and repeats the output record multiple times - one time for each value from the list argument. <br />
|
||||
Example: <code>SELECT a1, UNNEST(a2.split(';'))</code> </p>
|
||||
<h3 id="like-function">LIKE() function</h3>
|
||||
<p>RBQL does not support LIKE operator, instead it provides "like()" function which can be used like this:<br />
|
||||
<code>SELECT * where like(a1, 'foo%bar')</code></p>
|
||||
<h3 id="with-header-and-with-noheader-statements">WITH (header) and WITH (noheader) statements</h3>
|
||||
<p>You can set whether the input (and join) CSV file has a header or not using the environment configuration parameters which could be <code>--with_headers</code> CLI flag or GUI checkbox or something else.<br />
|
||||
But it is also possible to override this selection directly in the query by adding either <code>WITH (header)</code> or <code>WITH (noheader)</code> statement at the end of the query.<br />
|
||||
Example: <code>select top 5 NR, * with (header)</code></p>
|
||||
<h3 id="user-defined-functions-udf">User Defined Functions (UDF)</h3>
|
||||
<p>RBQL supports User Defined Functions <br />
|
||||
You can define custom functions and/or import libraries in two special files: </p>
|
||||
<ul>
|
||||
<li><code>~/.rbql_init_source.py</code> - for Python</li>
|
||||
<li><code>~/.rbql_init_source.js</code> - for JavaScript</li>
|
||||
</ul>
|
||||
<h2 id="examples-of-rbql-queries">Examples of RBQL queries</h2>
|
||||
<h4 id="with-python-expressions">With Python expressions</h4>
|
||||
<ul>
|
||||
<li><code>select top 100 a1, int(a2) * 10, len(a4) where a1 == "Buy" order by int(a2) desc</code></li>
|
||||
<li><code>select * order by random.random()</code> - random sort</li>
|
||||
<li><code>select len(a.vehicle_price) / 10, a2 where int(a.vehicle_price) < 500 and a['Vehicle type'] in ["car", "plane", "boat"] limit 20</code> - referencing columns by names from header and using Python's "in" to emulate SQL's "in"</li>
|
||||
<li><code>update set a3 = 'NPC' where a3.find('Non-playable character') != -1</code></li>
|
||||
<li><code>select NR, *</code> - enumerate records, NR is 1-based</li>
|
||||
<li><code>select * where re.match(".*ab.*", a1) is not None</code> - select entries where first column has "ab" pattern</li>
|
||||
<li><code>select a1, b1, b2 inner join ./countries.txt on a2 == b1 order by a1, a3</code> - example of join query</li>
|
||||
<li><code>select MAX(a1), MIN(a1) where a.Name != 'John' group by a2, a3</code> - example of aggregate query</li>
|
||||
<li><code>select *a1.split(':')</code> - Using Python3 unpack operator to split one column into many. Do not try this with other SQL engines!</li>
|
||||
</ul>
|
||||
<h4 id="with-javascript-expressions">With JavaScript expressions</h4>
|
||||
<ul>
|
||||
<li><code>select top 100 a1, a2 * 10, a4.length where a1 == "Buy" order by parseInt(a2) desc</code></li>
|
||||
<li><code>select * order by Math.random()</code> - random sort</li>
|
||||
<li><code>select top 20 a.vehicle_price.length / 10, a2 where parseInt(a.vehicle_price) < 500 && ["car", "plane", "boat"].indexOf(a['Vehicle type']) > -1 limit 20</code> - referencing columns by names from header</li>
|
||||
<li><code>update set a3 = 'NPC' where a3.indexOf('Non-playable character') != -1</code></li>
|
||||
<li><code>select NR, *</code> - enumerate records, NR is 1-based</li>
|
||||
<li><code>select a1, b1, b2 inner join ./countries.txt on a2 == b1 order by a1, a3</code> - example of join query</li>
|
||||
<li><code>select MAX(a1), MIN(a1) where a.Name != 'John' group by a2, a3</code> - example of aggregate query</li>
|
||||
<li><code>select ...a1.split(':')</code> - Using JS "destructuring assignment" syntax to split one column into many. Do not try this with other SQL engines!</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user