Repository: ploomber/jupysql
Pull request #385 (2023-04-06 21:55:26)

Improve connecting tutorial
## Describe your changes

Added intro and conclusion
Included various mechanisms and database options

## Issue ticket number and link
Closes https://github.com/ploomber/jupysql/issues/284

## Checklist before requesting a review

- [x] I have performed a self-review of my code
- [x] I have added thorough [tests](https://github.com/ploomber/contributing/blob/main/CONTRIBUTING.md#testing) (when necessary).
- [x] I have added the right documentation in the [docstring](https://github.com/ploomber/contributing/blob/main/CONTRIBUTING.md#documenting-changes-and-new-features) and [changelog](https://github.com/ploomber/contributing/blob/main/CONTRIBUTING.md#changelog) (when needed)


Preview https://jupysql--385.org.readthedocs.build/en/385/connecting.html


lfunderburk: Hello @edublancas  and @idomic 

Resolved feedback pointers. The only issue left is whether to include this https://github.com/ploomber/jupysql/pull/350 and if so, how to best present it. 

I suggested the following. I need advise from you on a different approach if this is not satisfactory

> JupySQL's next goal is to provide support for custom connections that are not directly supported by SQLAlchemy. This allows users to run JupySQL functionality, such as `%sql`, `%sqlcmd`, `%sqlplot`, `%sqlrender`, and the ggplot API, without causing disruptions to the existing API or registering a new dialect.
> 
> **Note** This feature is still under development, and improvements are being made to provide more seamless integration with custom database connections.
edublancas: @lfunderburk: I think let's leave this paragraph out for now. once we merge the functionality, we can revisit this and add the paragraph

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e3158ef..d4376cc 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,7 @@
 # CHANGELOG
 
 ## 0.7.1dev
+* [Fix] Fix `%sqlcmd columns` in MySQL and MariaDB
 * [Doc] Updating connecting guide (by @DaveOkpare) (#56)
 
 * [Feature] Upgrades SQLAlchemy version to 2
diff --git a/doc/connecting.md b/doc/connecting.md
index 6979161..b207884 100644
--- a/doc/connecting.md
+++ b/doc/connecting.md
@@ -19,11 +19,17 @@ myst:
     property=og:locale: "en_US"
 ---
 
-# Connecting
+# Connecting to Databases with JupySQL
 
-Connection strings are [SQLAlchemy URL](http://docs.sqlalchemy.org/en/latest/core/engines.html#database-urls) standard.
+Learn how to connect to various databases using JupySQL in this tutorial. JupySQL is a Jupyter Notebook extension that allows you to execute SQL queries directly in your notebook cells. We'll show you how to establish connections, connect securely, and use existing `sqlalchemy.engine.Engine` instances.
 
-Some example connection strings:
+## Establishing a connection 
+
+### Connect with SQLAlchemy
+
+Connection strings follow the SQLAlchemy URL standard. 
+
+Here are some example connection strings for various databases:
 
 ```
 mysql+pymysql://scott:tiger@localhost/foo
@@ -33,15 +39,13 @@ sqlite:///foo.db
 mssql+pyodbc://username:password@host/database?driver=SQL+Server+Native+Client+11.0
 ```
 
-Note that `mysql` and `mysql+pymysql` connections (and perhaps others)
-don't read your client character set information from .my.cnf.  You need
-to specify it in the connection string::
+**Note:** `mysql` and `mysql+pymysql` connections (and perhaps others) don't read your client character set information from `.my.cnf.` You need to specify it in the connection string:
 
 ```
 mysql+pymysql://scott:tiger@localhost/foo?charset=utf8
 ```
 
-Note that an `impala` connection with [`impyla`](https://github.com/cloudera/impyla) for HiveServer2 requires disabling autocommit::
+For an `impala` connection with [`impyla`](https://github.com/cloudera/impyla) for HiveServer2, you need to disable autocommit:
 
 ```
 %config SqlMagic.autocommit=False
@@ -61,15 +65,21 @@ a flag with (-a|--connection_arguments)the connection string as a JSON string. S
 
 +++
 
-## Connecting to...
+## Connecting to Databases
 
 Check out our guide for connecting to a database:
 
 - [PostgreSQL](integrations/postgres-connect)
+- [ClickHouse](integrations/clickhouse)
+- [MariaDB](integrations/mariadb)
+- [MindsDB](integrations/mindsdb)
+- [MSSQL](integrations/mssql)
+- [MySQL](integrations/mysql)
 
 +++
 
-## Connecting securely
+## Secure Connections
+
 
 **It is highly recommended** that you do not pass plain credentials.
 
@@ -106,7 +116,7 @@ then you can establish a connection to your database by running the following co
 
 +++
 
-### Building connection string
+### Building connection strings
 
 One option is to use `getpass`, type your password, build your connection string and pass it to `%sql`:
 
@@ -126,7 +136,7 @@ connection_string = f"postgresql://user:{password}@localhost/database"
 
 +++
 
-You may also set the `DATABASE_URL` environment variable, and `%sql` will automatically load it from there. You can do it either by setting the environment variable from your terminal or in your notebook:
+Alternatively, set the `DATABASE_URL` environment variable, and `%sql` will automatically load it. You can do this either by setting the environment variable from your terminal or in your notebook:
 
 ```python
 from getpass import getpass
@@ -145,9 +155,6 @@ environ["DATABASE_URL"] = f"postgresql://user:{password}@localhost/database"
 
 ## Using an existing `sqlalchemy.engine.Engine`
 
-```{versionadded} 0.5.1
-```
-
 Use an existing `Engine` by passing the variable name to `%sql`.
 
 ```{code-cell} ipython3
@@ -176,3 +183,14 @@ df.to_sql("numbers", engine)
 %%sql
 SELECT * FROM numbers
 ```
+## Conclusion
+
+This tutorial demonstrated how to leverage the power of JupySQL in Jupyter Notebooks for connecting to and interacting with databases. We covered key aspects such as:
+
+- Connection strings for different databases following SQLAlchemy URL standards.
+- Connecting to databases using the %sql magic command.
+- Securely connecting to databases by avoiding plain credentials and using methods like getpass and DATABASE_URL environment variable.
+- Using DSN connections for managing connection information in configuration files.
+- Utilizing existing sqlalchemy.engine.Engine instances for database connections.
+
+With these techniques, you can confidently manage connections to your databases while ensuring security and flexibility. JupySQL provides a convenient and powerful way to execute SQL queries and analyze data within Jupyter Notebooks.
diff --git a/doc/integrations/mariadb.ipynb b/doc/integrations/mariadb.ipynb
index 0d6d615..81e8e85 100644
--- a/doc/integrations/mariadb.ipynb
+++ b/doc/integrations/mariadb.ipynb
@@ -82,7 +82,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 56,
+   "execution_count": 2,
    "id": "f9c88366",
    "metadata": {
     "tags": []
@@ -92,7 +92,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "b6a4edfc17164baccd411d48e9068eb4ae053de4c16ee726e358fe4ef9897ced\n"
+      "c2a0a18f9c37285ffdb17b22d75a3a8ae789a93f58a59c9c1892a4f30f7bf9a2\n"
      ]
     }
    ],
@@ -116,7 +116,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 57,
+   "execution_count": 3,
    "id": "ec326f31-6cac-4f97-a5f6-5538e694082b",
    "metadata": {
     "tags": []
@@ -127,7 +127,7 @@
      "output_type": "stream",
      "text": [
       "CONTAINER ID   IMAGE            COMMAND                  CREATED        STATUS                  PORTS                    NAMES\n",
-      "b6a4edfc1716   mariadb:latest   \"docker-entrypoint.s…\"   1 second ago   Up Less than a second   0.0.0.0:3306->3306/tcp   mariadb\n"
+      "c2a0a18f9c37   mariadb:latest   \"docker-entrypoint.s…\"   1 second ago   Up Less than a second   0.0.0.0:3306->3306/tcp   mariadb\n"
      ]
     }
    ],
@@ -148,7 +148,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 58,
+   "execution_count": 4,
    "id": "82b7d34f-aa22-4625-b2ff-cebcc70747da",
    "metadata": {},
    "outputs": [
@@ -166,7 +166,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 59,
+   "execution_count": 5,
    "id": "16b1bfed",
    "metadata": {
     "tags": []
@@ -178,7 +178,7 @@
        "(1369769, 19)"
       ]
      },
-     "execution_count": 59,
+     "execution_count": 5,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -202,7 +202,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 60,
+   "execution_count": 6,
    "id": "a3402cdf",
    "metadata": {
     "tags": []
@@ -228,7 +228,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 61,
+   "execution_count": 7,
    "id": "3df653d7",
    "metadata": {
     "tags": []
@@ -238,9 +238,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "Note: you may need to restart the kernel to use updated packages.\n",
-      "The sql extension is already loaded. To reload it, use:\n",
-      "  %reload_ext sql\n"
+      "Note: you may need to restart the kernel to use updated packages.\n"
      ]
     }
    ],
@@ -262,7 +260,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 62,
+   "execution_count": 8,
    "id": "84902d46",
    "metadata": {
     "tags": []
@@ -296,7 +294,7 @@
        "[(1369769,)]"
       ]
      },
-     "execution_count": 62,
+     "execution_count": 8,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -316,7 +314,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 63,
+   "execution_count": 9,
    "id": "ff575b33-c27c-4c58-8f31-17b930454191",
    "metadata": {
     "tags": []
@@ -328,7 +326,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 64,
+   "execution_count": 10,
    "id": "58106d30-790d-4c8a-88da-86dd0b0c12bc",
    "metadata": {
     "tags": []
@@ -362,7 +360,7 @@
        "[(1297415,)]"
       ]
      },
-     "execution_count": 64,
+     "execution_count": 10,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -375,7 +373,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 65,
+   "execution_count": 11,
    "id": "b820944c-0016-484a-a23f-42f4290ccce8",
    "metadata": {
     "tags": []
@@ -387,7 +385,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 66,
+   "execution_count": 12,
    "id": "7fb73771-2251-4ed4-95ca-8f89ef0131b6",
    "metadata": {
     "tags": []
@@ -421,7 +419,7 @@
        "[(73849,)]"
       ]
      },
-     "execution_count": 66,
+     "execution_count": 12,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -444,7 +442,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 67,
+   "execution_count": 13,
    "id": "3ff7c2d9-20b3-4214-bbd0-8043dd78aa67",
    "metadata": {
     "tags": []
@@ -474,7 +472,7 @@
        "+------+"
       ]
      },
-     "execution_count": 67,
+     "execution_count": 13,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -483,6 +481,228 @@
     "%sqlcmd tables"
    ]
   },
+  {
+   "cell_type": "code",
+   "execution_count": 14,
+   "id": "547d41a8-2ea1-4152-a4da-653da9f4bcc9",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "    <thead>\n",
+       "        <tr>\n",
+       "            <th>name</th>\n",
+       "            <th>type</th>\n",
+       "            <th>default</th>\n",
+       "            <th>comment</th>\n",
+       "            <th>nullable</th>\n",
+       "            <th>autoincrement</th>\n",
+       "        </tr>\n",
+       "    </thead>\n",
+       "    <tbody>\n",
+       "        <tr>\n",
+       "            <td>index</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>VendorID</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tpep_pickup_datetime</td>\n",
+       "            <td>DATETIME</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tpep_dropoff_datetime</td>\n",
+       "            <td>DATETIME</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>passenger_count</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>trip_distance</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>RatecodeID</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>store_and_fwd_flag</td>\n",
+       "            <td>TEXT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>PULocationID</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>DOLocationID</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>payment_type</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>fare_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>extra</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>mta_tax</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tip_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tolls_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>improvement_surcharge</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>total_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>congestion_surcharge</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>airport_fee</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "    </tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "+-----------------------+----------+---------+---------+----------+---------------+\n",
+       "|          name         |   type   | default | comment | nullable | autoincrement |\n",
+       "+-----------------------+----------+---------+---------+----------+---------------+\n",
+       "|         index         |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|        VendorID       |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|  tpep_pickup_datetime | DATETIME |   None  |   None  |   True   |               |\n",
+       "| tpep_dropoff_datetime | DATETIME |   None  |   None  |   True   |               |\n",
+       "|    passenger_count    |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|     trip_distance     |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|       RatecodeID      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|   store_and_fwd_flag  |   TEXT   |   None  |   None  |   True   |               |\n",
+       "|      PULocationID     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|      DOLocationID     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|      payment_type     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|      fare_amount      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|         extra         |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|        mta_tax        |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|       tip_amount      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|      tolls_amount     |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "| improvement_surcharge |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|      total_amount     |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|  congestion_surcharge |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|      airport_fee      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "+-----------------------+----------+---------+---------+----------+---------------+"
+      ]
+     },
+     "execution_count": 14,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "%sqlcmd columns --table taxi"
+   ]
+  },
   {
    "cell_type": "markdown",
    "id": "cffcaf73-c2f3-4cc6-b777-7a2784c743e9",
@@ -495,7 +715,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 68,
+   "execution_count": 15,
    "id": "7ec71402",
    "metadata": {
     "tags": []
@@ -521,7 +741,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 69,
+   "execution_count": 16,
    "id": "e5195ed0-d354-4565-937e-fb6be55e4353",
    "metadata": {
     "tags": []
@@ -559,7 +779,7 @@
        "[(0.0, 2.5010889812889836, 18.92)]"
       ]
      },
-     "execution_count": 69,
+     "execution_count": 16,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -580,7 +800,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 70,
+   "execution_count": 17,
    "id": "636803f1-7c40-4695-b950-5604dad98c33",
    "metadata": {
     "tags": []
@@ -616,7 +836,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 71,
+   "execution_count": 18,
    "id": "3c7845eb-59f4-495f-a3a3-d9ff150e323e",
    "metadata": {
     "tags": []
@@ -628,7 +848,7 @@
        "<AxesSubplot: title={'center': \"'trip_distance' from 'many_passengers'\"}, xlabel='trip_distance', ylabel='Count'>"
       ]
      },
-     "execution_count": 71,
+     "execution_count": 18,
      "metadata": {},
      "output_type": "execute_result"
     },
