From 8bcf3adf80eaaf3fe022b8cdb7dc6abd7a503094 Mon Sep 17 00:00:00 2001 From: Tony Kuo <123580782+tonykploomber@users.noreply.github.com> Date: Fri, 18 Aug 2023 16:12:59 -0400 Subject: [PATCH] fix error when using `%sqlplot` in snowflake (#697) --- CHANGELOG.md | 1 + doc/integrations/snowflake.ipynb | 1703 +++++++++-------- src/sql/plot.py | 12 +- src/sql/util.py | 9 + .../integration/test_generic_db_operations.py | 7 +- 5 files changed, 892 insertions(+), 840 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89e294d16..912483de3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ * [API Change] Starting connections from a `.ini` file via `%sql [section_name]` has been deprecated * [Doc] Fixes documentation inaccuracy that said `:variable` was deprecated (we brought it back in `0.9.0`) * [Fix] Fix Twice message printing when switching to the current connection (#772) +* [Fix] Error when using %sqlplot in snowflake (#697) ## 0.9.1 (2023-08-10) diff --git a/doc/integrations/snowflake.ipynb b/doc/integrations/snowflake.ipynb index 3968fba22..f5d909e0b 100644 --- a/doc/integrations/snowflake.ipynb +++ b/doc/integrations/snowflake.ipynb @@ -1,833 +1,874 @@ { - "cells": [ - { - "cell_type": "markdown", - "id": "8a26f191", - "metadata": {}, - "source": [ - "# Snowflake\n", - "\n", - "```{important}\n", - "`snowflake-sqlalchemy` requires SQLAlchemy 1.x (as of version 1.4.7 )\n", - "```\n", - "\n", - "`Snowflake` is a cloud-based data warehousing platform that provides organizations with a powerful and flexible solution for storing, managing, and analyzing large amounts of data. Unlike traditional data warehouses, Snowflake operates entirely in the cloud, utilizing a distributed architecture that allows it to process and store data across multiple computing resources. \n", - "\n", - "In this guide, we'll demonstrate how to integrate with Snowflake using JupySQL magics.\n", - "\n", - "```{tip}\n", - "If you encounter any issues, feel free to join our [community](https://ploomber.io/community) and we'll be happy to help!\n", - "```" - ] - }, - { - "cell_type": "markdown", - "id": "14dc32cc", - "metadata": {}, - "source": [ - "## Pre-requisites\n", - "\n", - "We will need the `snowflake-sqlalchemy` package for connecting to the warehouse." - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "ac2a4ee0", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Note: you may need to restart the kernel to use updated packages.\n" - ] - } - ], - "source": [ - "%pip install --upgrade snowflake-sqlalchemy 'sqlalchemy<2' --quiet" - ] - }, - { - "cell_type": "markdown", - "id": "4629c09b", - "metadata": {}, - "source": [ - "Now let's define the URL connection parameters and create an `Engine` object." - ] - }, - { - "cell_type": "code", - "execution_count": 17, - "id": "b824fb60", - "metadata": {}, - "outputs": [], - "source": [ - "from sqlalchemy import create_engine\n", - "from snowflake.sqlalchemy import URL\n", - "\n", - "\n", - "engine = create_engine(\n", - " URL(\n", - " drivername=\"driver\",\n", - " user=\"user\",\n", - " password=\"password\",\n", - " account=\"account\",\n", - " database=\"database\",\n", - " role=\"role\",\n", - " schema=\"schema\",\n", - " warehouse=\"warehouse\",\n", - " )\n", - ")" - ] - }, - { - "cell_type": "markdown", - "id": "7853cb8d", - "metadata": {}, - "source": [ - "## Load sample data\n", - "\n", - "Now, let's load the `penguins` dataset. We'll convert this `.csv` file to a dataframe and create a table in Snowflake database from the data." - ] - }, - { - "cell_type": "code", - "execution_count": 3, - "id": "09b2ac9e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "('penguins.csv', )" - ] - }, - "execution_count": 3, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import urllib.request\n", - "\n", - "urllib.request.urlretrieve(\n", - " \"https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv\",\n", - " \"penguins.csv\",\n", - ")" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "id": "65ff0181", - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext sql" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "id": "803c43e4", - "metadata": {}, - "outputs": [], - "source": [ - "%sql engine --alias connection" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "3e364576", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "344" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "import pandas as pd\n", - "\n", - "df = pd.read_csv(\"penguins.csv\")\n", - "connection = engine.connect()\n", - "df.to_sql(name=\"penguins\", con=connection, index=False, if_exists=\"replace\")" - ] - }, - { - "cell_type": "markdown", - "id": "747f5239", - "metadata": {}, - "source": [ - "## Query" - ] - }, - { - "cell_type": "markdown", - "id": "494cbab2-a241-4e91-ae94-4ad6cb74c8ec", - "metadata": {}, - "source": [ - "List the tables in the database:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "23aa0941", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
Name
penguins
" - ], - "text/plain": [ - "+----------+\n", - "| Name |\n", - "+----------+\n", - "| penguins |\n", - "+----------+" - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%sqlcmd tables" - ] - }, - { - "cell_type": "markdown", - "id": "a1936edd-342e-476d-ae83-ab00749daa9b", - "metadata": {}, - "source": [ - "List columns in the penguins table:" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "1397fbb6", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
nametypenullabledefaultautoincrementcommentprimary_key
speciesVARCHAR(16777216)TrueNoneFalseNoneFalse
islandVARCHAR(16777216)TrueNoneFalseNoneFalse
bill_length_mmFLOATTrueNoneFalseNoneFalse
bill_depth_mmFLOATTrueNoneFalseNoneFalse
flipper_length_mmFLOATTrueNoneFalseNoneFalse
body_mass_gFLOATTrueNoneFalseNoneFalse
sexVARCHAR(16777216)TrueNoneFalseNoneFalse
" - ], - "text/plain": [ - "+-------------------+-------------------+----------+---------+---------------+---------+-------------+\n", - "| name | type | nullable | default | autoincrement | comment | primary_key |\n", - "+-------------------+-------------------+----------+---------+---------------+---------+-------------+\n", - "| species | VARCHAR(16777216) | True | None | False | None | False |\n", - "| island | VARCHAR(16777216) | True | None | False | None | False |\n", - "| bill_length_mm | FLOAT | True | None | False | None | False |\n", - "| bill_depth_mm | FLOAT | True | None | False | None | False |\n", - "| flipper_length_mm | FLOAT | True | None | False | None | False |\n", - "| body_mass_g | FLOAT | True | None | False | None | False |\n", - "| sex | VARCHAR(16777216) | True | None | False | None | False |\n", - "+-------------------+-------------------+----------+---------+---------------+---------+-------------+" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%sqlcmd columns --table penguins" - ] - }, - { - "cell_type": "markdown", - "id": "831ca098-a0f7-419b-ae96-b2c8b5026be6", - "metadata": {}, - "source": [ - "Query our data:" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "8f92b0f7", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "Running query in 'connection'" - ], - "text/plain": [ - "Running query in 'connection'" - ] - }, - "metadata": {}, - "output_type": "display_data" + "cells": [ + { + "cell_type": "markdown", + "id": "8a26f191", + "metadata": {}, + "source": [ + "# Snowflake\n", + "\n", + "```{important}\n", + "`snowflake-sqlalchemy` requires SQLAlchemy 1.x (as of version 1.4.7 )\n", + "```\n", + "\n", + "`Snowflake` is a cloud-based data warehousing platform that provides organizations with a powerful and flexible solution for storing, managing, and analyzing large amounts of data. Unlike traditional data warehouses, Snowflake operates entirely in the cloud, utilizing a distributed architecture that allows it to process and store data across multiple computing resources. \n", + "\n", + "In this guide, we'll demonstrate how to integrate with Snowflake using JupySQL magics.\n", + "\n", + "```{tip}\n", + "If you encounter any issues, feel free to join our [community](https://ploomber.io/community) and we'll be happy to help!\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "14dc32cc", + "metadata": {}, + "source": [ + "## Pre-requisites\n", + "\n", + "We will need the `snowflake-sqlalchemy` package for connecting to the warehouse." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "ac2a4ee0", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install --upgrade snowflake-sqlalchemy 'sqlalchemy<2' --quiet" + ] + }, + { + "cell_type": "markdown", + "id": "4629c09b", + "metadata": {}, + "source": [ + "Now let's define the URL connection parameters and create an `Engine` object." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "id": "b824fb60", + "metadata": {}, + "outputs": [], + "source": [ + "from sqlalchemy import create_engine\n", + "from snowflake.sqlalchemy import URL\n", + "\n", + "\n", + "engine = create_engine(\n", + " URL(\n", + " drivername=\"driver\",\n", + " user=\"user\",\n", + " password=\"password\",\n", + " account=\"account\",\n", + " database=\"database\",\n", + " role=\"role\",\n", + " schema=\"schema\",\n", + " warehouse=\"warehouse\",\n", + " )\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "7853cb8d", + "metadata": {}, + "source": [ + "## Load sample data\n", + "\n", + "Now, let's load the `penguins` dataset. We'll convert this `.csv` file to a dataframe and create a table in Snowflake database from the data." + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "id": "09b2ac9e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "('penguins.csv', )" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import urllib.request\n", + "\n", + "urllib.request.urlretrieve(\n", + " \"https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv\",\n", + " \"penguins.csv\",\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "id": "65ff0181", + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext sql" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "803c43e4", + "metadata": {}, + "outputs": [], + "source": [ + "%sql engine --alias connection" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "3e364576", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "344" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "df = pd.read_csv(\"penguins.csv\")\n", + "connection = engine.connect()\n", + "df.to_sql(name=\"penguins\", con=connection, index=False, if_exists=\"replace\")" + ] + }, + { + "cell_type": "markdown", + "id": "747f5239", + "metadata": {}, + "source": [ + "## Query" + ] + }, + { + "cell_type": "markdown", + "id": "494cbab2-a241-4e91-ae94-4ad6cb74c8ec", + "metadata": {}, + "source": [ + "List the tables in the database:" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "23aa0941", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
Name
penguins
" + ], + "text/plain": [ + "+----------+\n", + "| Name |\n", + "+----------+\n", + "| penguins |\n", + "+----------+" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%sqlcmd tables" + ] + }, + { + "cell_type": "markdown", + "id": "a1936edd-342e-476d-ae83-ab00749daa9b", + "metadata": {}, + "source": [ + "List columns in the penguins table:" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "1397fbb6", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
nametypenullabledefaultautoincrementcommentprimary_key
speciesVARCHAR(16777216)TrueNoneFalseNoneFalse
islandVARCHAR(16777216)TrueNoneFalseNoneFalse
bill_length_mmFLOATTrueNoneFalseNoneFalse
bill_depth_mmFLOATTrueNoneFalseNoneFalse
flipper_length_mmFLOATTrueNoneFalseNoneFalse
body_mass_gFLOATTrueNoneFalseNoneFalse
sexVARCHAR(16777216)TrueNoneFalseNoneFalse
" + ], + "text/plain": [ + "+-------------------+-------------------+----------+---------+---------------+---------+-------------+\n", + "| name | type | nullable | default | autoincrement | comment | primary_key |\n", + "+-------------------+-------------------+----------+---------+---------------+---------+-------------+\n", + "| species | VARCHAR(16777216) | True | None | False | None | False |\n", + "| island | VARCHAR(16777216) | True | None | False | None | False |\n", + "| bill_length_mm | FLOAT | True | None | False | None | False |\n", + "| bill_depth_mm | FLOAT | True | None | False | None | False |\n", + "| flipper_length_mm | FLOAT | True | None | False | None | False |\n", + "| body_mass_g | FLOAT | True | None | False | None | False |\n", + "| sex | VARCHAR(16777216) | True | None | False | None | False |\n", + "+-------------------+-------------------+----------+---------+---------------+---------+-------------+" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%sqlcmd columns --table penguins" + ] + }, + { + "cell_type": "markdown", + "id": "831ca098-a0f7-419b-ae96-b2c8b5026be6", + "metadata": {}, + "source": [ + "Query our data:" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "8f92b0f7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "Running query in 'connection'" + ], + "text/plain": [ + "Running query in 'connection'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "1 rows affected." + ], + "text/plain": [ + "1 rows affected." + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
COUNT(*)
344
" + ], + "text/plain": [ + "+----------+\n", + "| COUNT(*) |\n", + "+----------+\n", + "| 344 |\n", + "+----------+" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%sql\n", + "SELECT COUNT(*) FROM penguins " + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "082c9090", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "Running query in 'connection'" + ], + "text/plain": [ + "Running query in 'connection'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "3 rows affected." + ], + "text/plain": [ + "3 rows affected." + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
speciescount
Adelie152
Gentoo124
Chinstrap68
" + ], + "text/plain": [ + "+-----------+-------+\n", + "| species | count |\n", + "+-----------+-------+\n", + "| Adelie | 152 |\n", + "| Gentoo | 124 |\n", + "| Chinstrap | 68 |\n", + "+-----------+-------+" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%sql\n", + "SELECT species, COUNT(*) AS count\n", + "FROM penguins\n", + "GROUP BY species\n", + "ORDER BY count DESC" + ] + }, + { + "cell_type": "markdown", + "id": "972cf9e5", + "metadata": {}, + "source": [ + "## Parametrize queries\n", + "\n", + "JupySQL supports variable expansion in this format: `{{variable}}`." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "f3bad484", + "metadata": {}, + "outputs": [], + "source": [ + "dynamic_limit = 5\n", + "dynamic_column = \"island, sex\"" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "id": "aa7319e8", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "Running query in 'connection'" + ], + "text/plain": [ + "Running query in 'connection'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "5 rows affected." + ], + "text/plain": [ + "5 rows affected." + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
islandsex
TorgersenMALE
TorgersenFEMALE
TorgersenFEMALE
TorgersenNone
TorgersenFEMALE
" + ], + "text/plain": [ + "+-----------+--------+\n", + "| island | sex |\n", + "+-----------+--------+\n", + "| Torgersen | MALE |\n", + "| Torgersen | FEMALE |\n", + "| Torgersen | FEMALE |\n", + "| Torgersen | None |\n", + "| Torgersen | FEMALE |\n", + "+-----------+--------+" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%sql SELECT {{dynamic_column}} FROM penguins LIMIT {{dynamic_limit}}" + ] + }, + { + "cell_type": "markdown", + "id": "898f9f0c", + "metadata": {}, + "source": [ + "## CTEs\n", + "\n", + "Using JupySQL we can save query snippets, and use these saved snippets to form larger queries. Let's see CTEs in action:" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "a108569c", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "Running query in 'connection'" + ], + "text/plain": [ + "Running query in 'connection'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "Skipping execution..." + ], + "text/plain": [ + "Skipping execution..." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%%sql --save no_nulls --no-execute\n", + "SELECT *\n", + "FROM penguins\n", + "WHERE body_mass_g IS NOT NULL and\n", + "sex IS NOT NULL" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "6768b87e", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Generating CTE with stored snippets : no_nulls\n" + ] + }, + { + "data": { + "text/html": [ + "Running query in 'connection'" + ], + "text/plain": [ + "Running query in 'connection'" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "3 rows affected." + ], + "text/plain": [ + "3 rows affected." + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
islandavg_body_mass_g
Torgersen3708.5106382978724
Biscoe4719.171779141105
Dream3718.9024390243903
" + ], + "text/plain": [ + "+-----------+--------------------+\n", + "| island | avg_body_mass_g |\n", + "+-----------+--------------------+\n", + "| Torgersen | 3708.5106382978724 |\n", + "| Biscoe | 4719.171779141105 |\n", + "| Dream | 3718.9024390243903 |\n", + "+-----------+--------------------+" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%%sql\n", + "SELECT island, avg(body_mass_g) as avg_body_mass_g\n", + "FROM no_nulls\n", + "GROUP BY island;" + ] + }, + { + "cell_type": "markdown", + "id": "4a11d4f4", + "metadata": {}, + "source": [ + "The query gets compiled like so:" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "7bcf72de", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "WITH\n", + "SELECT *\n", + "FROM penguins\n", + "WHERE body_mass_g IS NOT NULL and\n", + "sex IS NOT NULL\n" + ] + } + ], + "source": [ + "final = %sqlcmd snippets no_nulls\n", + "print(final)" + ] + }, + { + "cell_type": "markdown", + "id": "8644b4a1-0f51-4d76-b348-29c8bff2c3be", + "metadata": {}, + "source": [ + "## Plotting\n" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "c739d88e-6593-41b6-998d-a453c6355590", + "metadata": { + "tags": [] + }, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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2rx5c7nuC1UHM0CwpEOHDumLL75wanvvvffk7e2tv/3tb5Vez8CBA+Xh4aFvv/1WXbp0KfBVWn369FF2drY2bdrk1L5y5cp8fS/9XzxKp1+/ftq+fbsj8ORZvny5atWq5bKPU1izZo3T7FF2drY+/PBD9erVS9WrV1etWrXUt29fHThwQO3bty/wuivtfwi6d+8uu92uVatWObXv3r073+3IvDD05ZdfOrWvX7++VPssjZCQEI0fP179+/d3ye1uuA9mgGBJwcHBuvnmmxUdHa2goCC988472rp1q+bMmeP0HEllCQsL07PPPqunn35a3333nW644QbVq1dPP//8sz7//HPVrl271B9UOHr0aL388ssaMWKE/vnPf+qqq67Spk2b9PHHH0uS03M47dq1kyTNmTNHgwYNUvXq1dW+fXvHLRgUbebMmfroo4/Ut29fPfPMM/Lz89O7776rDRs2aO7cufL19XVJXdWrV1f//v01efJk5ebmas6cOcrKynK6ll555RVde+216tWrlx555BGFhYUpOztbR44c0Ycffqjt27eXap9+fn6aPHmyYmNjVa9ePd1222364YcfFBMTo6CgIKfrrmvXrmrVqpWmTJmi8+fPq169elq7dq0+/fTTcjsHmZmZ6tu3r4YPH67WrVvL29tbe/bs0ebNm3X77beX235Q9RCAYEkdO3bU3//+d82cOVPJyckKDg7WSy+9pMcff9xlNUVFRalNmzZ65ZVXtGLFCuXk5CgwMFBdu3bVww8/XOrt1a5dW9u3b9ekSZP05JNPymazacCAAXrttdc0ePBgp693GD58uP7zn//otdde07PPPitjjFJSUir0qweuJK1atdKuXbv01FNPady4cTp9+rTCw8O1dOlSjRkzxmV1jR8/XmfOnNHEiROVkZGhtm3basOGDbrmmmscfdq0aaP9+/frH//4h6ZPn66MjAzVrVtXLVq0cDwHVFqzZs1S7dq1tWjRIi1dulStW7fWwoUL9fTTTztdd9WrV9eHH36o8ePH6+GHH5bdbtfdd9+t+fPnl9snsHt5eal79+56++23dfToUZ07d04hISGaOnWqnnzyyXLZB6ommzHGuLoIAJXnueee0/Tp05WamqrGjRu7uhxUgKNHj6pp06Z6/vnnNWXKFFeXI0lKSUlR69atNXPmTD311FOuLgdgBgi4ks2f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MwAAqPou6xmgffv26Z133tG7776rAwcOlHr8qVOn1KFDB82fP7/A9XPnztVLL72k+fPna8+ePQoMDFT//v2VnZ1d6DYTExM1bNgwjRw5Ul988YVGjhypu+66S5999lmp6wMAAFemMs0AZWRk6O6771Z8fLzq1q0rY4wyMzPVt29frVy5Ug0bNizRdgYNGqRBgwYVuM4Yo7i4OD399NOOZ47eeustBQQE6L333tNDDz1U4Li4uDj1799fUVFRkqSoqCglJCQoLi5OK1asKMPRAgCAK02ZZoAmTJigrKwsHTp0SL/99pt+//13ffXVV8rKytLEiRPLpbCUlBSlp6c7PVNkt9vVp08f7dq1q9BxiYmJ+Z5DGjhwYJFjAACAtZRpBmjz5s3atm2bwsPDHW1t2rTRggULyu0h6PT0dElSQECAU3tAQIC+//77IscVNCZvewXJyclRTk6OYzkrK6ssJQMAgCqiTAEoNzdXnp6e+do9PT2Vm5t72UVd7NLvHDPGFPk9ZGUZExsbq5iYmLIXCQCXIWzaBleXAFhOmW6BXXfddXrsscf0008/Odp+/PFHPf744+rXr1+5FBYYGChJ+WZuMjIy8s3wXDqutGOioqKUmZnpeKWlpV1G5QAAwN2VKQDNnz9f2dnZCgsLU/PmzXXVVVepadOmys7O1quvvlouhTVt2lSBgYHaunWro+3s2bNKSEhQz549Cx0XERHhNEaStmzZUuQYu90uHx8fpxcAALhylekWWJMmTbR//35t3bpV33zzjYwxatOmja6//vpSbefkyZM6cuSIYzklJUVJSUny8/NTSEiIJk2apOeee04tWrRQixYt9Nxzz6lWrVoaPny4Y8yoUaPUqFEjxcbGSpIee+wx9e7dW3PmzNEtt9yiDz74QNu2bdOnn35alkMFAABXoFIFoO3bt2v8+PHavXu3fHx81L9/f/Xv31+SlJmZqbZt22rRokXq1atXiba3d+9e9e3b17E8efJkSdLo0aO1bNkyPfnkkzp9+rQeffRRxwchbtmyRd7e3o4xqampqlbtr4msnj17auXKlZo+fbpmzJih5s2ba9WqVerevXtpDhUAAFzBShWA4uLi9OCDDxZ4i8jX11cPPfSQXnrppRIHoMjISBljCl1vs9kUHR2t6OjoQvvEx8fnaxs6dKiGDh1aohoAAID1lOoZoC+++EI3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vgUGAABQEQhAAADAcghAAADAcghAAADAcghAAADAcghAAADAcghAAADAcghAAADAcghAAADAcghAAADAcghAAADActz6y1BROfgOLwCA1TADBAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALIcABAAALMfD1QUAAFCUsGkbStTv6OwbK7gSXEmYAQIAAJZDAAIAAJZDAAIAAJbj1gEoNjZWXbt2lbe3t/z9/XXrrbfq8OHDRY6Jj4+XzWbL9/rmm28qqWoAAODu3DoAJSQkaNy4cdq9e7e2bt2q8+fPa8CAATp16lSxYw8fPqxjx445Xi1atKiEigEAQFXg1u8C27x5s9Py0qVL5e/vr3379ql3795FjvX391fdunUrsDoAAFBVufUM0KUyMzMlSX5+fsX27dSpk4KCgtSvXz/t2LGjoksDAABViFvPAF3MGKPJkyfr2muv1dVXX11ov6CgIC1evFidO3dWTk6O3n77bfXr10/x8fGFzhrl5OQoJyfHsZyVlVXu9QMAAPdRZQLQ+PHj9eWXX+rTTz8tsl+rVq3UqlUrx3JERITS0tL0wgsvFBqAYmNjFRMTU671AgAA91UlboFNmDBB69ev144dO9S4ceNSj+/Ro4eSk5MLXR8VFaXMzEzHKy0t7XLKBQAAbs6tZ4CMMZowYYLWrl2r+Ph4NW3atEzbOXDggIKCggpdb7fbZbfby1omAACoYtw6AI0bN07vvfeePvjgA3l7eys9PV2S5Ovrq5o1a0r6c/bmxx9/1PLlyyVJcXFxCgsLU9u2bXX27Fm98847Wr16tVavXu2y4wAAAO7FrQPQwoULJUmRkZFO7UuXLtWYMWMkSceOHVNqaqpj3dmzZzVlyhT9+OOPqlmzptq2basNGzZo8ODBlVU2AABwczZjjHF1Ee4mKytLvr6+yszMlI+Pj6vLqXAl/aZlAHBnfBs8SvP7u0o8BA0AAFCeCEAAAMBy3PoZIAAASqokt/NLcpusvLYD98YMEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwCEAAAsBwPVxdgRWHTNhTb5+jsG8tlOwCA8leZ//6W5PdBSZTX7x5321dZMQMEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAshwAEAAAsp0oEoNdee01NmzaVl5eXOnfurH//+99F9k9ISFDnzp3l5eWlZs2aadGiRZVUKQAAqArcPgCtWrVKkyZN0tNPP60DBw6oV69eGjRokFJTUwvsn5KSosGDB6tXr146cOCAnnrqKU2cOFGrV6+u5MoBAIC7cvsA9NJLL+n+++/XAw88oPDwcMXFxalJkyZauHBhgf0XLVqkkJAQxcXFKTw8XA888IDuu+8+vfDCC5VcOQAAcFduHYDOnj2rffv2acCAAU7tAwYM0K5duwock5iYmK//wIEDtXfvXp07d67CagUAAFWHh6sLKMqvv/6qCxcuKCAgwKk9ICBA6enpBY5JT08vsP/58+f166+/KigoKN+YnJwc5eTkOJYzMzMlSVlZWZd7CAXKzfmj2D4l2XdJtgMA+EtV/Le1vH4XldfvHnfbV0HbNMYU29etA1Aem83mtGyMyddWXP+C2vPExsYqJiYmX3uTJk1KW2q58Y1z2a4B4IpVFf9trcyar5R9ZWdny9fXt8g+bh2AGjRooOrVq+eb7cnIyMg3y5MnMDCwwP4eHh6qX79+gWOioqI0efJkx3Jubq5+++031a9fv8ighT9lZWWpSZMmSktLk4+Pj6vLqXI4f5eH83f5OIeXh/N3ecrz/BljlJ2dreDg4GL7unUAqlGjhjp37qytW7fqtttuc7Rv3bpVt9xyS4FjIiIi9OGHHzq1bdmyRV26dJGnp2eBY+x2u+x2u1Nb3bp1L694C/Lx8eGH/zJw/i4P5+/ycQ4vD+fv8pTX+Stu5iePWz8ELUmTJ0/WG2+8oSVLlujrr7/W448/rtTUVD388MOS/py9GTVqlKP/ww8/rO+//16TJ0/W119/rSVLlujNN9/UlClTXHUIAADAzbj1DJAkDRs2TMePH9ezzz6rY8eO6eqrr9bGjRsVGhoqSTp27JjTZwI1bdpUGzdu1OOPP64FCxYoODhY8+bN0x133OGqQwAAAG7G7QOQJD366KN69NFHC1y3bNmyfG19+vTR/v37K7gq5LHb7Zo5c2a+24goGc7f5eH8XT7O4eXh/F0eV50/mynJe8UAAACuIG7/DBAAAEB5IwABAADLIQABAADLIQABAADLIQChRBYuXKj27ds7PqgqIiJCmzZtcqwfM2aMbDab06tHjx4urNi9xcbGymazadKkSY42Y4yio6MVHBysmjVrKjIyUocOHXJdkW6soPPHNVi06OjofOcnMDDQsZ7rr2jFnT+uv5L58ccfNWLECNWvX1+1atVSx44dtW/fPsf6yrwOCUAokcaNG2v27Nnau3ev9u7dq+uuu0633HKL04V5ww036NixY47Xxo0bXVix+9qzZ48WL16s9u3bO7XPnTtXL730kubPn689e/YoMDBQ/fv3V3Z2tosqdU+FnT+Ja7A4bdu2dTo/Bw8edKzj+iteUedP4vorzu+//65rrrlGnp6e2rRpk/7v//5PL774otM3L1TqdWiAMqpXr5554403jDHGjB492txyyy2uLagKyM7ONi1atDBbt241ffr0MY899pgxxpjc3FwTGBhoZs+e7eh75swZ4+vraxYtWuSiat1PYefPGK7B4sycOdN06NChwHVcf8Ur6vwZw/VXElOnTjXXXnttoesr+zpkBgilduHCBa1cuVKnTp1SRESEoz0+Pl7+/v5q2bKlHnzwQWVkZLiwSvc0btw43Xjjjbr++uud2lNSUpSenq4BAwY42ux2u/r06aNdu3ZVdpluq7Dzl4drsGjJyckKDg5W06ZNdffdd+u7776TxPVXUoWdvzxcf0Vbv369unTpojvvvFP+/v7q1KmTXn/9dcf6yr4Oq8QnQcM9HDx4UBERETpz5ozq1KmjtWvXqk2bNpKkQYMG6c4771RoaKhSUlI0Y8YMXXfdddq3bx+fjvr/rVy5Uvv379eePXvyrUtPT5ckBQQEOLUHBATo+++/r5T63F1R50/iGixO9+7dtXz5crVs2VI///yz/vnPf6pnz546dOgQ118JFHX+6tevz/VXAt99950WLlyoyZMn66mnntLnn3+uiRMnym63a9SoUZV/HZb7nBKuWDk5OSY5Odns2bPHTJs2zTRo0MAcOnSowL4//fST8fT0NKtXr67kKt1Tamqq8ff3N0lJSY62i2/h/Oc//zGSzE8//eQ07oEHHjADBw6szFLdUnHnryBcg0U7efKkCQgIMC+++CLXXxlcfP4K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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%sqlplot histogram --table penguins --column bill_length_mm" + ] + }, + { + "cell_type": "markdown", + "id": "38d6711c", + "metadata": {}, + "source": [ + "## Clean up\n", + "\n", + "To ensure that the Python connector closes the session properly, execute `connection.close()` before `engine.dispose()`. This prevents the garbage collector from removing the resources required to communicate with Snowflake." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "20db062a", + "metadata": {}, + "outputs": [], + "source": [ + "connection.close()\n", + "engine.dispose()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + }, + "varInspector": { + "cols": { + "lenName": 16, + "lenType": 16, + "lenVar": 40 + }, + "kernels_config": { + "python": { + "delete_cmd_postfix": "", + "delete_cmd_prefix": "del ", + "library": "var_list.py", + "varRefreshCmd": "print(var_dic_list())" + }, + "r": { + "delete_cmd_postfix": ") ", + "delete_cmd_prefix": "rm(", + "library": "var_list.r", + "varRefreshCmd": "cat(var_dic_list()) " + } + }, + "types_to_exclude": [ + "module", + "function", + "builtin_function_or_method", + "instance", + "_Feature" + ], + "window_display": false + } }, - { - "data": { - "text/html": [ - "1 rows affected." - ], - "text/plain": [ - "1 rows affected." - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
COUNT(*)
344
" - ], - "text/plain": [ - "+----------+\n", - "| COUNT(*) |\n", - "+----------+\n", - "| 344 |\n", - "+----------+" - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%sql\n", - "SELECT COUNT(*) FROM penguins " - ] - }, - { - "cell_type": "code", - "execution_count": 10, - "id": "082c9090", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "Running query in 'connection'" - ], - "text/plain": [ - "Running query in 'connection'" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "3 rows affected." - ], - "text/plain": [ - "3 rows affected." - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
speciescount
Adelie152
Gentoo124
Chinstrap68
" - ], - "text/plain": [ - "+-----------+-------+\n", - "| species | count |\n", - "+-----------+-------+\n", - "| Adelie | 152 |\n", - "| Gentoo | 124 |\n", - "| Chinstrap | 68 |\n", - "+-----------+-------+" - ] - }, - "execution_count": 10, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%sql\n", - "SELECT species, COUNT(*) AS count\n", - "FROM penguins\n", - "GROUP BY species\n", - "ORDER BY count DESC" - ] - }, - { - "cell_type": "markdown", - "id": "972cf9e5", - "metadata": {}, - "source": [ - "## Parametrize queries\n", - "\n", - "JupySQL supports variable expansion in this format: `{{variable}}`." - ] - }, - { - "cell_type": "code", - "execution_count": 14, - "id": "f3bad484", - "metadata": {}, - "outputs": [], - "source": [ - "dynamic_limit = 5\n", - "dynamic_column = \"island, sex\"" - ] - }, - { - "cell_type": "code", - "execution_count": 15, - "id": "aa7319e8", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "Running query in 'connection'" - ], - "text/plain": [ - "Running query in 'connection'" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "5 rows affected." - ], - "text/plain": [ - "5 rows affected." - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
islandsex
TorgersenMALE
TorgersenFEMALE
TorgersenFEMALE
TorgersenNone
TorgersenFEMALE
" - ], - "text/plain": [ - "+-----------+--------+\n", - "| island | sex |\n", - "+-----------+--------+\n", - "| Torgersen | MALE |\n", - "| Torgersen | FEMALE |\n", - "| Torgersen | FEMALE |\n", - "| Torgersen | None |\n", - "| Torgersen | FEMALE |\n", - "+-----------+--------+" - ] - }, - "execution_count": 15, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%sql SELECT {{dynamic_column}} FROM penguins LIMIT {{dynamic_limit}}" - ] - }, - { - "cell_type": "markdown", - "id": "898f9f0c", - "metadata": {}, - "source": [ - "## CTEs\n", - "\n", - "Using JupySQL we can save query snippets, and use these saved snippets to form larger queries. Let's see CTEs in action:" - ] - }, - { - "cell_type": "code", - "execution_count": 11, - "id": "a108569c", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "Running query in 'connection'" - ], - "text/plain": [ - "Running query in 'connection'" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "Skipping execution..." - ], - "text/plain": [ - "Skipping execution..." - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], - "source": [ - "%%sql --save no_nulls --no-execute\n", - "SELECT *\n", - "FROM penguins\n", - "WHERE body_mass_g IS NOT NULL and\n", - "sex IS NOT NULL" - ] - }, - { - "cell_type": "code", - "execution_count": 12, - "id": "6768b87e", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Generating CTE with stored snippets : no_nulls\n" - ] - }, - { - "data": { - "text/html": [ - "Running query in 'connection'" - ], - "text/plain": [ - "Running query in 'connection'" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "3 rows affected." - ], - "text/plain": [ - "3 rows affected." - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
islandavg_body_mass_g
Torgersen3708.5106382978724
Biscoe4719.171779141105
Dream3718.9024390243903
" - ], - "text/plain": [ - "+-----------+--------------------+\n", - "| island | avg_body_mass_g |\n", - "+-----------+--------------------+\n", - "| Torgersen | 3708.5106382978724 |\n", - "| Biscoe | 4719.171779141105 |\n", - "| Dream | 3718.9024390243903 |\n", - "+-----------+--------------------+" - ] - }, - "execution_count": 12, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "%%sql\n", - "SELECT island, avg(body_mass_g) as avg_body_mass_g\n", - "FROM no_nulls\n", - "GROUP BY island;" - ] - }, - { - "cell_type": "markdown", - "id": "4a11d4f4", - "metadata": {}, - "source": [ - "The query gets compiled like so:" - ] - }, - { - "cell_type": "code", - "execution_count": 13, - "id": "7bcf72de", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "WITH\n", - "SELECT *\n", - "FROM penguins\n", - "WHERE body_mass_g IS NOT NULL and\n", - "sex IS NOT NULL\n" - ] - } - ], - "source": [ - "final = %sqlcmd snippets no_nulls\n", - "print(final)" - ] - }, - { - "cell_type": "markdown", - "id": "38d6711c", - "metadata": {}, - "source": [ - "## Clean up\n", - "\n", - "To ensure that the Python connector closes the session properly, execute `connection.close()` before `engine.dispose()`. This prevents the garbage collector from removing the resources required to communicate with Snowflake." - ] - }, - { - "cell_type": "code", - "execution_count": 16, - "id": "20db062a", - "metadata": {}, - "outputs": [], - "source": [ - "connection.close()\n", - "engine.dispose()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3 (ipykernel)", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - }, - "varInspector": { - "cols": { - "lenName": 16, - "lenType": 16, - "lenVar": 40 - }, - "kernels_config": { - "python": { - "delete_cmd_postfix": "", - "delete_cmd_prefix": "del ", - "library": "var_list.py", - "varRefreshCmd": "print(var_dic_list())" - }, - "r": { - "delete_cmd_postfix": ") ", - "delete_cmd_prefix": "rm(", - "library": "var_list.r", - "varRefreshCmd": "cat(var_dic_list()) " - } - }, - "types_to_exclude": [ - "module", - "function", - "builtin_function_or_method", - "instance", - "_Feature" - ], - "window_display": false - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} + "nbformat": 4, + "nbformat_minor": 5 +} \ No newline at end of file diff --git a/src/sql/plot.py b/src/sql/plot.py index 1cd94bf0a..9b16438a7 100644 --- a/src/sql/plot.py +++ b/src/sql/plot.py @@ -5,10 +5,13 @@ from ploomber_core.exceptions import modify_exceptions from jinja2 import Template - from sql import exceptions, display from sql.stats import _summary_stats -from sql.util import _are_numeric_values, validate_mutually_exclusive_args +from sql.util import ( + _are_numeric_values, + validate_mutually_exclusive_args, + to_upper_if_snowflake_conn, +) from sql.display import message try: @@ -551,6 +554,9 @@ def _histogram( conn = sql.connection.ConnectionManager.current use_backticks = conn.is_use_backtick_template() + # Snowflake will use UPPERCASE in the table and column name + column = to_upper_if_snowflake_conn(conn, column) + table = to_upper_if_snowflake_conn(conn, table) # FIXME: we're computing all the with elements twice min_, max_ = _min_max(conn, table, column, with_=with_, use_backticks=use_backticks) @@ -654,7 +660,7 @@ def _histogram( else: template_ = """ select - "{{column}}" as col, count ({{column}}) + "{{column}}" as col, count ("{{column}}") from "{{table}}" {{filter_query}} group by col diff --git a/src/sql/util.py b/src/sql/util.py index a8d91efcc..cb61e3d05 100644 --- a/src/sql/util.py +++ b/src/sql/util.py @@ -420,6 +420,15 @@ def get_line_content_from_toml(file_path, line_number): return eline, ekey, evalue +def to_upper_if_snowflake_conn(conn, upper): + return ( + upper.upper() + if callable(conn._get_sqlglot_dialect) + and conn._get_sqlglot_dialect() == "snowflake" + else upper + ) + + @requires(["toml"]) def load_toml(file_path): """ diff --git a/src/tests/integration/test_generic_db_operations.py b/src/tests/integration/test_generic_db_operations.py index 6c26e7ec9..c8ae6e220 100644 --- a/src/tests/integration/test_generic_db_operations.py +++ b/src/tests/integration/test_generic_db_operations.py @@ -313,18 +313,13 @@ def test_telemetry_execute_command_has_connection_info( ("ip_with_mariaDB"), ("ip_with_SQLite"), ("ip_with_duckDB"), + ("ip_with_Snowflake"), ("ip_with_duckDB_native"), ("ip_with_redshift"), pytest.param( "ip_with_MSSQL", marks=pytest.mark.xfail(reason="sqlglot does not support SQL server"), ), - pytest.param( - "ip_with_Snowflake", - marks=pytest.mark.xfail( - reason="Something wrong with sqlplot histogram in snowflake" - ), - ), ], ) def test_sqlplot_histogram(ip_with_dynamic_db, cell, request, test_table_name_dict):