| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,97 @@ | ||
| from __future__ import annotations # noqa: INP001 | ||
|
|
||
| import os | ||
| import re | ||
| from functools import partial | ||
|
|
||
| from algoliasearch.search_client import SearchClient | ||
|
|
||
| api_key = os.environ["ALGOLIA_WRITE_API_KEY"] | ||
| app_id = os.environ["ALGOLIA_APP_ID"] | ||
| index_name = os.environ["ALGOLIA_INDEX"] | ||
|
|
||
|
|
||
| # These are QMD files generated with help from Quartodoc. | ||
| API_QMDS = [ | ||
| "docs/reference/expression-collections.qmd", | ||
| "docs/reference/expression-generic.qmd", | ||
| "docs/reference/expression-geospatial.qmd", | ||
| "docs/reference/expression-numeric.qmd", | ||
| "docs/reference/expression-strings.qmd", | ||
| "docs/reference/expression-tables.qmd", | ||
| "docs/reference/expression-temporal.qmd", | ||
| ] | ||
|
|
||
|
|
||
| HORRID_REGEX = re.compile(r"\|\s*\[(\w+)\]\((#[\w.]+)\)\s*\|\s*(.*?)\s*\|") | ||
| # Given | [method](some-anchor) | some multiword description | | ||
| # this regex extracts ("method", "some-anchor", "some multiword description") | ||
|
|
||
|
|
||
| def _grab_qmd_methods(lines): | ||
| # All of the QMD files have a section that looks like: | ||
| # | ||
| # ## Methods | ||
| # | ||
| # | [method](anchor-ref) | description | | ||
| # ... | ||
| # | ||
| # ### method | ||
| # | ||
| # yes this is gross, but grab the lines between the `## Methods` and the | ||
| # first `###` and then smash it into a list | ||
| methods = lines[(fence := lines.find("## Methods")) : lines.find("###", fence)] | ||
| methods = [entry for entry in methods.split("\n") if entry.startswith("| [")] | ||
|
|
||
| # Now this in in the form: | ||
| # | [method name](#anchor-name) | Top-level description | | ||
| return methods | ||
|
|
||
|
|
||
| def _create_api_record_from_method_line(base_url, method): | ||
| # for e.g. `reference/expression-collections.html` we want to grab "Collections" | ||
| section = ( | ||
| base_url.removesuffix(".html") | ||
| .removeprefix("reference/expression-") | ||
| .capitalize() | ||
| ) | ||
| name, anchor, desc = re.match(HORRID_REGEX, method).groups() | ||
| record = { | ||
| "objectID": f"{base_url}{anchor}", | ||
| "href": f"{base_url}{anchor}", | ||
| "title": name, | ||
| "text": desc, | ||
| "crumbs": ["Expression API", "API", f"{section} expressions"], | ||
| } | ||
|
|
||
| return record | ||
|
|
||
|
|
||
| def main(): | ||
| client = SearchClient.create(app_id, api_key) | ||
| index = client.init_index(index_name) | ||
|
|
||
| records = [] | ||
| for qmd in API_QMDS: | ||
| # For each QMD file, get the table-section of the methods, anchors, and descriptions | ||
| with open(qmd) as f: | ||
| methods = _grab_qmd_methods(f.read()) | ||
|
|
||
| # Massage the QMD filename into the expected URL that prepends the anchor | ||
| # so we end up eventually with something like | ||
| # `reference/expression-collections.html#some-anchor` | ||
| base_url = f"{qmd.removeprefix('docs/').removesuffix('.qmd')}.html" | ||
|
|
||
| # Generate a dictionary for each row of the method table | ||
| _creator = partial(_create_api_record_from_method_line, base_url) | ||
| records += list(map(_creator, methods)) | ||
|
|
||
| # This saves the list of records to Algolia | ||
| # If the object IDs are new (which typically should be) this adds a new | ||
| # record to the Algolia index. If the object ID already exists, it gets | ||
| # updated with the new fields in the record dict | ||
| index.save_objects(records) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,3 +151,4 @@ docs/**/*.html | |
|
|
||
| # jupyterlite stuff | ||
| .jupyterlite.doit.db | ||
| docs/jupyter_lite_config.json | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,130 @@ | ||
| --- | ||
| title: "Operation support matrix" | ||
| format: dashboard | ||
| hide: | ||
| - toc | ||
| --- | ||
|
|
||
| ## {height=25%} | ||
|
|
||
| ::: {.card title="Welcome to the operation support matrix!"} | ||
|
|
||
| This is a [Quarto dashboard](https://quarto.org/docs/dashboards/) that shows | ||
| the operations each backend supports. | ||
|
|
||
| Due to differences in SQL dialects and upstream support for different | ||
| operations in different backends, support for the full breadth of the Ibis API | ||
| varies. | ||
|
|
||
| ::: {.callout-tip} | ||
| Backends with low coverage are good places to start contributing! | ||
|
|
||
| Each backend implements operations differently, but this is usually very | ||
| similar to other backends. If you want to start contributing to ibis, it's | ||
| a good idea to start by adding missing operations to backends that have low | ||
| operation coverage. | ||
| ::: | ||
|
|
||
| ::: | ||
|
|
||
| ### {width=25%} | ||
|
|
||
| ```{python} | ||
| #| content: valuebox | ||
| #| title: "Number of backends" | ||
| import ibis | ||
| dict( | ||
| value=len(ibis.util.backend_entry_points()), | ||
| color="info", | ||
| icon="signpost-split-fill", | ||
| ) | ||
| ``` | ||
|
|
||
| ### {width=25%} | ||
|
|
||
| ```{python} | ||
| #| content: valuebox | ||
| #| title: "Number of SQL backends" | ||
| import importlib | ||
| from ibis.backends.sql import SQLBackend | ||
| sql_backends = sum( | ||
| issubclass( | ||
| importlib.import_module(f"ibis.backends.{entry_point.name}").Backend, SQLBackend | ||
| ) | ||
| for entry_point in ibis.util.backend_entry_points() | ||
| ) | ||
| assert sql_backends > 0 | ||
| dict(value=sql_backends, color="green", icon="database") | ||
| ``` | ||
|
|
||
| ## {height=70%} | ||
|
|
||
| ```{python} | ||
| #| echo: false | ||
| import pandas as pd | ||
| import ibis | ||
| import ibis.expr.operations as ops | ||
| def make_support_matrix(): | ||
| """Construct the backend operation support matrix data.""" | ||
| from ibis.backends.sql.compiler import ALL_OPERATIONS | ||
| support_matrix_ignored_operations = (ops.ScalarParameter,) | ||
| public_ops = ALL_OPERATIONS.difference(support_matrix_ignored_operations) | ||
| assert public_ops | ||
| support = {"Operation": [f"{op.__module__}.{op.__name__}" for op in public_ops]} | ||
| support.update( | ||
| (backend, list(map(getattr(ibis, backend).has_operation, public_ops))) | ||
| for backend in sorted(ep.name for ep in ibis.util.backend_entry_points()) | ||
| ) | ||
| def make_link(parts): | ||
| module, op = parts[-2:] | ||
| return f'<a href="./operations.html#ibis.expr.operations.{module}.{op}">{op}</a>' | ||
| support_matrix = ( | ||
| pd.DataFrame(support) | ||
| .assign(splits=lambda df: df.Operation.str.findall("[a-zA-Z_][a-zA-Z_0-9]*")) | ||
| .assign( | ||
| Category=lambda df: df.splits.str[-2], | ||
| Operation=lambda df: df.splits.map(make_link), | ||
| ) | ||
| .drop(["splits"], axis=1) | ||
| .set_index(["Category", "Operation"]) | ||
| .sort_index() | ||
| ) | ||
| all_visible_ops_count = len(support_matrix) | ||
| assert all_visible_ops_count | ||
| coverage = pd.Index( | ||
| support_matrix.sum() | ||
| .map(lambda n: f"{n} ({round(100 * n / all_visible_ops_count)}%)") | ||
| .T | ||
| ) | ||
| support_matrix.columns = pd.MultiIndex.from_tuples( | ||
| list(zip(support_matrix.columns, coverage)), names=("Backend", "API coverage") | ||
| ) | ||
| return support_matrix | ||
| ``` | ||
|
|
||
| ```{python} | ||
| from itables import show | ||
| matrix = make_support_matrix() | ||
| show( | ||
| matrix.replace({True: "✔", False: "🚫"}), | ||
| ordering=False, | ||
| paging=False, | ||
| buttons=["copy", "excel", "csv"], | ||
| ) | ||
| ``` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| {{< include ../../reference/operations.qmd >}} |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| # Contribute | ||
|
|
||
| Check out our [contributing guide](../CONTRIBUTING.md) for details! Guides for setting up an environment and getting started are here. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| --- | ||
| title: "Unlocking data insights with Ibis and SQLMesh" | ||
| author: "Chloe He" | ||
| date: "2024-05-21" | ||
| image: thumbnail.png | ||
| categories: | ||
| - blog | ||
| - sqlmesh | ||
| - data engineering | ||
| --- | ||
|
|
||
| # Overview | ||
|
|
||
| Have you ever needed to learn new dialects of database languages as a data | ||
| scientist or struggled with the differences between database languages? Does | ||
| your company manage different production pipelines with multiple databases | ||
| or engines? Have you needed to rewrite data pipelines from experimentation | ||
| to deployment? | ||
|
|
||
| These are challenges that SQLMesh and Ibis together can solve. | ||
|
|
||
| [SQLMesh](https://sqlmesh.com/) is a next-generation data transformation | ||
| and modeling framework. It aims to be easy to use, correct, and efficient | ||
| and is maintained by the [Tobiko Data](https://tobikodata.com/) team. It | ||
| helps you scalably, reliably and safely modify your data pipelines because | ||
| it understands SQL and can make intelligent updates instead of stringing | ||
| scripts together. SQLMesh boasts several future-proof features such as | ||
| automatic data contracts, virtual data environments and snapshots, extensive | ||
| change summaries (before updates are applied!) and column-level lineage out | ||
| of the box. | ||
|
|
||
| We walk through an example together to show you how to harness the full | ||
| potential of your data analytics workflow and how SQLMesh and Ibis can work | ||
| together hand-in-hand. Read the full article on | ||
| [SQLMesh blog](https://tobikodata.com/ibis-sqlmesh-unlocking-data-insights.html)! | ||
|
|
||
| In today's data-driven world, the ability to efficiently analyze and derive | ||
| insights from vast amounts of data is paramount. Leveraging powerful | ||
| open-source tools like SQLMesh and Ibis can streamline this process, | ||
| enabling you to easily manipulate and query data. | ||
|
|
||
| Let us know how you're using SQLMesh and Ibis together in your use case! |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,355 @@ | ||
| --- | ||
| title: "Test 20 databases on every commit" | ||
| subtitle: "It's not hyperbole" | ||
| author: | ||
| - Phillip Cloud | ||
| execute: | ||
| echo: true | ||
| format: | ||
| revealjs: | ||
| footer: <https://ibis-project.org> | ||
| # https://quarto.org/docs/presentations/revealjs/themes.html#using-themes | ||
| --- | ||
|
|
||
| ## Who | ||
|
|
||
| :::: {.columns} | ||
|
|
||
| ::: {.column width="50%"} | ||
| ### Me | ||
|
|
||
| - Phillip Cloud | ||
| - Ibis project | ||
| - Voltron Data | ||
| - Data tools for 10+ years | ||
| ::: | ||
|
|
||
| ::: {.column width="50%"} | ||
| ### Where | ||
|
|
||
| - {{< fa brands github >}} [`@cpcloud`](https://github.com/cpcloud) | ||
| - {{< fa brands youtube >}} [Phillip in the Cloud](https://www.youtube.com/@cpcloud) | ||
| - {{< fa brands twitter >}} [`@cpcloudy`](https://x.com/cpcloudy) | ||
| ::: | ||
|
|
||
| :::: | ||
|
|
||
| # What | ||
|
|
||
| ## Maybe this is you | ||
|
|
||
| {fig-align="center"} | ||
|
|
||
| ## Or this | ||
|
|
||
| {fig-align="center"} | ||
|
|
||
| ## Or maybe even this | ||
|
|
||
| {fig-align="center"} | ||
|
|
||
| ## Not earth shattering | ||
|
|
||
| :::: {.columns} | ||
|
|
||
| ::: {.column width="50%"} | ||
| ### Overview | ||
|
|
||
| - What we learned about maintenance | ||
| - Day to day of 20+ databases | ||
| - Unique challenges | ||
| ::: | ||
|
|
||
| ::: {.column width="50%"} | ||
| ### Tools | ||
|
|
||
| - Docker | ||
| - Packaging | ||
| - CI | ||
| - `pytest` plugins | ||
| ::: | ||
| :::: | ||
|
|
||
| # Overview of Ibis | ||
|
|
||
| ## Ibis is a Python library for: | ||
|
|
||
| - Exploratory data analysis (EDA) | ||
| - Analytics | ||
| - Data engineering | ||
| - ML preprocessing | ||
| - Building your own DataFrame lib | ||
|
|
||
| ::: {.r-fit-text} | ||
| _Dev to prod with the same API_ | ||
| ::: | ||
|
|
||
| ## One API, 20+ backends {.smaller .scrollable} | ||
|
|
||
| ```{python} | ||
| #| code-fold: true | ||
| #| echo: false | ||
| import ibis | ||
| ibis.options.interactive = True | ||
| t = ibis.examples.penguins.fetch() | ||
| t.to_parquet("penguins.parquet") | ||
| ``` | ||
|
|
||
| ::: {.panel-tabset} | ||
|
|
||
| ## DuckDB | ||
|
|
||
| ```{python} | ||
| con = ibis.connect("duckdb://") | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t = con.read_parquet("penguins.parquet") | ||
| t.head(3) | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t.group_by("species", "island").agg(count=t.count()).order_by("count") | ||
| ``` | ||
|
|
||
| ## Polars | ||
|
|
||
| ```{python} | ||
| con = ibis.connect("polars://") | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t = con.read_parquet("penguins.parquet") | ||
| t.head(3) | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t.group_by("species", "island").agg(count=t.count()).order_by("count") | ||
| ``` | ||
|
|
||
| ## DataFusion | ||
|
|
||
| ```{python} | ||
| con = ibis.connect("datafusion://") | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t = con.read_parquet("penguins.parquet") | ||
| t.head(3) | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t.group_by("species", "island").agg(count=t.count()).order_by("count") | ||
| ``` | ||
|
|
||
| ## PySpark | ||
|
|
||
| ```{python} | ||
| con = ibis.connect("pyspark://") | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t = con.read_parquet("penguins.parquet") | ||
| t.head(3) | ||
| ``` | ||
|
|
||
| ```{python} | ||
| t.group_by("species", "island").agg(count=t.count()).order_by("count") | ||
| ``` | ||
|
|
||
| ## 16+ other things | ||
|
|
||
| {fig-align="center" width="100%" height="100%"} | ||
|
|
||
| ::: | ||
|
|
||
| ## How it works | ||
|
|
||
| ```{python} | ||
| #| echo: false | ||
| #| fig-align: center | ||
| import os | ||
| import sys | ||
| sys.path.append(os.path.abspath("../..")) | ||
| from backends_sankey import fig | ||
| fig.show() | ||
| ``` | ||
|
|
||
| # What's in an Ibis? | ||
|
|
||
| ## By the numbers {.smaller} | ||
|
|
||
| :::: {.columns} | ||
| ::: {.column width="50%"} | ||
| ### Backends | ||
| - **17** SQL | ||
| - **3** non-SQL | ||
| - **2** cloud | ||
| ::: | ||
|
|
||
| ::: {.column width="50%"} | ||
| ### Engines + APIs | ||
| - **9** distributed SQL | ||
| - **3** dataframe | ||
| - oldest: **~45** years 👀 | ||
| - youngest: **~2** years | ||
| ::: | ||
| :::: | ||
|
|
||
| ### Other facts | ||
|
|
||
| - Latency is variable | ||
| - Deployment models vary | ||
|
|
||
| ::: {.fragment} | ||
| ::: {.r-fit-text} | ||
| _… **Feature development**_❓ | ||
| ::: | ||
| ::: | ||
|
|
||
| ## Bit of a pickle | ||
|
|
||
|  | ||
|
|
||
| # How | ||
|
|
||
| ## High level | ||
|
|
||
| ### Goal: fast iteration | ||
|
|
||
| - fast env setup (dependency management) | ||
| - fast(ish) tests (test-running library) | ||
| - high **job** concurrency (ci/provider) | ||
| - **easy to run**: dev speed ([`just`](https://github.com/casey/just)) | ||
|
|
||
| ::: {.fragment} | ||
| ::: {.r-fit-text} | ||
| _CI must complete "quickly"_ | ||
| ::: | ||
| ::: | ||
|
|
||
| ## Tools: overview | ||
|
|
||
| - 📦 poetry | ||
| - 🖥️ GitHub Actions | ||
| - 🦁 docker | ||
| - 🐕 docker | ||
| - 🐱 no special tx (duckdb, polars) | ||
| - 🏃 task runner (e.g.: `just up postgres`) | ||
|
|
||
| ## Tools: poetry | ||
|
|
||
| ::: {.callout-warning} | ||
| ## Opinions follow | ||
| ::: | ||
|
|
||
| - **Env setup needs to be _fast_**: avoid constraint solving | ||
| - Poetry is one way; there are others | ||
| - Get yourself a lockfile | ||
| - Downsides? | ||
|
|
||
| ::: {.fragment} | ||
| ::: {.r-fit-text} | ||
| … _Are you doing that **now**_❓ | ||
| ::: | ||
| ::: | ||
|
|
||
| ## This plot | ||
|
|
||
| ::: {layout="[[-1], [1], [-1]]"} | ||
|
|
||
| {fig-align="center"} | ||
|
|
||
| ::: | ||
|
|
||
| ::: {.fragment} | ||
| ::: {.r-fit-text} | ||
| _We've added 3 or 4 new backends since the switch_ | ||
| ::: | ||
| ::: | ||
|
|
||
| ## Tools: docker | ||
|
|
||
| - Sure, docker | ||
| - But, do you to use it locally? | ||
| - Use health checks; "dumb" ones are fine | ||
| - Make it easy for devs to use | ||
|
|
||
| ## Tools: GitHub Actions {.smaller} | ||
|
|
||
| ::: {.callout-note} | ||
| ### I don't work for GitHub | ||
| ::: | ||
|
|
||
| - Pay for the [the Teams plan](https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration#usage-limits) to get more concurrency | ||
| - Automate dependency updates | ||
|
|
||
| ::: {.columns} | ||
| ::: {.column width="50%"} | ||
| ### GHA concurrency limits | ||
|
|
||
|  | ||
| ::: | ||
|
|
||
| ::: {.column width="50%"} | ||
| ### Ibis CI cost | ||
|
|
||
|  | ||
| ::: | ||
| ::: | ||
|
|
||
| ## `pytest` {.smaller} | ||
|
|
||
| ### Ibis problems | ||
|
|
||
| - Tests run across **ALL** backends | ||
| - Backends don't implement the same stuff | ||
| - Need to know when backend passes | ||
| - Answer questions like: "will it _ever_ blend?" | ||
|
|
||
| ::: {.fragment} | ||
| ### Markers + hooks | ||
|
|
||
| ```python | ||
| @pytest.mark.never("duckdb") # never gonna happen | ||
| @pytest.mark.notyet("impala") # might happen | ||
| @pytest.mark.notimpl("snowflake") # ibis devs: do some work | ||
| def test_soundex(): | ||
| ... | ||
|
|
||
| def pytest_ignore_collect(...): | ||
| # pytest -m duckdb: don't collect things that aren't marked duckdb | ||
| ... | ||
| ``` | ||
| ::: | ||
|
|
||
| ## `pytest` plugins you may like | ||
|
|
||
| **`pytest-`** | ||
|
|
||
| - `xdist`: make this work if you can | ||
| - `randomly`: break your bogus stateful assumptions | ||
| - `repeat`: when `randomly` exposes your assumptions | ||
| - `clarity`: readable test failure messages | ||
| - `snapshot`: better than the giant `f`-string you just wrote | ||
|
|
||
| **hypothesis** 👈 that too, we don't use it enough | ||
|
|
||
| ## Why `pytest-randomly`? | ||
|
|
||
| {fig-align="center"} | ||
|
|
||
| # Summary | ||
|
|
||
| - Use docker for dev **and** prod | ||
| - Lock your dependencies (dev only!) | ||
| - Auto update stuff | ||
| - `pytest` probably has a thing for that | ||
| - Spend time on dev ex | ||
| - Track CI run durations, look at them too | ||
|
|
||
| # Questions? |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| approx_quantiles(IF(`t0`.`month` > 0, `t0`.`double_col`, NULL), IF(`t0`.`month` > 0, 2, NULL))[offset(1)] AS `ApproxMedian_double_col_Greater_month_0` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| APPROX_COUNT_DISTINCT(IF(`t0`.`month` > 0, `t0`.`double_col`, NULL)) AS `ApproxCountDistinct_double_col_Greater_month_0` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| CAST(`t0`.`value` AS BYTES) AS `Cast_value_binary` | ||
| FROM `t` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| bit_and(IF(`t0`.`bigint_col` > 0, `t0`.`int_col`, NULL)) AS `BitAnd_int_col_Greater_bigint_col_0` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| bit_or(IF(`t0`.`bigint_col` > 0, `t0`.`int_col`, NULL)) AS `BitOr_int_col_Greater_bigint_col_0` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| bit_xor(IF(`t0`.`bigint_col` > 0, `t0`.`int_col`, NULL)) AS `BitXor_int_col_Greater_bigint_col_0` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| AVG(IF(`t0`.`month` > 6, CAST(`t0`.`bool_col` AS INT64), NULL)) AS `Mean_bool_col_Greater_month_6` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| CAST(trunc(`t0`.`double_col`) AS INT64) AS `Cast_double_col_int64` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| COVAR_POP(`t0`.`double_col`, `t0`.`double_col`) AS `Covariance_double_col_double_col` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,3 @@ | ||
| SELECT | ||
| COVAR_SAMP(`t0`.`double_col`, `t0`.`double_col`) AS `Covariance_double_col_double_col` | ||
| FROM `functional_alltypes` AS `t0` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| SELECT | ||
| MOD(EXTRACT(dayofweek FROM DATE(2017, 1, 1)) + 5, 7) AS `DayOfWeekIndex_datetime_date_2017_1_1` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| SELECT | ||
| INITCAP(CAST(DATE(2017, 1, 1) AS STRING FORMAT 'DAY')) AS `DayOfWeekName_datetime_date_2017_1_1` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| SELECT | ||
| MOD(EXTRACT(dayofweek FROM datetime('2017-01-01T04:55:59')) + 5, 7) AS `DayOfWeekIndex_datetime_datetime_2017_1_1_4_55_59` |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,2 @@ | ||
| SELECT | ||
| INITCAP(CAST(datetime('2017-01-01T04:55:59') AS STRING FORMAT 'DAY')) AS `DayOfWeekName_datetime_datetime_2017_1_1_4_55_59` |