@@ -659,7 +879,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 72,
+   "execution_count": 19,
    "id": "6d408cc0",
    "metadata": {
     "tags": []
@@ -669,8 +889,8 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "CONTAINER ID   IMAGE            COMMAND                  CREATED              STATUS              PORTS                    NAMES\n",
-      "b6a4edfc1716   mariadb:latest   \"docker-entrypoint.s…\"   About a minute ago   Up About a minute   0.0.0.0:3306->3306/tcp   mariadb\n"
+      "CONTAINER ID   IMAGE            COMMAND                  CREATED         STATUS         PORTS                    NAMES\n",
+      "c2a0a18f9c37   mariadb:latest   \"docker-entrypoint.s…\"   2 minutes ago   Up 2 minutes   0.0.0.0:3306->3306/tcp   mariadb\n"
      ]
     }
    ],
@@ -681,7 +901,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 73,
+   "execution_count": 20,
    "id": "42c37efd-1666-42dd-a38c-1944860b9c39",
    "metadata": {
     "tags": []
@@ -702,7 +922,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 74,
+   "execution_count": 21,
    "id": "6c9bce10",
    "metadata": {
     "tags": []
@@ -723,7 +943,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 75,
+   "execution_count": 22,
    "id": "17d42e97-9be7-43a8-916a-56dea1ca3dda",
    "metadata": {
     "tags": []
diff --git a/doc/integrations/mysql.ipynb b/doc/integrations/mysql.ipynb
index 61e7696..d3d61a7 100644
--- a/doc/integrations/mysql.ipynb
+++ b/doc/integrations/mysql.ipynb
@@ -69,7 +69,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 5,
+   "execution_count": 1,
    "id": "f9c88366",
    "metadata": {
     "tags": []
@@ -79,7 +79,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "f868e73bd96e73a4e4810c34469aa60b4be12811d8ed0c97071d137b3b3b22ce\n"
+      "b9f7f973698a0063198a7e6358445e942de4905d18b99145a7dfc8bb947bfa97\n"
      ]
     }
    ],
@@ -102,7 +102,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 6,
+   "execution_count": 2,
    "id": "ec326f31-6cac-4f97-a5f6-5538e694082b",
    "metadata": {
     "tags": []
@@ -112,9 +112,8 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS                  PORTS                               NAMES\n",
-      "f868e73bd96e   mysql      \"docker-entrypoint.s…\"   1 second ago     Up Less than a second   0.0.0.0:3306->3306/tcp, 33060/tcp   mysql\n",
-      "94fa1f440c4c   postgres   \"docker-entrypoint.s…\"   45 minutes ago   Up 45 minutes           0.0.0.0:5432->5432/tcp              postgres\n"
+      "CONTAINER ID   IMAGE     COMMAND                  CREATED        STATUS                  PORTS                               NAMES\n",
+      "b9f7f973698a   mysql     \"docker-entrypoint.s…\"   1 second ago   Up Less than a second   0.0.0.0:3306->3306/tcp, 33060/tcp   mysql\n"
      ]
     }
    ],
@@ -211,7 +210,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 8,
+   "execution_count": 3,
    "id": "16b1bfed",
    "metadata": {
     "tags": []
@@ -223,7 +222,7 @@
        "(1369769, 19)"
       ]
      },
-     "execution_count": 8,
+     "execution_count": 3,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -247,7 +246,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 10,
+   "execution_count": 4,
    "id": "a3402cdf",
    "metadata": {
     "tags": []
@@ -273,7 +272,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 11,
+   "execution_count": 5,
    "id": "3df653d7",
    "metadata": {
     "tags": []
@@ -305,7 +304,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 12,
+   "execution_count": 6,
    "id": "84902d46",
    "metadata": {
     "tags": []
@@ -339,7 +338,7 @@
        "[(1369769,)]"
       ]
      },
-     "execution_count": 12,
+     "execution_count": 6,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -359,7 +358,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 13,
+   "execution_count": 7,
    "id": "7ec71402",
    "metadata": {
     "tags": []
@@ -371,7 +370,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 14,
+   "execution_count": 8,
    "id": "78db29c3-0a15-4f66-a95e-01e3c7e22697",
    "metadata": {
     "tags": []
@@ -405,7 +404,7 @@
        "[(1297415,)]"
       ]
      },
-     "execution_count": 14,
+     "execution_count": 8,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -418,7 +417,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 15,
+   "execution_count": 9,
    "id": "8fd0e654-28d5-4bee-a3d3-7a59d513ef86",
    "metadata": {
     "tags": []
@@ -430,7 +429,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 16,
+   "execution_count": 10,
    "id": "ab4f4068-af8c-4f23-9cdf-3d0242c936f9",
    "metadata": {
     "tags": []
@@ -464,7 +463,7 @@
        "[(73849,)]"
       ]
      },
-     "execution_count": 16,
+     "execution_count": 10,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -485,7 +484,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 17,
+   "execution_count": 11,
    "id": "63511cdd-cb37-447c-a1e2-4272d12e341e",
    "metadata": {
     "tags": []
@@ -515,7 +514,7 @@
        "+------+"
       ]
      },
-     "execution_count": 17,
+     "execution_count": 11,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -524,6 +523,236 @@
     "%sqlcmd tables"
    ]
   },
+  {
+   "cell_type": "markdown",
+   "id": "12215e5a-cf5b-44a3-a1e0-b187065b9f04",
+   "metadata": {},
+   "source": [
+    "Listing columns in a table:"
+   ]
+  },
+  {
+   "cell_type": "code",
+   "execution_count": 12,
+   "id": "510c1670-2fef-4bdf-b29e-7cca68ea7c09",
+   "metadata": {
+    "tags": []
+   },
+   "outputs": [
+    {
+     "data": {
+      "text/html": [
+       "<table>\n",
+       "    <thead>\n",
+       "        <tr>\n",
+       "            <th>name</th>\n",
+       "            <th>type</th>\n",
+       "            <th>default</th>\n",
+       "            <th>comment</th>\n",
+       "            <th>nullable</th>\n",
+       "            <th>autoincrement</th>\n",
+       "        </tr>\n",
+       "    </thead>\n",
+       "    <tbody>\n",
+       "        <tr>\n",
+       "            <td>index</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>VendorID</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tpep_pickup_datetime</td>\n",
+       "            <td>DATETIME</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tpep_dropoff_datetime</td>\n",
+       "            <td>DATETIME</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>passenger_count</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>trip_distance</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>RatecodeID</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>store_and_fwd_flag</td>\n",
+       "            <td>TEXT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>PULocationID</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>DOLocationID</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>payment_type</td>\n",
+       "            <td>BIGINT</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td>False</td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>fare_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>extra</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>mta_tax</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tip_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>tolls_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>improvement_surcharge</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>total_amount</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>congestion_surcharge</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "        <tr>\n",
+       "            <td>airport_fee</td>\n",
+       "            <td>DOUBLE</td>\n",
+       "            <td>None</td>\n",
+       "            <td>None</td>\n",
+       "            <td>True</td>\n",
+       "            <td></td>\n",
+       "        </tr>\n",
+       "    </tbody>\n",
+       "</table>"
+      ],
+      "text/plain": [
+       "+-----------------------+----------+---------+---------+----------+---------------+\n",
+       "|          name         |   type   | default | comment | nullable | autoincrement |\n",
+       "+-----------------------+----------+---------+---------+----------+---------------+\n",
+       "|         index         |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|        VendorID       |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|  tpep_pickup_datetime | DATETIME |   None  |   None  |   True   |               |\n",
+       "| tpep_dropoff_datetime | DATETIME |   None  |   None  |   True   |               |\n",
+       "|    passenger_count    |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|     trip_distance     |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|       RatecodeID      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|   store_and_fwd_flag  |   TEXT   |   None  |   None  |   True   |               |\n",
+       "|      PULocationID     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|      DOLocationID     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|      payment_type     |  BIGINT  |   None  |   None  |   True   |     False     |\n",
+       "|      fare_amount      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|         extra         |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|        mta_tax        |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|       tip_amount      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|      tolls_amount     |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "| improvement_surcharge |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|      total_amount     |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|  congestion_surcharge |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "|      airport_fee      |  DOUBLE  |   None  |   None  |   True   |               |\n",
+       "+-----------------------+----------+---------+---------+----------+---------------+"
+      ]
+     },
+     "execution_count": 12,
+     "metadata": {},
+     "output_type": "execute_result"
+    }
+   ],
+   "source": [
+    "%sqlcmd columns --table taxi"
+   ]
+  },
   {
    "cell_type": "markdown",
    "id": "8b981aa2-e384-45f3-af24-c557e4ea0755",
@@ -536,7 +765,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 19,
+   "execution_count": 13,
    "id": "46038013-e467-4e12-afb1-4005b192bbd8",
    "metadata": {
     "tags": []
@@ -562,7 +791,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 20,
+   "execution_count": 14,
    "id": "8f95765a-8b71-42c7-97d4-fd4b91695c79",
    "metadata": {
     "tags": []
@@ -600,7 +829,7 @@
        "[(0.0, 2.5010889812889836, 18.92)]"
       ]
      },
-     "execution_count": 20,
+     "execution_count": 14,
      "metadata": {},
      "output_type": "execute_result"
     }
@@ -621,7 +850,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 21,
+   "execution_count": 15,
    "id": "5a38ac36-1eb0-4b16-96a1-98ca584fc6c7",
    "metadata": {
     "tags": []
@@ -657,7 +886,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 22,
+   "execution_count": 17,
    "id": "7237d664-1b80-4a35-b52c-a130229be306",
    "metadata": {
     "tags": []
@@ -666,16 +895,16 @@
     {
      "data": {
       "text/plain": [
-       "<Axes: title={'center': \"'trip_distance' from 'taxi'\"}, xlabel='trip_distance', ylabel='Count'>"
+       "<AxesSubplot: title={'center': \"'trip_distance' from 'many_passengers'\"}, xlabel='trip_distance', ylabel='Count'>"
       ]
      },
-     "execution_count": 22,
+     "execution_count": 17,
      "metadata": {},
      "output_type": "execute_result"
     },
     {
      "data": {
-      "image/png": "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aaJff/1VQ4cO1X//+9/yKhcotmt65uZyHnroIX377bdatGiR426Gnj17Ov7XumLFCjVs2FCff/65wsLCFBoaqqFDh+r33393ceVwlYtnGq7UggULnJY/+eQTSXIE7Mtp2rSp6tatq4ULF8oY42g/fPiwEhISSlRLQECAhgwZovvvv1/79u1znFrJv+354nHn/9L/623Rxhh9+OGHJdrvX8XExOjHH3/U2rVrL9mnT58+On78uHJzcxUZGVngdbX/I9K0aVPVq1dPn3zyidPP/MyZM1q8eLHjDqryVJJjJEnvv/9+odsZPny4UlJStGTJEn300Udavny53nrrratQMXBlrumZm6L8/PPPWrhwoX755RcFBQVJkp5++mmtWrVKc+fO1SuvvKIDBw7o8OHD+vTTTzV//nzl5uZq7Nixuueee4r8xxfW1apVKy1atEhxcXFq2LChvL291apVq1Jty8vLS9OmTdPp06d14403KiEhQS+99JJiYmJ06623Fmsbbm5u+uc//6mhQ4fqb3/7mx599FGdPHlSkyZNKtZpqfbt26tPnz5q3bq1atSooeTkZP373/92+gWdP75XX31VMTExcnd3V+vWrdW9e3d5eXnp/vvv17PPPqtz585p1qxZBU7JlMSYMWMUFxenO++8U+PHj9dNN92ks2fPasOGDerTp4+6dOmi++67TwsWLFCvXr00evRo3XTTTfL09NQvv/yidevW6c4779Tf/va3UtdwOW5ubnrttdf04IMPqk+fPho2bJiys7P1+uuv6+TJk5o6depV2/elhIeHS5I++OADVa9eXd7e3goLC1OzZs3UqFEjjR8/XsYY+fv7a8WKFYqPjy+wjdmzZ+s///mP5s6dq5YtW6ply5YaOXKknnvuOd1yyy2cjkfF4tLLmSsQSWbp0qWO5f/93/81koyPj4/Ty8PDw/Tv398YY8yjjz5qJJl9+/Y51ktKSjKSzA8//FDeQ0AFcOjQIRMdHW2qV69uJDnuRsq/I+rTTz8tsM6l7pby8fExO3fuNJ07dzZVqlQx/v7+5vHHHzenT58ucV2zZ882119/vfHy8jJNmjQxc+bMMYMHD77s3VLjx483kZGRpkaNGsZut5uGDRuasWPHmoyMDEef7OxsM3ToUFO7dm1js9mMJHPw4EFjjDErVqwwbdq0Md7e3qZevXrmmWeeMV9++WWB8RZ2N1L+z+HiGk+cOGFGjx5tGjRoYDw9PU2dOnVM7969nf7OnT9/3rzxxhuOfVerVs00a9bMDBs2zOzfv7/EP7+i7pZ6/fXXC11n2bJlpn379sbb29v4+PiYbt26mW+//dapT/6dRb/99luBcfv4+BSrjuKaPn26CQsLM+7u7kaSmTt3rjHGmL1795ru3bub6tWrmxo1aph7773XpKSkOH0Wdu7caapUqWIGDx7stM1z586ZiIgIExoaak6cOOE0JsCVbMb8Zd70Gmaz2bR06VLHd8bExcXpwQcf1J49e+Tu7u7Ut1q1agoMDNTEiRP1yiuvOD2Q7OzZs6patapWr17NXQQotSFDhuizzz7T6dOnXV0KAFQ6nJa6hLZt2yo3N1fp6enq2LFjoX1uueUWXbhwQT///LMaNWokSY7bW/96ASUAACg/13S4OX36tNNdAQcPHtSOHTvk7++vJk2a6MEHH9SgQYM0bdo0tW3bVhkZGVq7dq1atWqlXr166fbbb1e7du308MMPa/r06crLy9OIESPUvXt3NWnSxIUjw7UgLy+vwFcTXMzD45r+Kw7gGnVNn5Zav369unTpUqB98ODBmjdvns6fP6+XXnpJ8+fP19GjR1WzZk1FRUVp8uTJjosojx07pieffFKrV6+Wj4+PYmJiNG3atEr3rcGofIYMGaKPP/64yD7X8F9vANewazrcAJXZoUOHLvtAusjIyHKqBgAqDsINAACwFB7iBwAALOWau9owLy9Px44dU/Xq1Uv0KHwAAOA6xhidOnVKQUFBTl9KW5hrLtwcO3ZMwcHBri4DAACUwpEjRy77BbrXXLjJ/9K8I0eOyNfX18XVAACA4sjKylJwcHCxvvz2mgs3+aeifH19CTcAAFQyxbmkhAuKAQCApRBuAACApRBuAACApbg03GzcuFF9+/ZVUFCQbDabli1bVux1v/32W3l4eOiGG264avUBAIDKx6Xh5syZM2rTpo3efffdEq2XmZmpQYMGqVu3blepMgAAUFm59G6pmJgYxcTElHi9YcOG6YEHHpC7u3uJZnsAAID1VbprbubOnauff/5ZEydOLFb/7OxsZWVlOb0AAIB1Vapws3//fo0fP14LFiyQh0fxJp1iY2Pl5+fnePF0YgAArK3ShJvc3Fw98MADmjx5spo0aVLs9SZMmKDMzEzH68iRI1exSgAA4GqV5gnFp06d0tatW7V9+3aNHDlS0p9fgmmMkYeHh1avXq2uXbsWWM9ut8tut5d3uQAAwEUqTbjx9fXVrl27nNpmzpyptWvX6rPPPlNYWJiLKgMAABWJS8PN6dOn9dNPPzmWDx48qB07dsjf318NGjTQhAkTdPToUc2fP19ubm4KDw93Wr9OnTry9vYu0A4AAK5dLg03W7duVZcuXRzL48aNkyQNHjxY8+bNU2pqqlJSUlxVHgAAqIRsxhjj6iLKU1ZWlvz8/JSZmcm3ggMAUEmU5Pd3pblbCgAAoDgqzQXFlUXo+C9cXQIs4NDU3q4uAQAqLWZuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApRBuAACApbg03GzcuFF9+/ZVUFCQbDabli1bVmT/JUuWqHv37qpdu7Z8fX0VFRWlr776qnyKBQAAlYJLw82ZM2fUpk0bvfvuu8Xqv3HjRnXv3l0rV65UUlKSunTpor59+2r79u1XuVIAAFBZeLhy5zExMYqJiSl2/+nTpzstv/LKK/rvf/+rFStWqG3btmVcHQAAqIxcGm6uVF5enk6dOiV/f/9L9snOzlZ2drZjOSsrqzxKAwAALlKpLyieNm2azpw5o/79+1+yT2xsrPz8/Byv4ODgcqwQAACUt0obbhYuXKhJkyYpLi5OderUuWS/CRMmKDMz0/E6cuRIOVYJAADKW6U8LRUXF6dHHnlEn376qW6//fYi+9rtdtnt9nKqDAAAuFqlm7lZuHChhgwZok8++US9e/d2dTkAAKCCcenMzenTp/XTTz85lg8ePKgdO3bI399fDRo00IQJE3T06FHNnz9f0p/BZtCgQXr77bd18803Ky0tTZJUpUoV+fn5uWQMAACgYnHpzM3WrVvVtm1bx23c48aNU9u2bfXiiy9KklJTU5WSkuLo//777+vChQsaMWKE6tat63iNHj3aJfUDAICKx6UzN507d5Yx5pLvz5s3z2l5/fr1V7cgAABQ6VW6a24AAACKQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACW4tJws3HjRvXt21dBQUGy2WxatmzZZdfZsGGDIiIi5O3trYYNG+q99967+oUCAIBKw6Xh5syZM2rTpo3efffdYvU/ePCgevXqpY4dO2r79u16/vnnNWrUKC1evPgqVwoAACoLD1fuPCYmRjExMcXu/95776lBgwaaPn26JKl58+baunWr3njjDd19991XqUoAAFCZVKprbhITExUdHe3U1qNHD23dulXnz593UVUAAKAicenMTUmlpaUpICDAqS0gIEAXLlxQRkaG6tatW2Cd7OxsZWdnO5azsrKuep0AAMB1KtXMjSTZbDanZWNMoe35YmNj5efn53gFBwdf9RoBAIDrVKpwExgYqLS0NKe29PR0eXh4qGbNmoWuM2HCBGVmZjpeR44cKY9SAQCAi1Sq01JRUVFasWKFU9vq1asVGRkpT0/PQtex2+2y2+3lUR4AAKgAXDpzc/r0ae3YsUM7duyQ9Oet3jt27FBKSoqkP2ddBg0a5Og/fPhwHT58WOPGjVNycrLmzJmjjz76SE8//bQrygcAABWQS2dutm7dqi5dujiWx40bJ0kaPHiw5s2bp9TUVEfQkaSwsDCtXLlSY8eO1YwZMxQUFKR33nmH28ABAICDzeRfkXuNyMrKkp+fnzIzM+Xr61vm2w8d/0WZbxPXnkNTe7u6BACoUEry+7tSXVAMAABwOYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKYQbAABgKS4PNzNnzlRYWJi8vb0VERGhTZs2Fdl/wYIFatOmjapWraq6devqoYce0vHjx8upWgAAUNG5NNzExcVpzJgxeuGFF7R9+3Z17NhRMTExSklJKbT/N998o0GDBumRRx7Rnj179Omnn2rLli0aOnRoOVcOAAAqKpeGmzfffFOPPPKIhg4dqubNm2v69OkKDg7WrFmzCu2/efNmhYaGatSoUQoLC9Ott96qYcOGaevWreVcOQAAqKhcFm5ycnKUlJSk6Ohop/bo6GglJCQUuk6HDh30yy+/aOXKlTLG6Ndff9Vnn32m3r17X3I/2dnZysrKcnoBAADrclm4ycjIUG5urgICApzaAwIClJaWVug6HTp00IIFCzRgwAB5eXkpMDBQ1113nf71r39dcj+xsbHy8/NzvIKDg8t0HAAAoGJx+QXFNpvNadkYU6At3969ezVq1Ci9+OKLSkpK0qpVq3Tw4EENHz78ktufMGGCMjMzHa8jR46Uaf0AAKBi8XDVjmvVqiV3d/cCszTp6ekFZnPyxcbG6pZbbtEzzzwjSWrdurV8fHzUsWNHvfTSS6pbt26Bdex2u+x2e9kPAAAAVEilmrlp2LBhobdfnzx5Ug0bNizWNry8vBQREaH4+Hin9vj4eHXo0KHQdf744w+5uTmX7O7uLunPGR8AAIBShZtDhw4pNze3QHt2draOHj1a7O2MGzdOs2fP1pw5c5ScnKyxY8cqJSXFcZppwoQJGjRokKN/3759tWTJEs2aNUsHDhzQt99+q1GjRummm25SUFBQaYYCAAAspkSnpZYvX+7481dffSU/Pz/Hcm5urtasWaPQ0NBib2/AgAE6fvy4pkyZotTUVIWHh2vlypUKCQmRJKWmpjo982bIkCE6deqU3n33XT311FO67rrr1LVrV7366qslGQYAALAwmynB+Zz8U0I2m63AaSBPT0+FhoZq2rRp6tOnT9lWWYaysrLk5+enzMxM+fr6lvn2Q8d/UebbxLXn0NRLP94AAK5FJfn9XaKZm7y8PElSWFiYtmzZolq1apW+SgAAgKugVHdLHTx4sKzrAAAAKBOlvhV8zZo1WrNmjdLT0x0zOvnmzJlzxYUBAACURqnCzeTJkzVlyhRFRkaqbt26l3zoHgAAQHkrVbh57733NG/ePA0cOLCs6wEAALgipXrOTU5OziUftAcAAOBKpQo3Q4cO1SeffFLWtQAAAFyxUp2WOnfunD744AN9/fXXat26tTw9PZ3ef/PNN8ukOAAAgJIqVbjZuXOnbrjhBknS7t27nd7j4mIAAOBKpQo369atK+s6AAAAykSprrkBAACoqEo1c9OlS5ciTz+tXbu21AUBAABciVKFm/zrbfKdP39eO3bs0O7duzV48OCyqAsAAKBUShVu3nrrrULbJ02apNOnT19RQQAAAFeiTK+5+fvf/873SgEAAJcq03CTmJgob2/vstwkAABAiZTqtNRdd93ltGyMUWpqqrZu3ap//OMfZVIYAABAaZQq3Pj5+Tktu7m5qWnTppoyZYqio6PLpDAAAIDSKFW4mTt3blnXAQAAUCZKFW7yJSUlKTk5WTabTS1atFDbtm3Lqi4AAIBSKVW4SU9P13333af169fruuuukzFGmZmZ6tKlixYtWqTatWuXdZ0AAADFUqq7pZ588kllZWVpz549+v3333XixAnt3r1bWVlZGjVqVFnXCAAAUGylmrlZtWqVvv76azVv3tzR1qJFC82YMYMLigEAgEuVauYmLy9Pnp6eBdo9PT2Vl5d3xUUBAACUVqnCTdeuXTV69GgdO3bM0Xb06FGNHTtW3bp1K7PiAAAASqpU4ebdd9/VqVOnFBoaqkaNGqlx48YKCwvTqVOn9K9//ausawQAACi2Ul1zExwcrG3btik+Pl4//PCDjDFq0aKFbr/99rKuDwAAoERKNHOzdu1atWjRQllZWZKk7t2768knn9SoUaN04403qmXLltq0adNVKRQAAKA4ShRupk+frkcffVS+vr4F3vPz89OwYcP05ptvlllxAAAAJVWicPP999+rZ8+el3w/OjpaSUlJV1wUAABAaZUo3Pz666+F3gKez8PDQ7/99tsVFwUAAFBaJQo39erV065duy75/s6dO1W3bt0rLgoAAKC0ShRuevXqpRdffFHnzp0r8N7Zs2c1ceJE9enTp8yKAwAAKKkS3Qr+P//zP1qyZImaNGmikSNHqmnTprLZbEpOTtaMGTOUm5urF1544WrVCgAAcFklCjcBAQFKSEjQ448/rgkTJsgYI0my2Wzq0aOHZs6cqYCAgKtSKAAAQHGU+CF+ISEhWrlypU6cOKGffvpJxhhdf/31qlGjxtWoDwAAoERK9YRiSapRo4ZuvPHGsqwFAADgipXqu6UAAAAqKsINAACwFMINAACwFJeHm5kzZyosLEze3t6KiIi47BdvZmdn64UXXlBISIjsdrsaNWqkOXPmlFO1AACgoiv1BcVlIS4uTmPGjNHMmTN1yy236P3331dMTIz27t2rBg0aFLpO//799euvv+qjjz5S48aNlZ6ergsXLpRz5QAAoKKymfyH1bhA+/bt1a5dO82aNcvR1rx5c/Xr10+xsbEF+q9atUr33XefDhw4IH9//1LtMysrS35+fsrMzCz0282vVOj4L8p8m7j2HJra29UlAECFUpLf3y47LZWTk6OkpCRFR0c7tUdHRyshIaHQdZYvX67IyEi99tprqlevnpo0aaKnn35aZ8+eveR+srOzlZWV5fQCAADW5bLTUhkZGcrNzS3wROOAgAClpaUVus6BAwf0zTffyNvbW0uXLlVGRoaeeOIJ/f7775e87iY2NlaTJ08u8/oBAEDF5PILim02m9OyMaZAW768vDzZbDYtWLBAN910k3r16qU333xT8+bNu+TszYQJE5SZmel4HTlypMzHAAAAKg6XzdzUqlVL7u7uBWZp0tPTL/n9VHXr1lW9evXk5+fnaGvevLmMMfrll190/fXXF1jHbrfLbreXbfEAAKDCctnMjZeXlyIiIhQfH+/UHh8frw4dOhS6zi233KJjx47p9OnTjrYff/xRbm5uql+//lWtFwAAVA4uPS01btw4zZ49W3PmzFFycrLGjh2rlJQUDR8+XNKfp5QGDRrk6P/AAw+oZs2aeuihh7R3715t3LhRzzzzjB5++GFVqVLFVcMAAAAViEufczNgwAAdP35cU6ZMUWpqqsLDw7Vy5UqFhIRIklJTU5WSkuLoX61aNcXHx+vJJ59UZGSkatasqf79++ull15y1RAAAEAF49Ln3LgCz7lBZcBzbgDAWaV4zg0AAMDVQLgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACWQrgBAACW4vJwM3PmTIWFhcnb21sRERHatGlTsdb79ttv5eHhoRtuuOHqFggAACoVl4abuLg4jRkzRi+88IK2b9+ujh07KiYmRikpKUWul5mZqUGDBqlbt27lVCkAAKgsXBpu3nzzTT3yyCMaOnSomjdvrunTpys4OFizZs0qcr1hw4bpgQceUFRUVDlVCgAAKguXhZucnBwlJSUpOjraqT06OloJCQmXXG/u3Ln6+eefNXHixGLtJzs7W1lZWU4vAABgXS4LNxkZGcrNzVVAQIBTe0BAgNLS0gpdZ//+/Ro/frwWLFggDw+PYu0nNjZWfn5+jldwcPAV1w4AACoul19QbLPZnJaNMQXaJCk3N1cPPPCAJk+erCZNmhR7+xMmTFBmZqbjdeTIkSuuGQAAVFzFm/64CmrVqiV3d/cCszTp6ekFZnMk6dSpU9q6dau2b9+ukSNHSpLy8vJkjJGHh4dWr16trl27FljPbrfLbrdfnUEAAIAKx2UzN15eXoqIiFB8fLxTe3x8vDp06FCgv6+vr3bt2qUdO3Y4XsOHD1fTpk21Y8cOtW/fvrxKBwAAFZjLZm4kady4cRo4cKAiIyMVFRWlDz74QCkpKRo+fLikP08pHT16VPPnz5ebm5vCw8Od1q9Tp468vb0LtAMAgGuXS8PNgAEDdPz4cU2ZMkWpqakKDw/XypUrFRISIklKTU297DNvAAAA/spmjDGuLqI8ZWVlyc/PT5mZmfL19S3z7YeO/6LMt4lrz6GpvV1dAgBUKCX5/e3yu6UAAADKEuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYCuEGAABYisvDzcyZMxUWFiZvb29FRERo06ZNl+y7ZMkSde/eXbVr15avr6+ioqL01VdflWO1AACgonNpuImLi9OYMWP0wgsvaPv27erYsaNiYmKUkpJSaP+NGzeqe/fuWrlypZKSktSlSxf17dtX27dvL+fKAQBARWUzxhhX7bx9+/Zq166dZs2a5Whr3ry5+vXrp9jY2GJto2XLlhowYIBefPHFYvXPysqSn5+fMjMz5evrW6q6ixI6/osy3yauPYem9nZ1CQBQoZTk97fLZm5ycnKUlJSk6Ohop/bo6GglJCQUaxt5eXk6deqU/P39L9knOztbWVlZTi8AAGBdLgs3GRkZys3NVUBAgFN7QECA0tLSirWNadOm6cyZM+rfv/8l+8TGxsrPz8/xCg4OvqK6AQBAxebyC4ptNpvTsjGmQFthFi5cqEmTJikuLk516tS5ZL8JEyYoMzPT8Tpy5MgV1wwAACouD1ftuFatWnJ3dy8wS5Oenl5gNudicXFxeuSRR/Tpp5/q9ttvL7Kv3W6X3W6/4noBAEDl4LKZGy8vL0VERCg+Pt6pPT4+Xh06dLjkegsXLtSQIUP0ySefqHdvLroEAADOXDZzI0njxo3TwIEDFRkZqaioKH3wwQdKSUnR8OHDJf15Suno0aOaP3++pD+DzaBBg/T222/r5ptvdsz6VKlSRX5+fi4bBwAAqDhcGm4GDBig48ePa8qUKUpNTVV4eLhWrlypkJAQSVJqaqrTM2/ef/99XbhwQSNGjNCIESMc7YMHD9a8efPKu3wAAFABufQ5N67Ac25QGfCcGwBwVimecwMAAHA1EG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAIClEG4AAICluDzczJw5U2FhYfL29lZERIQ2bdpUZP8NGzYoIiJC3t7eatiwod57771yqhQAAFQGLg03cXFxGjNmjF544QVt375dHTt2VExMjFJSUgrtf/DgQfXq1UsdO3bU9u3b9fzzz2vUqFFavHhxOVcOAAAqKpsxxrhq5+3bt1e7du00a9YsR1vz5s3Vr18/xcbGFuj/3HPPafny5UpOTna0DR8+XN9//70SExOLtc+srCz5+fkpMzNTvr6+Vz6Ii4SO/6LMt4lrz6GpvV1dAgBUKCX5/e2ymZucnBwlJSUpOjraqT06OloJCQmFrpOYmFigf48ePbR161adP3/+qtUKAAAqDw9X7TgjI0O5ubkKCAhwag8ICFBaWlqh66SlpRXa/8KFC8rIyFDdunULrJOdna3s7GzHcmZmpqQ/E+DVkJf9x1XZLq4tV+vzCQCVVf6/i8U54eSycJPPZrM5LRtjCrRdrn9h7fliY2M1efLkAu3BwcElLRUoN37TXV0BAFRMp06dkp+fX5F9XBZuatWqJXd39wKzNOnp6QVmZ/IFBgYW2t/Dw0M1a9YsdJ0JEyZo3LhxjuW8vDz9/vvvqlmzZpEhqrxlZWUpODhYR44cuSrXAlUUjNNaGKe1XAvjvBbGKFlznMYYnTp1SkFBQZft67Jw4+XlpYiICMXHx+tvf/uboz0+Pl533nlnoetERUVpxYoVTm2rV69WZGSkPD09C13HbrfLbrc7tV133XVXVvxV5Ovra5kPYlEYp7UwTmu5FsZ5LYxRst44Lzdjk8+lt4KPGzdOs2fP1pw5c5ScnKyxY8cqJSVFw4cPl/TnrMugQYMc/YcPH67Dhw9r3LhxSk5O1pw5c/TRRx/p6aefdtUQAABABePSa24GDBig48ePa8qUKUpNTVV4eLhWrlypkJAQSVJqaqrTM2/CwsK0cuVKjR07VjNmzFBQUJDeeecd3X333a4aAgAAqGBcfkHxE088oSeeeKLQ9+bNm1egrVOnTtq2bdtVrqr82e12TZw4scApNKthnNbCOK3lWhjntTBG6doZ56W49CF+AAAAZc3l3y0FAABQlgg3AADAUgg3AADAUgg3AADAUgg3ZSw0NFQ2m83pNX78eKc+KSkp6tu3r3x8fFSrVi2NGjVKOTk5Tn127dqlTp06qUqVKqpXr56mTJlS4Ps0NmzYoIiICHl7e6thw4Z67733CtSzePFitWjRQna7XS1atNDSpUvLftAlMHPmTIWFhcnb21sRERHatGmTS+vJN2nSpALHLTAw0PG+MUaTJk1SUFCQqlSpos6dO2vPnj1O28jOztaTTz6pWrVqycfHR3fccYd++eUXpz4nTpzQwIED5efnJz8/Pw0cOFAnT5506lOcz0dxbdy4UX379lVQUJBsNpuWLVvm9H5FG1dxPvelGeeQIUMKHN+bb765Uo0zNjZWN954o6pXr646deqoX79+2rdvn1MfKxzP4ozTCsdz1qxZat26teMhe1FRUfryyy8d71vhWLqUQZkKCQkxU6ZMMampqY7XqVOnHO9fuHDBhIeHmy5dupht27aZ+Ph4ExQUZEaOHOnok5mZaQICAsx9991ndu3aZRYvXmyqV69u3njjDUefAwcOmKpVq5rRo0ebvXv3mg8//NB4enqazz77zNEnISHBuLu7m1deecUkJyebV155xXh4eJjNmzeXzw/jIosWLTKenp7mww8/NHv37jWjR482Pj4+5vDhwy6p568mTpxoWrZs6XTc0tPTHe9PnTrVVK9e3SxevNjs2rXLDBgwwNStW9dkZWU5+gwfPtzUq1fPxMfHm23btpkuXbqYNm3amAsXLjj69OzZ04SHh5uEhASTkJBgwsPDTZ8+fRzvF+fzURIrV640L7zwglm8eLGRZJYuXer0fkUaV3E+96Ud5+DBg03Pnj2dju/x48ed+lT0cfbo0cPMnTvX7N692+zYscP07t3bNGjQwJw+fdrRxwrHszjjtMLxXL58ufniiy/Mvn37zL59+8zzzz9vPD09ze7duy1zLF2JcFPGQkJCzFtvvXXJ91euXGnc3NzM0aNHHW0LFy40drvdZGZmGmOMmTlzpvHz8zPnzp1z9ImNjTVBQUEmLy/PGGPMs88+a5o1a+a07WHDhpmbb77Zsdy/f3/Ts2dPpz49evQw9913X6nHdyVuuukmM3z4cKe2Zs2amfHjx7uknr+aOHGiadOmTaHv5eXlmcDAQDN16lRH27lz54yfn5957733jDHGnDx50nh6eppFixY5+hw9etS4ubmZVatWGWOM2bt3r5HkFC4TExONJPPDDz8YY4r3+Siti3/pV7RxFedzX5pxGvPnL8M777zzkutUxnGmp6cbSWbDhg3GGOsez4vHaYw1j6cxxtSoUcPMnj3bsseyPHFa6ip49dVXVbNmTd1www16+eWXnab3EhMTFR4e7vTFXz169FB2draSkpIcfTp16uT08KUePXro2LFjOnTokKNPdHS003579OihrVu36vz580X2SUhIKNPxFkdOTo6SkpIK1BMdHe2Segqzf/9+BQUFKSwsTPfdd58OHDggSTp48KDS0tKcarfb7erUqZOj9qSkJJ0/f96pT1BQkMLDwx19EhMT5efnp/bt2zv63HzzzfLz83Pqc7nPR1mpaOMqzuf+Sqxfv1516tRRkyZN9Oijjyo9Pd3xXmUcZ2ZmpiTJ399fknWP58XjzGel45mbm6tFixbpzJkzioqKsuyxLE+EmzI2evRoLVq0SOvWrdPIkSM1ffp0pycwp6WlFfjW8xo1asjLy8vxjeeF9clfvlyfCxcuKCMjo8g+F3+zennIyMhQbm5uhannYu3bt9f8+fP11Vdf6cMPP1RaWpo6dOig48ePO+orqva0tDR5eXmpRo0aRfapU6dOgX3XqVOnyON68eejrFS0cRXnc19aMTExWrBggdauXatp06Zpy5Yt6tq1q7KzsyvlOI0xGjdunG699VaFh4c7rWul41nYOCXrHM9du3apWrVqstvtGj58uJYuXaoWLVpY8liWN5d//UJlMGnSJE2ePLnIPlu2bFFkZKTGjh3raGvdurVq1Kihe+65xzGbI0k2m63A+sYYp/aL+5j/78KtsuhT2P7LS0WrJ19MTIzjz61atVJUVJQaNWqkjz/+2HGhYmlqv9xxLW2fslSRxlWcz3RpDBgwwPHn8PBwRUZGKiQkRF988YXuuuuuS65XUcc5cuRI7dy5U998802B96x0PC81Tqscz6ZNm2rHjh06efKkFi9erMGDB2vDhg1FbreyHsvyxsxNMYwcOVLJyclFvv76v4q/yv/F+NNPP0mSAgMDCyTdEydO6Pz5844kXFif/CnXy/Xx8PBwhKhL9bk4gZeHWrVqyd3dvcLUczk+Pj5q1aqV9u/f77hrqqjaAwMDlZOToxMnThTZ59dffy2wr99++63I43rx56OsVLRxFedzX1bq1q2rkJAQ7d+/37HvyjLOJ598UsuXL9e6detUv359R7vVjuelxlmYyno8vby81Lhx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",
+      "image/png": "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fPiwbDabRo4cqZdffllff/21du3apYEDByogIMD8ZuKtt96qbt26aciQIdq8ebPWr1+v2NhY9e3bVwEBAZKkhx56SC4uLho8eLCSkpI0f/58vfnmmxo1apTZx1NPPaWlS5dq6tSp2rdvn+Li4rR161bFxsZe7x8JAACoQCqX5sa3bt2qO++803yeG36io6MVHx+v559/XmfPntXQoUOVlpam9u3ba+nSpXJzczOXmTdvnmJjY9WlSxc5OTmpd+/eeuutt8z5drtdy5cvV0xMjFq2bKmaNWtq3LhxDvfaateunT7++GP985//1P/7f/9P9evX16JFi9SoUaPr8FMAAAAVVZm5j1Z5x320AAAof27Y+2gBAACUdwQtAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAiBC0AAACLELQAAAAsQtACAACwCEELAADAIgQtAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAiBC0AAACLELQAAAAsQtACAACwCEELAADAIgQtAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAiBC0AAACLELQAAAAsQtACAACwCEELAADAIgQtAAAAixC0AAAALELQAgAAsEjl0m4AJSd4zJIys52Dr0Zeh04AACjbOKIFAABgEYIWAACARQhaAAAAFiFoAQAAWISgBQAAYJEyHbSys7P14osvKiQkRO7u7qpbt65eeuklGYZh1hiGoXHjxqlWrVpyd3dXeHi4Dhw44LCekydPqn///vLy8pK3t7cGDx6sM2fOONTs3LlTHTp0kJubmwIDAzV58uTrMkYAAFBxlemg9dprr2nmzJl6++23tXfvXr322muaPHmypk+fbtZMnjxZb731lmbNmqVNmzbJw8NDERERunDhglnTv39/JSUlKSEhQYsXL9a6des0dOhQc35GRoa6du2qoKAgbdu2TVOmTFFcXJzee++96zpeAABQsdiMyw8PlTF33323/Pz89OGHH5rTevfuLXd3d82dO1eGYSggIEDPPPOMnn32WUlSenq6/Pz8FB8fr759+2rv3r0KDQ3Vli1b1KpVK0nS0qVL1aNHDx09elQBAQGaOXOmXnjhBaWkpMjFxUWS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AFiEoAUAAGARghYAAIBFCFoAyry4uDg1a9bM0m107txZI0eONJ8HBwdr2rRplm4TQMVH0AJQaq4MNwV59tln8/z9R6tt2bJFQ4cOLVQtoQxAQSqXdgMAUBDDMJSdnS1PT095enpe1237+Phc1+0BqJg4ogWgVAwaNEhr167Vm2++KZvNJpvNpvj4eNlsNn333Xdq2bKlXF1d9f333+c5dTho0CBFRUVpwoQJ8vHxkZeXl5544gllZmYWattnz57VwIED5enpqVq1amnq1Kl5ai4/SmUYhuLi4lSnTh25uroqICBAI0aMkPTXUblDhw7p6aefNschSSdOnFC/fv100003qUqVKmrcuLE++eQTh2107txZI0aM0PPPP6/q1avL399fcXFxDjVpaWl6/PHH5efnJzc3NzVq1EiLFy8253///ffq0KGD3N3dFRgYqBEjRujs2bOF+jkAsB5BC0CpePPNNxUWFqYhQ4bo999/1++//67AwEBJ0pgxY/Tqq69q7969atKkSb7Lr1y5Unv37tWaNWv0ySefaMGCBZowYUKhtv3cc89p7dq1+uqrr7R8+XKtWbNG27dvL7D+yy+/1BtvvKF3331XBw4c0KJFi9S4cWNJ0oIFC1S7dm1NnDjRHIckXbhwQS1bttSSJUu0e/duDR06VAMGDNDmzZsd1j1nzhx5eHho06ZNmjx5siZOnKiEhARJUk5Ojrp3767169dr7ty52rNnj1599VVVqlRJkvTLL7+oW7du6t27t3bu3Kn58+fr+++/V2xsbKF+DgCug+L+pWwA+Ls6depkPPXUU+bz1atXG5KMRYsWOdSNHz/eaNq0qfk8OjraqF69unH27Flz2syZMw1PT08jOzv7qts8ffq04eLiYnz22WfmtBMnThju7u4OvQQFBRlvvPGGYRiGMXXqVOOWW24xMjMz813n5bVXExkZaTzzzDPm806dOhnt27d3qLn99tuN0aNHG4ZhGMuWLTOcnJyM/fv357u+wYMHG0OHDnWY9r///c9wcnIyzp8/f81+AFiPI1oAypxWrVpds6Zp06aqUqWK+TwsLExnzpzRkSNHrrrcL7/8oszMTLVp08acVr16dTVo0KDAZR544AGdP39eN998s4YMGaKFCxfq0qVLV91Odna2XnrpJTVu3FjVq1eXp6enli1bpsOHDzvUXXnErlatWjp+/LgkaceOHapdu7ZuueWWfLfx448/Kj4+3ryGzdPTUxEREcrJyVFycvJV+wNwfXAxPIAyx8PDo7RbcBAYGKj9+/drxYoVSkhI0JNPPqkpU6Zo7dq1cnZ2zneZKVOm6M0339S0adPUuHFjeXh4aOTIkXmuI7tyeZvNppycHEmSu7v7Vfs6c+aMHn/8cfN6scvVqVOnKEMEYBGCFoBS4+Liouzs7GIt++OPP+r8+fNmGNm4caM8PT3N67wKUrduXTk7O2vTpk1mGDl16pR++uknderUqcDl3N3d1bNnT/Xs2VMxMTFq2LChdu3apRYtWuQ7jvXr1+vee+/Vww8/LOmv661++uknhYaGFnqMTZo00dGjR/XTTz/le1SrRYsW2rNnj+rVq1fodQK4vjh1CKDUBAcHa9OmTTp48KD+/PNP80hOYWRmZmrw4MHas2ePvv32W40fP16xsbFycrr6f2uenp4aPHiwnnvuOa1atUq7d+/WoEGDrrpcfHy8PvzwQ+3evVu//vqr5s6dK3d3dwUFBZnjWLdunX777Tf9+eefkqT69esrISFBGzZs0N69e/X4448rNTW10OOTpE6dOqljx47q3bu3EhISlJycrO+++05Lly6VJI0ePVobNmxQbGysduzYoQMHDuirr77iYnigDCFoASg1zz77rCpVqqTQ0FD5+PjkuX7parp06aL69eurY8eOevDBB3XPPffkuTVCQaZMmaIOHTqoZ8+eCg8PV/v27dWyZcsC6729vfX+++/rjjvuUJMmTbRixQp98803qlGjhiRp4sSJOnjwoOrWrWvef+uf//ynWrRooYiICHXu3Fn+/v6Kiooq9Phyffnll7r99tvVr18/hYaG6vnnnzePnjVp0kRr167VTz/9pA4dOqh58+YaN26cAgICirwdANawGYZhlHYTAFAUgwYNUlpamhYtWlTarQDAVXFECwAAwCIELQAVyuHDhx1ud3DloyinJwHg7+LUIYAK5dKlSzp48GCB84ODg1W5Ml+4BnB9ELQAAAAswqlDAAAAixC0AAAALELQAgAAsAhBCwAAwCIELQAAAIsQtAAAACxC0AIAALAIQQsAAMAi/x/xuOIVWacZFAAAAABJRU5ErkJggg==",
       "text/plain": [
        "<Figure size 640x480 with 1 Axes>"
       ]
@@ -685,7 +914,7 @@
     }
    ],
    "source": [
-    "%sqlplot histogram --table taxi --column trip_distance"
+    "%sqlplot histogram --table many_passengers --column trip_distance --with many_passengers"
    ]
   },
   {
@@ -700,7 +929,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 24,
+   "execution_count": 18,
    "id": "6d408cc0",
    "metadata": {
     "tags": []
@@ -710,9 +939,8 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                               NAMES\n",
-      "f868e73bd96e   mysql      \"docker-entrypoint.s…\"   4 minutes ago    Up 4 minutes    0.0.0.0:3306->3306/tcp, 33060/tcp   mysql\n",
-      "94fa1f440c4c   postgres   \"docker-entrypoint.s…\"   49 minutes ago   Up 49 minutes   0.0.0.0:5432->5432/tcp              postgres\n"
+      "CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                               NAMES\n",
+      "b9f7f973698a   mysql     \"docker-entrypoint.s…\"   2 minutes ago   Up 2 minutes   0.0.0.0:3306->3306/tcp, 33060/tcp   mysql\n"
      ]
     }
    ],
@@ -723,7 +951,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 25,
+   "execution_count": 19,
    "id": "42c37efd-1666-42dd-a38c-1944860b9c39",
    "metadata": {
     "tags": []
@@ -744,7 +972,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 26,
+   "execution_count": 20,
    "id": "6c9bce10",
    "metadata": {
     "tags": []
@@ -765,7 +993,7 @@
   },
   {
    "cell_type": "code",
-   "execution_count": 27,
+   "execution_count": 21,
    "id": "17d42e97-9be7-43a8-916a-56dea1ca3dda",
    "metadata": {
     "tags": []
@@ -775,8 +1003,7 @@
      "name": "stdout",
      "output_type": "stream",
      "text": [
-      "CONTAINER ID   IMAGE      COMMAND                  CREATED          STATUS          PORTS                    NAMES\n",
-      "94fa1f440c4c   postgres   \"docker-entrypoint.s…\"   49 minutes ago   Up 49 minutes   0.0.0.0:5432->5432/tcp   postgres\n"
+      "CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES\n"
      ]
     }
    ],
diff --git a/examples/plot_boxplot.py b/examples/plot_boxplot.py
index c002786..018e2a4 100644
--- a/examples/plot_boxplot.py
+++ b/examples/plot_boxplot.py
@@ -11,6 +11,6 @@ if not Path("iris.csv").is_file():
         "iris.csv",
     )
 
-conn = Connection.from_connect_str("duckdb://").session
+conn = Connection.from_connect_str("duckdb://")
 
 plot.boxplot("iris.csv", "petal width", conn=conn)
diff --git a/examples/plot_boxplot_custom.py b/examples/plot_boxplot_custom.py
index fb1cf88..b578b9b 100644
--- a/examples/plot_boxplot_custom.py
+++ b/examples/plot_boxplot_custom.py
@@ -12,7 +12,7 @@ if not Path("iris.csv").is_file():
         "iris.csv",
     )
 
-conn = Connection.from_connect_str("duckdb://").session
+conn = Connection.from_connect_str("duckdb://")
 
 # returns matplotlib.Axes object
 ax = plot.boxplot("iris.csv", "petal width", conn=conn)
diff --git a/examples/plot_boxplot_horizontal.py b/examples/plot_boxplot_horizontal.py
index 3bc760a..81b4b81 100644
--- a/examples/plot_boxplot_horizontal.py
+++ b/examples/plot_boxplot_horizontal.py
@@ -12,6 +12,6 @@ if not Path("iris.csv").is_file():
         "iris.csv",
     )
 
-conn = Connection.from_connect_str("duckdb://").session
+conn = Connection.from_connect_str("duckdb://")
 
 plot.boxplot("iris.csv", "petal width", conn=conn, orient="h")
diff --git a/examples/plot_boxplot_many.py b/examples/plot_boxplot_many.py
index 8b1f7c5..05baca3 100644
--- a/examples/plot_boxplot_many.py
+++ b/examples/plot_boxplot_many.py
@@ -12,6 +12,6 @@ if not Path("iris.csv").is_file():
         "iris.csv",
     )
 
-conn = Connection.from_connect_str("duckdb://").session
+conn = Connection.from_connect_str("duckdb://")
 
 plot.boxplot("iris.csv", ["petal width", "sepal width"], conn=conn)
diff --git a/examples/plot_histogram.py b/examples/plot_histogram.py
index e253520..7ebcc30 100644
--- a/examples/plot_histogram.py
+++ b/examples/plot_histogram.py
@@ -10,6 +10,6 @@ urllib.request.urlretrieve(
     "iris.csv",
 )
 
-conn = Connection.from_connect_str("duckdb://").session
+conn = Connection.from_connect_str("duckdb://")
 
 plot.histogram("iris.csv", "petal width", bins=50, conn=conn)
diff --git a/examples/plot_histogram_many.py b/examples/plot_histogram_many.py
index 1702383..5631557 100644
--- a/examples/plot_histogram_many.py
+++ b/examples/plot_histogram_many.py
@@ -10,6 +10,6 @@ urllib.request.urlretrieve(
     "iris.csv",
 )
 
-conn = Connection.from_connect_str("duckdb://").session
+conn = Connection.from_connect_str("duckdb://")
 
 plot.histogram("iris.csv", ["petal width", "sepal width"], bins=50, conn=conn)
diff --git a/src/sql/connection.py b/src/sql/connection.py
index 7faf8eb..f30dc4c 100644
--- a/src/sql/connection.py
+++ b/src/sql/connection.py
@@ -349,8 +349,7 @@ class Connection:
             )
             conn.session.close()
 
-    @classmethod
-    def _get_curr_sqlalchemy_connection_info(cls):
+    def _get_curr_sqlalchemy_connection_info(self):
         """Get the dialect, driver, and database server version info of current
         connected dialect
 
@@ -360,18 +359,18 @@ class Connection:
             The dictionary which contains the SQLAlchemy-based dialect
             information, or None if there is no current connection.
         """
-        if not cls.current:
+
+        if not self.session:
             return None
+        engine = self.metadata.bind if IS_SQLALCHEMY_ONE else self.session
 
-        engine = cls.current.metadata.bind if IS_SQLALCHEMY_ONE else cls.current
         return {
             "dialect": getattr(engine.dialect, "name", None),
             "driver": getattr(engine.dialect, "driver", None),
             "server_version_info": getattr(engine.dialect, "server_version_info", None),
         }
 
-    @classmethod
-    def _get_curr_sqlglot_dialect(cls):
+    def _get_curr_sqlglot_dialect(self):
         """Get the dialect name in sqlglot package scope
 
         Returns
@@ -380,7 +379,7 @@ class Connection:
             Available dialect in sqlglot package, see more:
             https://github.com/tobymao/sqlglot/blob/main/sqlglot/dialects/dialect.py
         """
-        connection_info = cls._get_curr_sqlalchemy_connection_info()
+        connection_info = self._get_curr_sqlalchemy_connection_info()
         if not connection_info:
             return None
 
@@ -388,8 +387,7 @@ class Connection:
             connection_info["dialect"], connection_info["dialect"]
         )
 
-    @classmethod
-    def is_use_backtick_template(cls):
+    def is_use_backtick_template(self):
         """Get if the dialect support backtick (`) syntax as identifier
 
         Returns
@@ -397,7 +395,7 @@ class Connection:
         bool
             Indicate if the dialect can use backtick identifier in the SQL clause
         """
-        cur_dialect = cls._get_curr_sqlglot_dialect()
+        cur_dialect = self._get_curr_sqlglot_dialect()
         if not cur_dialect:
             return False
         try:
@@ -407,29 +405,7 @@ class Connection:
         except (ValueError, AttributeError, TypeError):
             return False
 
-    @classmethod
-    def _transpile_query(cls, query):
-        """Translate the given SQL clause that's compatible to current connected
-        dialect by sqlglot
-
-        Parameters
-        ----------
-        query : str
-            Original SQL clause
-
-        Returns
-        -------
-        str
-            SQL clause that's compatible to current connected dialect
-        """
-        write_dialect = cls._get_curr_sqlglot_dialect()
-        try:
-            query = sqlglot.parse_one(query).sql(dialect=write_dialect)
-        finally:
-            return query
-
-    @classmethod
-    def get_curr_identifiers(cls) -> list:
+    def get_curr_identifiers(self) -> list:
         """
         Returns list of identifiers for current connection
 
@@ -437,7 +413,7 @@ class Connection:
         """
         identifiers = ["", '"']
         try:
-            connection_info = cls._get_curr_sqlalchemy_connection_info()
+            connection_info = self._get_curr_sqlalchemy_connection_info()
             if connection_info:
                 cur_dialect = connection_info["dialect"]
                 identifiers_ = sqlglot.Dialect.get_or_raise(
@@ -449,3 +425,23 @@ class Connection:
             pass
 
         return identifiers
+
+    def _transpile_query(self, query):
+        """Translate the given SQL clause that's compatible to current connected
+        dialect by sqlglot
+
+        Parameters
+        ----------
+        query : str
+            Original SQL clause
+
+        Returns
+        -------
+        str
+            SQL clause that's compatible to current connected dialect
+        """
+        write_dialect = self._get_curr_sqlglot_dialect()
+        try:
+            query = sqlglot.parse_one(query).sql(dialect=write_dialect)
+        finally:
+            return query
diff --git a/src/sql/inspect.py b/src/sql/inspect.py
index 1a706d6..21b0142 100644
--- a/src/sql/inspect.py
+++ b/src/sql/inspect.py
@@ -44,6 +44,37 @@ class Tables(DatabaseInspection):
         self._table_txt = self._table.get_string()
 
 
+def _add_missing_keys(keys, mapping):
+    """
+    Return a copy of `mapping` with all the missing `keys`, setting the
+    value as an empty string
+    """
+    return {key: mapping.get(key, "") for key in keys}
+
+
+# we're assuming there's one row that contains all keys, I tested this and worked fine
+# my initial implementation just took all keys that appeared in "rows" but then order
+# isn't preserved, which is important for user experience
+def _get_row_with_most_keys(rows):
+    """
+    Get the row with the maximum length from the nested lists in `rows`
+    """
+    if not rows:
+        return list()
+
+    max_idx, max_ = None, 0
+
+    for idx, row in enumerate(rows):
+        if len(row) > max_:
+            max_idx = idx
+            max_ = len(row)
+
+    if max_idx is None:
+        return list()
+
+    return list(rows[max_idx])
+
+
 @modify_exceptions
 class Columns(DatabaseInspection):
     """
@@ -55,13 +86,18 @@ class Columns(DatabaseInspection):
 
         inspector = _get_inspector(conn)
 
-        columns = inspector.get_columns(name, schema)
+        # this returns a list of dictionaries. e.g.,
+        # [{"name": "column_a", "type": "INT"}
+        #  {"name": "column_b", "type": "FLOAT"}]
+        columns = inspector.get_columns(name, schema) or []
 
         self._table = PrettyTable()
-        self._table.field_names = list(columns[0].keys())
+        self._table.field_names = _get_row_with_most_keys(columns)
 
         for row in columns:
-            self._table.add_row(list(row.values()))
+            self._table.add_row(
+                list(_add_missing_keys(self._table.field_names, row).values())
+            )
 
         self._table_html = self._table.get_html_string()
         self._table_txt = self._table.get_string()
diff --git a/src/sql/magic.py b/src/sql/magic.py
index ff86d5b..e8568dc 100644
--- a/src/sql/magic.py
+++ b/src/sql/magic.py
@@ -341,9 +341,7 @@ class SqlMagic(Magics, Configurable):
             creator=args.creator,
             alias=args.alias,
         )
-        payload[
-            "connection_info"
-        ] = sql.connection.Connection._get_curr_sqlalchemy_connection_info()
+        payload["connection_info"] = conn._get_curr_sqlalchemy_connection_info()
         if args.persist:
             return self._persist_dataframe(
                 command.sql, conn, user_ns, append=False, index=not args.no_index
diff --git a/src/sql/plot.py b/src/sql/plot.py
index 0e5f444..ef70676 100644
--- a/src/sql/plot.py
+++ b/src/sql/plot.py
@@ -24,7 +24,9 @@ from sql.telemetry import telemetry
 import warnings
 
 
-def _summary_stats(con, table, column, with_=None):
+def _summary_stats(conn, table, column, with_=None):
+    if not conn:
+        conn = sql.connection.Connection.current
     """Compute percentiles and mean for boxplot"""
     template = Template(
         """
@@ -42,12 +44,14 @@ FROM "{{table}}"
     if with_:
         query = str(store.render(query, with_=with_))
 
-    values = con.execute(sqlalchemy.sql.text(query)).fetchone()
+    values = conn.session.execute(sqlalchemy.sql.text(query)).fetchone()
     keys = ["q1", "med", "q3", "mean", "N"]
     return {k: float(v) for k, v in zip(keys, values)}
 
 
-def _whishi(con, table, column, hival, with_=None):
+def _whishi(conn, table, column, hival, with_=None):
+    if not conn:
+        conn = sql.connection.Connection.current
     template = Template(
         """
 SELECT COUNT(*), MAX("{{column}}")
@@ -63,13 +67,15 @@ FROM (
 
     if with_:
         query = str(store.render(query, with_=with_))
-    query = sql.connection.Connection._transpile_query(query)
-    values = con.execute(sqlalchemy.sql.text(query)).fetchone()
+    query = conn._transpile_query(query)
+    values = conn.session.execute(sqlalchemy.sql.text(query)).fetchone()
     keys = ["N", "wiskhi_max"]
     return {k: float(v) for k, v in zip(keys, values)}
 
 
-def _whislo(con, table, column, loval, with_=None):
+def _whislo(conn, table, column, loval, with_=None):
+    if not conn:
+        conn = sql.connection.Connection.current
     template = Template(
         """
 SELECT COUNT(*), MIN("{{column}}")
@@ -85,13 +91,15 @@ FROM (
 
     if with_:
         query = str(store.render(query, with_=with_))
-    query = sql.connection.Connection._transpile_query(query)
-    values = con.execute(sqlalchemy.sql.text(query)).fetchone()
+    query = conn._transpile_query(query)
+    values = conn.session.execute(sqlalchemy.sql.text(query)).fetchone()
     keys = ["N", "wisklo_min"]
     return {k: float(v) for k, v in zip(keys, values)}
 
 
-def _percentile(con, table, column, pct, with_=None):
+def _percentile(conn, table, column, pct, with_=None):
+    if not conn:
+        conn = sql.connection.Connection.current.session
     template = Template(
         """
 SELECT
@@ -103,12 +111,12 @@ FROM "{{table}}"
 
     if with_:
         query = str(store.render(query, with_=with_))
-    query = sql.connection.Connection._transpile_query(query)
-    values = con.execute(sqlalchemy.sql.text(query)).fetchone()[0]
+    query = conn._transpile_query(query)
+    values = conn.session.execute(sqlalchemy.sql.text(query)).fetchone()[0]
     return values
 
 
-def _between(con, table, column, whislo, whishi, with_=None):
+def _between(conn, table, column, whislo, whishi, with_=None):
     template = Template(
         """
 SELECT "{{column}}"
@@ -121,14 +129,18 @@ OR  "{{column}}" > {{whishi}}
 
     if with_:
         query = str(store.render(query, with_=with_))
-    query = sql.connection.Connection._transpile_query(query)
-    results = [float(n[0]) for n in con.execute(sqlalchemy.sql.text(query)).fetchall()]
+    query = conn._transpile_query(query)
+    results = [
+        float(n[0]) for n in conn.session.execute(sqlalchemy.sql.text(query)).fetchall()
+    ]
     return results
 
 
 # https://github.com/matplotlib/matplotlib/blob/b5ac96a8980fdb9e59c9fb649e0714d776e26701/lib/matplotlib/cbook/__init__.py
 @modify_exceptions
-def _boxplot_stats(con, table, column, whis=1.5, autorange=False, with_=None):
+def _boxplot_stats(conn, table, column, whis=1.5, autorange=False, with_=None):
+    if not conn:
+        conn = sql.connection.Connection.current
     """Compute statistics required to create a boxplot"""
 
     def _compute_conf_interval(N, med, iqr):
@@ -140,7 +152,7 @@ def _boxplot_stats(con, table, column, whis=1.5, autorange=False, with_=None):
     stats = dict()
 
     # arithmetic mean
-    s_stats = _summary_stats(con, table, column, with_=with_)
+    s_stats = _summary_stats(conn, table, column, with_=with_)
 
     stats["mean"] = s_stats["mean"]
     q1, med, q3 = s_stats["q1"], s_stats["med"], s_stats["q3"]
@@ -157,7 +169,7 @@ def _boxplot_stats(con, table, column, whis=1.5, autorange=False, with_=None):
 
     # lowest/highest non-outliers
     if np.iterable(whis) and not isinstance(whis, str):
-        loval, hival = _percentile(con, table, column, whis, with_=with_)
+        loval, hival = _percentile(conn, table, column, whis, with_=with_)
 
     elif np.isreal(whis):
         loval = q1 - whis * stats["iqr"]
@@ -166,7 +178,7 @@ def _boxplot_stats(con, table, column, whis=1.5, autorange=False, with_=None):
         raise ValueError("whis must be a float or list of percentiles")
 
     # get high extreme
-    wiskhi_d = _whishi(con, table, column, hival, with_=with_)
+    wiskhi_d = _whishi(conn, table, column, hival, with_=with_)
 
     if wiskhi_d["N"] == 0 or wiskhi_d["wiskhi_max"] < q3:
         stats["whishi"] = q3
@@ -174,7 +186,7 @@ def _boxplot_stats(con, table, column, whis=1.5, autorange=False, with_=None):
         stats["whishi"] = wiskhi_d["wiskhi_max"]
 
     # get low extreme
-    wisklo_d = _whislo(con, table, column, loval, with_=with_)
+    wisklo_d = _whislo(conn, table, column, loval, with_=with_)
 
     if wisklo_d["N"] == 0 or wisklo_d["wisklo_min"] > q1:
         stats["whislo"] = q1
@@ -183,7 +195,7 @@ def _boxplot_stats(con, table, column, whis=1.5, autorange=False, with_=None):
 
     # compute a single array of outliers
     stats["fliers"] = np.array(
-        _between(con, table, column, stats["whislo"], stats["whishi"], with_=with_)
+        _between(conn, table, column, stats["whislo"], stats["whishi"], with_=with_)
     )
 
     # add in the remaining stats
@@ -245,11 +257,9 @@ def boxplot(payload, table, column, *, orient="v", with_=None, conn=None, ax=Non
     .. plot:: ../examples/plot_boxplot_many.py
     """
     if not conn:
-        conn = sql.connection.Connection.current.session
+        conn = sql.connection.Connection.current
 
-    payload[
-        "connection_info"
-    ] = sql.connection.Connection._get_curr_sqlalchemy_connection_info()
+    payload["connection_info"] = conn._get_curr_sqlalchemy_connection_info()
 
     ax = plt.gca()
     vert = orient == "v"
@@ -273,13 +283,14 @@ def boxplot(payload, table, column, *, orient="v", with_=None, conn=None, ax=Non
 
 
 def _min_max(con, table, column, with_=None, use_backticks=False):
+    if not con:
+        con = sql.connection.Connection.current
     template_ = """
 SELECT
     MIN("{{column}}"),
     MAX("{{column}}")
 FROM "{{table}}"
 """
-
     if use_backticks:
         template_ = template_.replace('"', "`")
 
@@ -288,8 +299,8 @@ FROM "{{table}}"
 
     if with_:
         query = str(store.render(query, with_=with_))
-    query = sql.connection.Connection._transpile_query(query)
-    min_, max_ = con.execute(sqlalchemy.sql.text(query)).fetchone()
+    query = con._transpile_query(query)
+    min_, max_ = con.session.execute(sqlalchemy.sql.text(query)).fetchone()
     return min_, max_
 
 
@@ -367,10 +378,12 @@ def histogram(
 
     .. plot:: ../examples/plot_histogram_many.py
     """
+    if not conn:
+        conn = sql.connection.Connection.current
+
+    print("Current conn: ", conn)
     ax = ax or plt.gca()
-    payload[
-        "connection_info"
-    ] = sql.connection.Connection._get_curr_sqlalchemy_connection_info()
+    payload["connection_info"] = conn._get_curr_sqlalchemy_connection_info()
     if category:
         if isinstance(column, list):
             if len(column) > 1:
@@ -485,11 +498,8 @@ def histogram(
 def _histogram(table, column, bins, with_=None, conn=None, facet=None):
     """Compute bins and heights"""
     if not conn:
-        conn = sql.connection.Connection.current.session
-        use_backticks = sql.connection.Connection.is_use_backtick_template()
-    else:
-        # TODO: fix
-        use_backticks = False
+        conn = sql.connection.Connection.current
+    use_backticks = conn.is_use_backtick_template()
 
     # FIXME: we're computing all the with elements twice
     min_, max_ = _min_max(conn, table, column, with_=with_, use_backticks=use_backticks)
@@ -545,8 +555,8 @@ def _histogram(table, column, bins, with_=None, conn=None, facet=None):
     if with_:
         query = str(store.render(query, with_=with_))
 
-    query = sql.connection.Connection._transpile_query(query)
-    data = conn.execute(sqlalchemy.sql.text(query)).fetchall()
+    query = conn._transpile_query(query)
+    data = conn.session.execute(sqlalchemy.sql.text(query)).fetchall()
     bin_, height = zip(*data)
 
     if bin_[0] is None:
@@ -568,7 +578,7 @@ def _histogram_stacked(
 ):
     """Compute the corresponding heights of each bin based on the category"""
     if not conn:
-        conn = sql.connection.Connection.current.session
+        conn = sql.connection.Connection.current
 
     cases = []
     for bin in bins:
@@ -605,7 +615,7 @@ def _histogram_stacked(
     if with_:
         query = str(store.render(query, with_=with_))
 
-    query = sql.connection.Connection._transpile_query(query)
-    data = conn.execute(sqlalchemy.text(query)).fetchall()
+    query = conn._transpile_query(query)
+    data = conn.session.execute(sqlalchemy.sql.text(query)).fetchall()
 
     return data
diff --git a/src/sql/run.py b/src/sql/run.py
index c2bc518..b9591d5 100644
--- a/src/sql/run.py
+++ b/src/sql/run.py
@@ -181,7 +181,7 @@ class ResultSet(list, ColumnGuesserMixin):
         frame = pd.DataFrame(self, columns=(self and self.keys) or [])
         payload[
             "connection_info"
-        ] = sql.connection.Connection._get_curr_sqlalchemy_connection_info()
+        ] = sql.connection.Connection.current._get_curr_sqlalchemy_connection_info()
         return frame
 
     @telemetry.log_call("polars-data-frame")
diff --git a/src/sql/store.py b/src/sql/store.py
index 5c5a035..b76ae49 100644
--- a/src/sql/store.py
+++ b/src/sql/store.py
@@ -111,7 +111,7 @@ class SQLQuery:
             """WITH{% for name in with_ %} `{{name}}` AS ({{saved[name]._query}})\
 {{ "," if not loop.last }}{% endfor %}{{query}}"""
         )
-        is_use_backtick = sql.connection.Connection.is_use_backtick_template()
+        is_use_backtick = sql.connection.Connection.current.is_use_backtick_template()
         with_all = _get_dependencies(self._store, self._with_)
         template = (
             with_clause_template_backtick if is_use_backtick else with_clause_template
diff --git a/src/sql/util.py b/src/sql/util.py
index 2994657..19f472c 100644
--- a/src/sql/util.py
+++ b/src/sql/util.py
@@ -39,7 +39,11 @@ def _is_long_number(num) -> bool:
 
 
 def is_table_exists(
-    table: str, schema: str = None, ignore_error: bool = False, with_: str = None
+    table: str,
+    schema: str = None,
+    ignore_error: bool = False,
+    with_: str = None,
+    conn=None,
 ) -> bool:
     """
     Checks if a given table exists for a given connection
@@ -63,6 +67,10 @@ def is_table_exists(
             return False
         else:
             raise ValueError("Table cannot be None")
+    if not Connection.current:
+        raise RuntimeError("No active connection")
+    if not conn:
+        conn = Connection.current
 
     table = strip_multiple_chars(table, "\"'")
 
@@ -71,7 +79,7 @@ def is_table_exists(
     else:
         table_ = table
 
-    _is_exist = _is_table_exists(table_, with_)
+    _is_exist = _is_table_exists(table_, with_, conn)
 
     if not _is_exist:
         if not ignore_error:
@@ -152,11 +160,13 @@ def strip_multiple_chars(string: str, chars: str) -> str:
     return string.translate(str.maketrans("", "", chars))
 
 
-def _is_table_exists(table: str, with_: str) -> bool:
+def _is_table_exists(table: str, with_: str, conn) -> bool:
     """
     Runs a SQL query to check if table exists
     """
-    identifiers = Connection.get_curr_identifiers()
+    if not conn:
+        conn = Connection.current
+    identifiers = conn.get_curr_identifiers()
     if with_:
         return table in list(store)
     else:
@@ -168,8 +178,8 @@ def _is_table_exists(table: str, with_: str) -> bool:
             else:
                 query = "SELECT * FROM {0}{1}{0} WHERE 1=0".format(iden, table)
             try:
-                query = sql.connection.Connection._transpile_query(query)
-                sql.run.raw_run(Connection.current, query)
+                query = conn._transpile_query(query)
+                sql.run.raw_run(conn, query)
                 return True
             except Exception:
                 pass


Test patch:
diff --git a/src/tests/test_connection.py b/src/tests/test_connection.py
index 84dffdc..bdba852 100644
--- a/src/tests/test_connection.py
+++ b/src/tests/test_connection.py
@@ -1,11 +1,13 @@
 import sys
-from unittest.mock import Mock, patch
+from unittest.mock import ANY, Mock, patch
 import pytest
+from sqlalchemy import create_engine
 from sqlalchemy.engine import Engine
 import sql.connection
 from sql.connection import Connection
 from IPython.core.error import UsageError
 import sqlglot
+import sqlalchemy
 
 
 @pytest.fixture
@@ -14,6 +16,13 @@ def cleanup():
     Connection.connections = {}
 
 
+@pytest.fixture
+def mock_database(monkeypatch, cleanup):
+    monkeypatch.setitem(sys.modules, "some_driver", Mock())
+    monkeypatch.setattr(Engine, "connect", Mock())
+    monkeypatch.setattr(sqlalchemy, "create_engine", Mock())
+
+
 @pytest.fixture
 def mock_postgres(monkeypatch, cleanup):
     monkeypatch.setitem(sys.modules, "psycopg2", Mock())
@@ -38,20 +47,21 @@ def test_alias(cleanup):
     assert list(Connection.connections) == ["some-alias"]
 
 
-def test_get_curr_sqlalchemy_connection_info(mock_postgres):
-    Connection.from_connect_str("postgresql://user:topsecret@somedomain.com/db")
-    assert Connection._get_curr_sqlalchemy_connection_info() == {
-        "dialect": "postgresql",
-        "driver": "psycopg2",
-        "server_version_info": None,
+def test_get_curr_sqlalchemy_connection_info():
+    engine = create_engine("sqlite://")
+    conn = Connection(engine=engine)
+
+    assert conn._get_curr_sqlalchemy_connection_info() == {
+        "dialect": "sqlite",
+        "driver": "pysqlite",
+        "server_version_info": ANY,
     }
 
 
-def test_get_curr_sqlglot_dialect_no_curr_connection(monkeypatch):
-    monkeypatch.setattr(
-        Connection, "_get_curr_sqlalchemy_connection_info", lambda: None
-    )
-    assert Connection._get_curr_sqlglot_dialect() is None
+def test_get_curr_sqlglot_dialect_no_curr_connection(mock_database, monkeypatch):
+    conn = Connection(engine=sqlalchemy.create_engine("someurl://"))
+    monkeypatch.setattr(conn, "_get_curr_sqlalchemy_connection_info", lambda: None)
+    assert conn._get_curr_sqlglot_dialect() is None
 
 
 @pytest.mark.parametrize(
@@ -93,7 +103,7 @@ def test_get_curr_sqlglot_dialect_no_curr_connection(monkeypatch):
     ],
 )
 def test_get_curr_sqlglot_dialect(
-    monkeypatch, sqlalchemy_connection_info, expected_sqlglot_dialect
+    monkeypatch, sqlalchemy_connection_info, expected_sqlglot_dialect, mock_database
 ):
     """To test if we can get the dialect name in sqlglot package scope
 
@@ -102,8 +112,10 @@ def test_get_curr_sqlglot_dialect(
         sqlalchemy_connection_info (dict): The metadata about the current dialect
         expected_sqlglot_dialect (str): Expected sqlglot dialect name
     """
+    conn = Connection(engine=sqlalchemy.create_engine("someurl://"))
+
     monkeypatch.setattr(
-        Connection,
+        conn,
         "_get_curr_sqlalchemy_connection_info",
         lambda: sqlalchemy_connection_info,
     )
@@ -112,7 +124,7 @@ def test_get_curr_sqlglot_dialect(
         "DIALECT_NAME_SQLALCHEMY_TO_SQLGLOT_MAPPING",
         {"sqlalchemy_mock_dialect_name": "sqlglot_mock_dialect"},
     )
-    assert Connection._get_curr_sqlglot_dialect() == expected_sqlglot_dialect
+    assert conn._get_curr_sqlglot_dialect() == expected_sqlglot_dialect
 
 
 @pytest.mark.parametrize(
@@ -123,7 +135,9 @@ def test_get_curr_sqlglot_dialect(
         ("postgres", False),
     ],
 )
-def test_is_use_backtick_template(monkeypatch, cur_dialect, expected_support_backtick):
+def test_is_use_backtick_template(
+    mock_database, cur_dialect, expected_support_backtick, monkeypatch
+):
     """To test if we can get the backtick supportive information from different dialects
 
     Args:
@@ -132,50 +146,66 @@ def test_is_use_backtick_template(monkeypatch, cur_dialect, expected_support_bac
         expected_support_backtick (bool): Excepted boolean value to indicate
         if the dialect supports backtick identifier
     """
-    monkeypatch.setattr(Connection, "_get_curr_sqlglot_dialect", lambda: cur_dialect)
-    assert Connection.is_use_backtick_template() == expected_support_backtick
+    # conn = Connection(engine=create_engine(sqlalchemy_url))
+    conn = Connection(engine=sqlalchemy.create_engine("someurl://"))
+    monkeypatch.setattr(conn, "_get_curr_sqlglot_dialect", lambda: cur_dialect)
+    assert conn.is_use_backtick_template() == expected_support_backtick
 
 
-def test_is_use_backtick_template_sqlglot_missing_dialect_ValueError(monkeypatch):
+def test_is_use_backtick_template_sqlglot_missing_dialect_ValueError(
+    mock_database, monkeypatch
+):
     """Since accessing missing dialect will raise ValueError from sqlglot, we assume
     that's not support case
     """
+    conn = Connection(engine=create_engine("sqlite://"))
+
     monkeypatch.setattr(
-        Connection, "_get_curr_sqlglot_dialect", lambda: "something_weird_dialect"
+        conn, "_get_curr_sqlglot_dialect", lambda: "something_weird_dialect"
     )
-    assert Connection.is_use_backtick_template() is False
+    assert conn.is_use_backtick_template() is False
 
 
-def test_is_use_backtick_template_sqlglot_missing_tokenizer_AttributeError(monkeypatch):
+def test_is_use_backtick_template_sqlglot_missing_tokenizer_AttributeError(
+    mock_database, monkeypatch
+):
     """Since accessing the dialect without Tokenizer Class will raise AttributeError
     from sqlglot, we assume that's not support case
     """
-    monkeypatch.setattr(Connection, "_get_curr_sqlglot_dialect", lambda: "mysql")
+    conn = Connection(engine=create_engine("sqlite://"))
+
+    monkeypatch.setattr(conn, "_get_curr_sqlglot_dialect", lambda: "mysql")
     monkeypatch.setattr(sqlglot.Dialect.get_or_raise("mysql"), "Tokenizer", None)
 
-    assert Connection.is_use_backtick_template() is False
+    assert conn.is_use_backtick_template() is False
 
 
-def test_is_use_backtick_template_sqlglot_missing_identifiers_TypeError(monkeypatch):
+def test_is_use_backtick_template_sqlglot_missing_identifiers_TypeError(
+    mock_database, monkeypatch
+):
     """Since accessing the IDENTIFIERS list of the dialect's Tokenizer Class
     will raise TypeError from sqlglot, we assume that's not support case
     """
-    monkeypatch.setattr(Connection, "_get_curr_sqlglot_dialect", lambda: "mysql")
+    conn = Connection(engine=create_engine("sqlite://"))
+
+    monkeypatch.setattr(conn, "_get_curr_sqlglot_dialect", lambda: "mysql")
     monkeypatch.setattr(
         sqlglot.Dialect.get_or_raise("mysql").Tokenizer, "IDENTIFIERS", None
     )
-    assert Connection.is_use_backtick_template() is False
+    assert conn.is_use_backtick_template() is False
 
 
-def test_is_use_backtick_template_sqlglot_empty_identifiers(monkeypatch):
+def test_is_use_backtick_template_sqlglot_empty_identifiers(mock_database, monkeypatch):
     """Since looking up the "`" symbol in IDENTIFIERS list of the dialect's
     Tokenizer Class will raise TypeError from sqlglot, we assume that's not support case
     """
-    monkeypatch.setattr(Connection, "_get_curr_sqlglot_dialect", lambda: "mysql")
+    conn = Connection(engine=create_engine("sqlite://"))
+
+    monkeypatch.setattr(conn, "_get_curr_sqlglot_dialect", lambda: "mysql")
     monkeypatch.setattr(
         sqlglot.Dialect.get_or_raise("mysql").Tokenizer, "IDENTIFIERS", []
     )
-    assert Connection.is_use_backtick_template() is False
+    assert conn.is_use_backtick_template() is False
 
 
 # Mock the missing package
@@ -227,6 +257,9 @@ def test_missing_driver(
         assert "try to install package: " + missing_pkg in str(error.value)
 
 
-def test_no_current_connection_and_get_info(monkeypatch):
-    monkeypatch.setattr(Connection, "current", None)
-    assert Connection._get_curr_sqlalchemy_connection_info() is None
+def test_no_current_connection_and_get_info(monkeypatch, mock_database):
+    engine = create_engine("sqlite://")
+    conn = Connection(engine=engine)
+
+    monkeypatch.setattr(conn, "session", None)
+    assert conn._get_curr_sqlalchemy_connection_info() is None
diff --git a/src/tests/test_inspect.py b/src/tests/test_inspect.py
index 320a06c..a5ae492 100644
--- a/src/tests/test_inspect.py
+++ b/src/tests/test_inspect.py
@@ -1,7 +1,11 @@
+from unittest.mock import Mock
+
 from inspect import getsource
 import pytest
 from functools import partial
 
+from prettytable import PrettyTable
+
 from sql import inspect, connection
 
 
@@ -124,3 +128,114 @@ ATTACH DATABASE 'my.db' AS test_schema
     schema_names = inspect.get_schema_names()
     for schema in schema_names:
         assert schema in expected_schema_names
+
+
+@pytest.mark.parametrize(
+    "get_columns, rows, field_names, name, schema",
+    [
+        [
+            [
+                {"column_a": "a", "column_b": "b"},
+                # the second row does not have column_b
+                {
+                    "column_a": "a2",
+                },
+            ],
+            [["a", "b"], ["a2", ""]],
+            ["column_a", "column_b"],
+            "test_table",
+            None,
+        ],
+        [
+            [
+                {"column_a": "a", "column_b": "b"},
+                # the second row does not have column_b
+                {
+                    "column_a": "a2",
+                },
+            ],
+            [["a", "b"], ["a2", ""]],
+            ["column_a", "column_b"],
+            "another_table",
+            "another_schema",
+        ],
+        [
+            [
+                {
+                    "column_a": "a2",
+                },
+                # contains an extra column
+                {"column_a": "a", "column_b": "b"},
+            ],
+            [["a2", ""], ["a", "b"]],
+            ["column_a", "column_b"],
+            "test_table",
+            None,
+        ],
+        [
+            [
+                {"column_a": "a", "column_b": "b"},
+                {"column_b": "b2", "column_a": "a2"},
+            ],
+            [["a", "b"], ["a2", "b2"]],
+            ["column_a", "column_b"],
+            "test_table",
+            None,
+        ],
+        [
+            [
+                dict(),
+                dict(),
+            ],
+            [[], []],
+            [],
+            "test_table",
+            None,
+        ],
+        [
+            None,
+            [],
+            [],
+            "test_table",
+            None,
+        ],
+    ],
+    ids=[
+        "missing-val-second-row",
+        "missing-val-second-row-another-schema",
+        "extra-val-second-row",
+        "keeps-order",
+        "empty-dictionaries",
+        "none-return-value",
+    ],
+)
+def test_columns_with_missing_values(
+    tmp_empty, ip, monkeypatch, get_columns, rows, field_names, name, schema
+):
+    mock = Mock()
+    mock.get_columns.return_value = get_columns
+
+    monkeypatch.setattr(inspect, "_get_inspector", lambda _: mock)
+
+    ip.run_cell(
+        """%%sql sqlite:///another.db
+CREATE TABLE IF NOT EXISTS another_table (id INT)
+"""
+    )
+
+    ip.run_cell(
+        """%%sql sqlite:///my.db
+CREATE TABLE IF NOT EXISTS test_table (id INT)
+"""
+    )
+
+    ip.run_cell(
+        """%%sql
+ATTACH DATABASE 'another.db' as 'another_schema';
+"""
+    )
+
+    pt = PrettyTable(field_names=field_names)
+    pt.add_rows(rows)
+
+    assert str(inspect.get_columns(name=name, schema=schema)) == str(pt)
diff --git a/src/tests/test_plot.py b/src/tests/test_plot.py
index d18f817..bd7d4b1 100644
--- a/src/tests/test_plot.py
+++ b/src/tests/test_plot.py
@@ -54,7 +54,7 @@ def test_boxplot_stats(chinook_db, ip_empty):
     res = ip_empty.run_cell("%sql SELECT * FROM Invoice").result
     X = res.DataFrame().Total
     expected = cbook.boxplot_stats(X)
-    result = plot._boxplot_stats(Connection.current.session, "Invoice", "Total")
+    result = plot._boxplot_stats(Connection.current, "Invoice", "Total")
 
     assert DictOfFloats(result) == DictOfFloats(expected[0])
 
@@ -74,7 +74,7 @@ def test_boxplot_stats_exception(chinook_db, ip_empty):
         BaseException, match="whis must be a float or list of percentiles.*"
     ):
         plot._boxplot_stats(
-            Connection.current.session,
+            Connection.current,
             "Invoice",
             "Total",
             "Not a float or list of percentiles whis param",
diff --git a/src/tests/test_store.py b/src/tests/test_store.py
index f31d7ea..8233b7a 100644
--- a/src/tests/test_store.py
+++ b/src/tests/test_store.py
@@ -2,6 +2,7 @@ import pytest
 from sql.connection import Connection
 from IPython.core.error import UsageError
 from sql.store import SQLStore
+from sqlalchemy import create_engine
 
 
 @pytest.fixture(autouse=True)
@@ -106,8 +107,10 @@ def test_serial(with_, is_dialect_support_backtick, monkeypatch):
     monkeypatch : Monkeypatch
         A convenient fixture for monkey-patching
     """
+    conn = Connection(engine=create_engine("sqlite://"))
+
     monkeypatch.setattr(
-        Connection,
+        conn,
         "is_use_backtick_template",
         lambda: is_dialect_support_backtick,
     )
@@ -149,9 +152,9 @@ def test_branch_root(is_dialect_support_backtick, monkeypatch):
     monkeypatch : Monkeypatch
         A convenient fixture for monkey-patching
     """
-
+    conn = Connection(engine=create_engine("sqlite://"))
     monkeypatch.setattr(
-        Connection,
+        conn,
         "is_use_backtick_template",
         lambda: is_dialect_support_backtick,
     )
@@ -194,8 +197,10 @@ def test_branch_root_reverse_final_with(is_dialect_support_backtick, monkeypatch
     monkeypatch : Monkeypatch
         A convenient fixture for monkey-patching
     """
+    conn = Connection(engine=create_engine("sqlite://"))
+
     monkeypatch.setattr(
-        Connection,
+        conn,
         "is_use_backtick_template",
         lambda: is_dialect_support_backtick,
     )
@@ -237,8 +242,10 @@ def test_branch(is_dialect_support_backtick, monkeypatch):
     monkeypatch : Monkeypatch
         A convenient fixture for monkey-patching
     """
+    conn = Connection(engine=create_engine("sqlite://"))
+
     monkeypatch.setattr(
-        Connection,
+        conn,
         "is_use_backtick_template",
         lambda: is_dialect_support_backtick,
     )
diff --git a/src/tests/test_telemetry.py b/src/tests/test_telemetry.py
index 260ba0d..b018b89 100644
--- a/src/tests/test_telemetry.py
+++ b/src/tests/test_telemetry.py
@@ -5,6 +5,7 @@ import urllib.request
 from sql.telemetry import telemetry
 from sql import plot
 from sql.connection import Connection
+from sqlalchemy import create_engine
 
 # Ref: https://pytest.org/en/7.2.x/how-to/tmp_path.html#
 # Utilize tmp directory to store downloaded csv
@@ -39,7 +40,8 @@ def simple_file_path_penguins(tmpdir):
 
 @pytest.fixture
 def simple_db_conn():
-    return Connection.from_connect_str("duckdb://").session
+    engine = create_engine("duckdb://")
+    return Connection(engine=engine)
 
 
 @pytest.fixture