1
0
Fork 0

Adding upstream version 1.1.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-24 20:14:26 +01:00
parent a7c3cb7344
commit 7269eaf22a
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
23 changed files with 4597 additions and 0 deletions

47
.github/workflows/publish.yml vendored Normal file
View file

@ -0,0 +1,47 @@
name: Build and Publish Package
on:
pull_request:
branches:
- main
types:
- closed
jobs:
publish-package:
if: ${{ github.event.pull_request.merged == true && startsWith(github.event.pull_request.head.ref, 'release/v') }}
runs-on: ubuntu-latest
steps:
- name: Check out the main branch
uses: actions/checkout@v4
with:
ref: main
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.6.1
- name: Configure poetry
run: poetry config --no-interaction pypi-token.pypi ${{ secrets.PYPI_TOKEN }}
- name: Get this package's Version
id: package_version
run: echo "package_version=$(poetry version --short)" >> $GITHUB_OUTPUT
- name: Build package
run: poetry build --no-interaction
- name: Publish package to PyPI
run: poetry publish --no-interaction
- name: Create a Github Release
uses: softprops/action-gh-release@v1
with:
tag_name: v${{ steps.package_version.outputs.package_version }}
target_commitish: main
token: ${{ secrets.GH_RELEASE_TOKEN }}
body_path: CHANGELOG.md
files: |
LICENSE
dist/*harlequin*.whl
dist/*harlequin*.tar.gz

57
.github/workflows/release.yml vendored Normal file
View file

@ -0,0 +1,57 @@
name: Create Release Branch
on:
workflow_dispatch:
inputs:
newVersion:
description: A version number for this release (e.g., "0.1.0")
required: true
jobs:
prepare-release:
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Check out the main branch
uses: actions/checkout@v4
with:
ref: main
- name: Set up Python 3.10
uses: actions/setup-python@v4
with:
python-version: "3.10"
- name: Install Poetry
uses: snok/install-poetry@v1
with:
version: 1.6.1
- name: Create release branch
run: |
git checkout -b release/v${{ github.event.inputs.newVersion }}
git push --set-upstream origin release/v${{ github.event.inputs.newVersion }}
- name: Bump version
run: poetry version ${{ github.event.inputs.newVersion }} --no-interaction
- name: Ensure package can be built
run: poetry build --no-interaction
- name: Update CHANGELOG
uses: thomaseizinger/keep-a-changelog-new-release@v1
with:
version: ${{ github.event.inputs.newVersion }}
- name: Commit Changes
uses: stefanzweifel/git-auto-commit-action@v5
with:
commit_message: Bumps version to ${{ github.event.inputs.newVersion }}
- name: Create pull request into main
uses: thomaseizinger/create-pull-request@1.3.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
head: release/v${{ github.event.inputs.newVersion }}
base: main
title: v${{ github.event.inputs.newVersion }}
body: >
This PR was automatically generated. It bumps the version number
in pyproject.toml and updates CHANGELOG.md. You may have to close
this PR and reopen it to get the required checks to run.

161
.gitignore vendored Normal file
View file

@ -0,0 +1,161 @@
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
Pipfile
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
.pybuilder/
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
# For a library or package, you might want to ignore these files since the code is
# intended to run in multiple environments; otherwise, check them in:
# .python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# poetry
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
# This is especially recommended for binary packages to ensure reproducibility, and is more
# commonly ignored for libraries.
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock
# pdm
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
# in version control.
# https://pdm.fming.dev/#use-with-ide
.pdm.toml
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/
# Celery stuff
celerybeat-schedule
celerybeat.pid
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# pytype static type analyzer
.pytype/
# Cython debug symbols
cython_debug/
# PyCharm
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
# and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/

10
.harlequin.toml Normal file
View file

@ -0,0 +1,10 @@
default_profile = "azure"
[profiles.azure]
adapter = "mysql"
theme = "harlequin"
limit = 10000
host = "harlequin-mysql-dev.mysql.database.azure.com"
port = "3306"
database = "dev"
user = "harlequin"
password = "roEj5cN9Jdyqbyqf"

79
CHANGELOG.md Normal file
View file

@ -0,0 +1,79 @@
# harlequin-mysql CHANGELOG
All notable changes to this project will be documented in this file.
## [Unreleased]
## [1.1.0] - 2025-01-28
- Bumps the MySQL Connector Python version to >=9.1
- Bumps the required Harlequin version to >= 1.25.0
- Adds support for the `openid_token_file` connection option introduced with MySQL Connector 9.1
- This adapter now lazy-loads the catalog, which will dramatically improve the catalog performance for large databases with thousands of objects.
- This adapter now implements interactions for catalog items, like dropping tables, inserting columns at the cursor, etc.
## [1.0.0] - 2025-01-07
- Drops support for Python 3.8
- Adds support for Python 3.13
- Adds support for Harlequin 2.X
## [0.3.0] - 2024-08-20
- Implements `connection_id` for better persistence.
- Implements the `cancel()` protocol to cancel in-flight queries.
- Implements `close()`
- Fixes a bug where a race condition could cause a crash with an `AssertionError` ([#14](https://github.com/tconbeer/harlequin-mysql/issues/14) - thank you [@blasferna](https://github.com/blasferna)!).
## [0.2.0] - 2024-04-11
### Features
- Adds a `pool-size` CLI option to set the size of the MySQL connection pool. Defaults to 5.
### Bug Fixes
- Updates the connection pool config to keep all connections in sync after running a `use database` command ([#11](https://github.com/tconbeer/harlequin-mysql/issues/11) - thank you [@mlopezgva](https://github.com/mlopezgva)!).
- Handles several issues caused by running too many concurrent queries and not fetching results.
## [0.1.3] - 2024-01-29
### Fixes
- Fixes a typo in the help text for the `--user` option (thank you [@alexmalins](https://github.com/alexmalins)!).
## [0.1.2] - 2024-01-25
### Fixes
- Sets the `pool_name` property on the MySQL connection to prevent auto-generated pool names from being too long ([#6](https://github.com/tconbeer/harlequin-mysql/issues/6) - thank you [sondeokhyeon](https://github.com/sondeokhyeon)!).
## [0.1.1] - 2024-01-09
### Fixes
- Sorts relation names alphabetically and columns by ordinal position.
## [0.1.0] - 2023-12-14
### Features
- Adds a basic MySQL adapter with most common connection options.
[Unreleased]: https://github.com/tconbeer/harlequin-mysql/compare/1.1.0...HEAD
[1.1.0]: https://github.com/tconbeer/harlequin-mysql/compare/1.0.0...1.1.0
[1.0.0]: https://github.com/tconbeer/harlequin-mysql/compare/0.3.0...1.0.0
[0.3.0]: https://github.com/tconbeer/harlequin-mysql/compare/0.2.0...0.3.0
[0.2.0]: https://github.com/tconbeer/harlequin-mysql/compare/0.1.3...0.2.0
[0.1.3]: https://github.com/tconbeer/harlequin-mysql/compare/0.1.2...0.1.3
[0.1.2]: https://github.com/tconbeer/harlequin-mysql/compare/0.1.1...0.1.2
[0.1.1]: https://github.com/tconbeer/harlequin-mysql/compare/0.1.0...0.1.1
[0.1.0]: https://github.com/tconbeer/harlequin-mysql/compare/f2caef7de11e68bb2b9798fb597c3fc05044b71e...0.1.0

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Ted Conbeer
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

18
Makefile Normal file
View file

@ -0,0 +1,18 @@
.PHONY: check
check:
ruff format .
ruff check . --fix
mypy
pytest
.PHONY: init
init:
docker-compose up -d
.PHONY: clean
clean:
docker-compose down
.PHONY: serve
serve:
harlequin -P None -a mysql -h localhost -U root --password example --database dev

67
README.md Normal file
View file

@ -0,0 +1,67 @@
# harlequin-mysql
This repo provides the Harlequin adapter for MySQL.
## Installation
`harlequin-mysql` depends on `harlequin`, so installing this package will also install Harlequin.
### Using pip
To install this adapter into an activated virtual environment:
```bash
pip install harlequin-mysql
```
### Using poetry
```bash
poetry add harlequin-mysql
```
### Using pipx
If you do not already have Harlequin installed:
```bash
pip install harlequin-mysql
```
If you would like to add the Postgres adapter to an existing Harlequin installation:
```bash
pipx inject harlequin harlequin-mysql
```
### As an Extra
Alternatively, you can install Harlequin with the `mysql` extra:
```bash
pip install harlequin[mysql]
```
```bash
poetry add harlequin[mysql]
```
```bash
pipx install harlequin[mysql]
```
## Usage and Configuration
You can open Harlequin with the MySQL adapter by selecting it with the `-a` option and passing connection parameters as CLI options:
```bash
harlequin -a mysql -h localhost -p 3306 -U root --password example --database dev
```
The MySQL adapter does not accept a connection string or DSN.
Many more options are available; to see the full list, run:
```bash
harlequin --help
```
For more information, see the [Harlequin Docs](https://harlequin.sh/docs/mysql/index).

9
docker-compose.yml Normal file
View file

@ -0,0 +1,9 @@
services:
db:
image: mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
ports:
- 3306:3306

1483
poetry.lock generated Normal file

File diff suppressed because it is too large Load diff

67
pyproject.toml Normal file
View file

@ -0,0 +1,67 @@
[tool.poetry]
name = "harlequin-mysql"
version = "1.1.0"
description = "A Harlequin adapter for MySQL."
authors = ["Ted Conbeer <tconbeer@users.noreply.github.com>"]
license = "MIT"
readme = "README.md"
packages = [
{ include = "harlequin_mysql", from = "src" },
]
[tool.poetry.plugins."harlequin.adapter"]
mysql = "harlequin_mysql:HarlequinMySQLAdapter"
[tool.poetry.dependencies]
python = ">=3.9,<3.14"
harlequin = ">=1.25.0,<3"
mysql-connector-python = "^9.1.0"
[tool.poetry.group.dev.dependencies]
ruff = "^0.6"
pytest = "^8"
mypy = "^1.11"
pre-commit = "^3.5.0"
importlib_metadata = { version = ">=4.6.0", python = "<3.10.0" }
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
[tool.ruff]
target-version = "py39"
[tool.ruff.lint]
select = ["A", "B", "E", "F", "I"]
[tool.mypy]
python_version = "3.9"
files = [
"src/**/*.py",
"tests/**/*.py",
]
mypy_path = "src:stubs"
show_column_numbers = true
# show error messages from unrelated files
follow_imports = "normal"
# be strict
disallow_untyped_calls = true
disallow_untyped_defs = true
check_untyped_defs = true
disallow_untyped_decorators = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
strict_optional = true
warn_return_any = true
warn_no_return = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_unused_configs = true
no_implicit_reexport = true
strict_equality = true

View file

@ -0,0 +1,3 @@
from harlequin_mysql.adapter import HarlequinMySQLAdapter
__all__ = ["HarlequinMySQLAdapter"]

View file

@ -0,0 +1,428 @@
from __future__ import annotations
import re
from contextlib import suppress
from typing import Any, Sequence
from harlequin import (
HarlequinAdapter,
HarlequinConnection,
HarlequinCursor,
)
from harlequin.autocomplete.completion import HarlequinCompletion
from harlequin.catalog import Catalog, CatalogItem
from harlequin.exception import (
HarlequinConfigError,
HarlequinConnectionError,
HarlequinQueryError,
)
from mysql.connector import FieldType
from mysql.connector.cursor import MySQLCursor
from mysql.connector.errors import InternalError, PoolError
from mysql.connector.pooling import (
MySQLConnectionPool,
PooledMySQLConnection,
)
from textual_fastdatatable.backend import AutoBackendType
from harlequin_mysql.catalog import DatabaseCatalogItem
from harlequin_mysql.cli_options import MYSQLADAPTER_OPTIONS
from harlequin_mysql.completions import load_completions
USE_DATABASE_PROG = re.compile(
r"\s*use\s+([^\\/?%*:|\"<>.]{1,64})", flags=re.IGNORECASE
)
QUERY_INTERRUPT_MSG = "1317 (70100): Query execution was interrupted"
class HarlequinMySQLCursor(HarlequinCursor):
def __init__(
self,
cur: MySQLCursor,
conn: PooledMySQLConnection,
harlequin_conn: HarlequinMySQLConnection,
*_: Any,
**__: Any,
) -> None:
self.cur = cur
# copy description in case the cursor is closed before columns() is called
assert cur.description is not None
self.description = cur.description.copy()
self.conn = conn
self.harlequin_conn = harlequin_conn
self.connection_id = conn._cnx.connection_id
self._limit: int | None = None
def columns(self) -> list[tuple[str, str]]:
return [(col[0], self._get_short_type(col[1])) for col in self.description]
def set_limit(self, limit: int) -> "HarlequinMySQLCursor":
self._limit = limit
return self
def fetchall(self) -> AutoBackendType:
try:
if self._limit is None:
results = self.cur.fetchall()
else:
results = self.cur.fetchmany(self._limit)
return results
except Exception as e:
if str(e) == QUERY_INTERRUPT_MSG:
return []
else:
raise HarlequinQueryError(
msg=str(e),
title="Harlequin encountered an error while executing your query.",
) from e
finally:
self.conn.consume_results()
self.cur.close()
self.conn.close()
if self.connection_id:
self.harlequin_conn._in_use_connections.discard(self.connection_id)
@staticmethod
def _get_short_type(type_id: int) -> str:
mapping = {
FieldType.BIT: "010",
FieldType.BLOB: "0b",
FieldType.DATE: "d",
FieldType.DATETIME: "dt",
FieldType.DECIMAL: "#.#",
FieldType.DOUBLE: "#.#",
FieldType.ENUM: "enum",
FieldType.FLOAT: "#.#",
FieldType.GEOMETRY: "▽□",
FieldType.INT24: "###",
FieldType.JSON: "{}",
FieldType.LONG: "##",
FieldType.LONGLONG: "##",
FieldType.LONG_BLOB: "00b",
FieldType.MEDIUM_BLOB: "00b",
FieldType.NEWDATE: "d",
FieldType.NEWDECIMAL: "#.#",
FieldType.NULL: "",
FieldType.SET: "set",
FieldType.SHORT: "#",
FieldType.STRING: "s",
FieldType.TIME: "t",
FieldType.TIMESTAMP: "#ts",
FieldType.TINY: "#",
FieldType.TINY_BLOB: "b",
FieldType.VARCHAR: "s",
FieldType.VAR_STRING: "s",
FieldType.YEAR: "y",
}
return mapping.get(type_id, "?")
class HarlequinMySQLConnection(HarlequinConnection):
def __init__(
self,
conn_str: Sequence[str],
*_: Any,
init_message: str = "",
options: dict[str, Any],
) -> None:
self.init_message = init_message
self._in_use_connections: set[int] = set()
try:
self._pool: MySQLConnectionPool = MySQLConnectionPool(
pool_name="harlequin",
pool_reset_session=False,
autocommit=True,
**options,
)
except Exception as e:
raise HarlequinConnectionError(
msg=str(e), title="Harlequin could not connect to your database."
) from e
def safe_get_mysql_cursor(
self, buffered: bool = False
) -> tuple[PooledMySQLConnection | None, MySQLCursor | None]:
"""
Return None if the connection pool is exhausted, to avoid getting
in an unrecoverable state.
"""
try:
conn = self._pool.get_connection()
except (InternalError, PoolError):
# if we're out of connections, we can't raise a query error,
# or we get in a state where we have cursors without fetched
# results, which requires a restart of Harlequin. Instead,
# just return None and silently fail (there isn't a sensible
# way to show an error to the user without aborting processing
# all the other cursors).
return None, None
try:
cur: MySQLCursor = conn.cursor(buffered=buffered)
except InternalError:
# cursor has an unread result. Try to consume the results,
# and try again.
conn.consume_results()
cur = conn.cursor(buffered=buffered)
return conn, cur
def set_pool_config(self, **config: Any) -> None:
"""
Updates the config of the MySQL connection pool.
"""
self._pool.set_config(**config)
def execute(self, query: str) -> HarlequinCursor | None:
retval: HarlequinCursor | None = None
conn, cur = self.safe_get_mysql_cursor()
if conn is None or cur is None:
return None
else:
connection_id = conn._cnx.connection_id
if connection_id:
self._in_use_connections.add(connection_id)
try:
cur.execute(query)
except Exception as e:
cur.close()
conn.close()
if connection_id:
self._in_use_connections.discard(connection_id)
if str(e) == QUERY_INTERRUPT_MSG:
return None
else:
raise HarlequinQueryError(
msg=str(e),
title="Harlequin encountered an error while executing your query.",
) from e
else:
if cur.description is not None:
retval = HarlequinMySQLCursor(cur, conn=conn, harlequin_conn=self)
else:
cur.close()
conn.close()
if connection_id:
self._in_use_connections.discard(connection_id)
# this is a hack to update all connections in the pool if the user
# changes the database for the active connection.
# it is impossible to check the database or other config
# of a connection with an open cursor, and we can't use a dedicated
# connection for user queries, since mysql only supports a single
# (unfetched) cursor per connection.
if match := USE_DATABASE_PROG.match(query):
new_db = match.group(1)
self.set_pool_config(database=new_db)
return retval
def cancel(self) -> None:
# get a new cursor to execute the KILL statements
conn, cur = self.safe_get_mysql_cursor()
if conn is None or cur is None:
return None
# loop through in-use connections and kill each of them
for connection_id in self._in_use_connections:
try:
cur.execute("KILL QUERY %s", (connection_id,))
except BaseException:
continue
cur.close()
conn.close()
self._in_use_connections = set()
def close(self) -> None:
with suppress(PoolError):
self._pool._remove_connections()
def get_catalog(self) -> Catalog:
databases = self._get_databases()
db_items: list[CatalogItem] = [
DatabaseCatalogItem.from_label(label=db, connection=self)
for (db,) in databases
]
return Catalog(items=db_items)
def get_completions(self) -> list[HarlequinCompletion]:
return load_completions()
def _get_databases(self) -> list[tuple[str]]:
conn, cur = self.safe_get_mysql_cursor(buffered=True)
if conn is None or cur is None:
raise HarlequinConnectionError(
title="Connection pool exhausted",
msg=(
"Connection pool exhausted. Try restarting Harlequin "
"with a larger pool or running fewer queries at once."
),
)
cur.execute(
"""
show databases
where `Database` not in (
'sys', 'information_schema', 'performance_schema', 'mysql'
)
"""
)
results: list[tuple[str]] = cur.fetchall() # type: ignore
cur.close()
conn.close()
return results
def _get_relations(self, db_name: str) -> list[tuple[str, str]]:
conn, cur = self.safe_get_mysql_cursor(buffered=True)
if conn is None or cur is None:
raise HarlequinConnectionError(
title="Connection pool exhausted",
msg=(
"Connection pool exhausted. Try restarting Harlequin "
"with a larger pool or running fewer queries at once."
),
)
cur.execute(
f"""
select
table_name,
table_type
from information_schema.tables
where table_schema = '{db_name}'
and table_type != 'SYSTEM VIEW'
order by table_name asc
;"""
)
results: list[tuple[str, str]] = cur.fetchall() # type: ignore
cur.close()
conn.close()
return results
def _get_columns(self, db_name: str, rel_name: str) -> list[tuple[str, str]]:
conn, cur = self.safe_get_mysql_cursor(buffered=True)
if conn is None or cur is None:
raise HarlequinConnectionError(
title="Connection pool exhausted",
msg=(
"Connection pool exhausted. Try restarting Harlequin "
"with a larger pool or running fewer queries at once."
),
)
cur.execute(
f"""
select column_name, data_type
from information_schema.columns
where
table_schema = '{db_name}'
and table_name = '{rel_name}'
and extra not like '%INVISIBLE%'
order by ordinal_position asc
;"""
)
results: list[tuple[str, str]] = cur.fetchall() # type: ignore
cur.close()
conn.close()
return results
@staticmethod
def _short_column_type(info_schema_type: str) -> str:
mapping = {
"bigint": "###",
"binary": "010",
"blob": "0b",
"char": "c",
"datetime": "dt",
"decimal": "#.#",
"double": "#.#",
"enum": "enum",
"float": "#.#",
"int": "##",
"json": "{}",
"longblob": "00b",
"longtext": "ss",
"mediumblob": "00b",
"mediumint": "##",
"mediumtext": "s",
"set": "set",
"smallint": "#",
"text": "s",
"time": "t",
"timestamp": "ts",
"tinyint": "#",
"varbinary": "010",
"varchar": "s",
}
return mapping.get(info_schema_type, "?")
class HarlequinMySQLAdapter(HarlequinAdapter):
ADAPTER_OPTIONS = MYSQLADAPTER_OPTIONS
IMPLEMENTS_CANCEL = True
def __init__(
self,
conn_str: Sequence[str],
host: str | None = None,
port: str | int | None = 3306,
unix_socket: str | None = None,
database: str | None = None,
user: str | None = None,
password: str | None = None,
password2: str | None = None,
password3: str | None = None,
connection_timeout: str | int | None = None,
ssl_ca: str | None = None,
ssl_cert: str | None = None,
ssl_disabled: str | bool | None = False,
ssl_key: str | None = None,
openid_token_file: str | None = None,
pool_size: str | int | None = 5,
**_: Any,
) -> None:
if conn_str:
raise HarlequinConnectionError(
f"Cannot provide a DSN to the MySQL adapter. Got:\n{conn_str}"
)
try:
self.options = {
"host": host,
"port": int(port) if port is not None else 3306,
"unix_socket": unix_socket,
"database": database,
"user": user,
"password": password,
"password2": password2,
"password3": password3,
"connection_timeout": int(connection_timeout)
if connection_timeout is not None
else None,
"ssl_ca": ssl_ca,
"ssl_cert": ssl_cert,
"ssl_disabled": ssl_disabled if ssl_disabled is not None else False,
"ssl_key": ssl_key,
"openid_token_file": openid_token_file,
"pool_size": int(pool_size) if pool_size is not None else 5,
}
except (ValueError, TypeError) as e:
raise HarlequinConfigError(
msg=f"MySQL adapter received bad config value: {e}",
title="Harlequin could not initialize the selected adapter.",
) from e
@property
def connection_id(self) -> str | None:
host = self.options.get("host", "") or ""
sock = self.options.get("unix_socket", "") or ""
host = host if host or sock else "127.0.0.1"
port = self.options.get("port", 3306)
database = self.options.get("database", "") or ""
return f"{host}{sock}:{port}/{database}"
def connect(self) -> HarlequinMySQLConnection:
conn = HarlequinMySQLConnection(conn_str=tuple(), options=self.options)
return conn

View file

@ -0,0 +1,154 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import TYPE_CHECKING
from harlequin.catalog import InteractiveCatalogItem
from harlequin_mysql.interactions import (
execute_drop_database_statement,
execute_drop_table_statement,
execute_drop_view_statement,
execute_use_statement,
insert_columns_at_cursor,
show_select_star,
)
if TYPE_CHECKING:
from harlequin_mysql.adapter import HarlequinMySQLConnection
@dataclass
class ColumnCatalogItem(InteractiveCatalogItem["HarlequinMySQLConnection"]):
parent: "RelationCatalogItem" | None = None
@classmethod
def from_parent(
cls,
parent: "RelationCatalogItem",
label: str,
type_label: str,
) -> "ColumnCatalogItem":
column_qualified_identifier = f"{parent.qualified_identifier}.`{label}`"
column_query_name = f"`{label}`"
return cls(
qualified_identifier=column_qualified_identifier,
query_name=column_query_name,
label=label,
type_label=type_label,
connection=parent.connection,
parent=parent,
loaded=True,
)
@dataclass
class RelationCatalogItem(InteractiveCatalogItem["HarlequinMySQLConnection"]):
INTERACTIONS = [
("Insert Columns at Cursor", insert_columns_at_cursor),
("Preview Data", show_select_star),
]
parent: "DatabaseCatalogItem" | None = None
def fetch_children(self) -> list[ColumnCatalogItem]:
if self.parent is None or self.connection is None:
return []
result = self.connection._get_columns(self.parent.label, self.label)
return [
ColumnCatalogItem.from_parent(
parent=self,
label=column_name,
type_label=self.connection._short_column_type(column_type),
)
for column_name, column_type in result
]
class ViewCatalogItem(RelationCatalogItem):
INTERACTIONS = RelationCatalogItem.INTERACTIONS + [
("Drop View", execute_drop_view_statement),
]
@classmethod
def from_parent(
cls,
parent: "DatabaseCatalogItem",
label: str,
) -> "ViewCatalogItem":
relation_query_name = f"`{parent.label}`.`{label}`"
relation_qualified_identifier = f"{parent.qualified_identifier}.`{label}`"
return cls(
qualified_identifier=relation_qualified_identifier,
query_name=relation_query_name,
label=label,
type_label="v",
connection=parent.connection,
parent=parent,
)
class TableCatalogItem(RelationCatalogItem):
INTERACTIONS = RelationCatalogItem.INTERACTIONS + [
("Drop Table", execute_drop_table_statement),
]
@classmethod
def from_parent(
cls,
parent: "DatabaseCatalogItem",
label: str,
) -> "TableCatalogItem":
relation_query_name = f"`{parent.label}`.`{label}`"
relation_qualified_identifier = f"{parent.qualified_identifier}.`{label}`"
return cls(
qualified_identifier=relation_qualified_identifier,
query_name=relation_query_name,
label=label,
type_label="t",
connection=parent.connection,
parent=parent,
)
@dataclass
class DatabaseCatalogItem(InteractiveCatalogItem["HarlequinMySQLConnection"]):
INTERACTIONS = [
("Set Editor Context (USE)", execute_use_statement),
("Drop Database", execute_drop_database_statement),
]
@classmethod
def from_label(
cls, label: str, connection: "HarlequinMySQLConnection"
) -> "DatabaseCatalogItem":
database_identifier = f"`{label}`"
return cls(
qualified_identifier=database_identifier,
query_name=database_identifier,
label=label,
type_label="db",
connection=connection,
)
def fetch_children(self) -> list[RelationCatalogItem]:
if self.connection is None:
return []
children: list[RelationCatalogItem] = []
result = self.connection._get_relations(self.label)
for table_label, table_type in result:
if table_type == "VIEW":
children.append(
ViewCatalogItem.from_parent(
parent=self,
label=table_label,
)
)
else:
children.append(
TableCatalogItem.from_parent(
parent=self,
label=table_label,
)
)
return children

View file

@ -0,0 +1,151 @@
from __future__ import annotations
from harlequin.options import (
FlagOption,
PathOption,
TextOption,
)
def _int_validator(s: str | None) -> tuple[bool, str]:
if s is None:
return True, ""
try:
_ = int(s)
except ValueError:
return False, f"Cannot convert {s} to an int!"
else:
return True, ""
host = TextOption(
name="host",
description=("The host name or IP address of the MySQL server."),
short_decls=["-h"],
default="localhost",
)
port = TextOption(
name="port",
description=("The TCP/IP port of the MySQL server. Must be an integer."),
short_decls=["-p"],
default="3306",
validator=_int_validator,
)
unix_socket = TextOption(
name="unix_socket",
description=("The location of the Unix socket file."),
)
database = TextOption(
name="database",
description=("The database name to use when connecting with the MySQL server."),
short_decls=["-d", "-db"],
default="postgres",
)
user = TextOption(
name="user",
description=("The user name used to authenticate with the MySQL server."),
short_decls=["-u", "--username", "-U"],
)
password = TextOption(
name="password",
description=("The password to authenticate the user with the MySQL server."),
short_decls=["--password1"],
)
password2 = TextOption(
name="password2",
description=("For Multi-Factor Authentication (MFA); Added in 8.0.28."),
)
password3 = TextOption(
name="password3",
description=("For Multi-Factor Authentication (MFA); Added in 8.0.28."),
)
connect_timeout = TextOption(
name="connection_timeout",
description="Timeout for the TCP and Unix socket connections. Must be an integer.",
short_decls=["--connect_timeout"],
validator=_int_validator,
)
ssl_ca = PathOption(
name="ssl-ca",
description="File containing the SSL certificate authority.",
exists=True,
dir_okay=False,
)
ssl_cert = PathOption(
name="ssl-cert",
description="File containing the SSL certificate file.",
exists=True,
dir_okay=False,
short_decls=["--sslcert"],
)
ssl_disabled = FlagOption(
name="ssl-disabled",
description="True disables SSL/TLS usage.",
)
ssl_key = PathOption(
name="ssl-key",
description="File containing the SSL key.",
exists=True,
dir_okay=False,
short_decls=["--sslkey"],
)
openid_token_file = PathOption(
name="openid-token-file",
description="File containing the OpenID Token.",
exists=True,
dir_okay=False,
short_decls=["--oid"],
)
pool_size = TextOption(
name="pool-size",
description=(
"The number of concurrent connections maintained by Harlequin. MySQL "
"only allows one cursor per connection, so this sets the number of queries "
"that can be executed at once in Harlequin."
),
short_decls=["-n"],
default="5",
validator=_int_validator,
)
MYSQLADAPTER_OPTIONS = [
host,
port,
unix_socket,
database,
user,
password,
password2,
password3,
connect_timeout,
ssl_ca,
ssl_cert,
ssl_disabled,
ssl_key,
openid_token_file,
pool_size,
]

View file

@ -0,0 +1,48 @@
from __future__ import annotations
import csv
import re
from pathlib import Path
from harlequin import HarlequinCompletion
WORD = re.compile(r"\w+")
def load_completions() -> list[HarlequinCompletion]:
completions: list[HarlequinCompletion] = []
keywords_path = Path(__file__).parent / "keywords.csv"
with keywords_path.open("r") as f:
reader = csv.reader(f, dialect="unix")
for name, reserved, removed in reader:
if removed == "False":
completions.append(
HarlequinCompletion(
label=name.lower(),
type_label="kw",
value=name.lower(),
priority=100 if reserved else 1000,
context=None,
)
)
functions_path = Path(__file__).parent / "functions.tsv"
with functions_path.open("r") as f:
reader = csv.reader(f, dialect="unix", delimiter="\t")
for name, _, _, deprecated in reader:
if deprecated:
continue
for alias in name.split(", "):
if WORD.match(alias):
completions.append(
HarlequinCompletion(
label=alias.split("...")[0].split("(")[0].lower(),
type_label="fn",
value=alias.split("...")[0].split("(")[0].lower(),
priority=1000,
context=None,
)
)
return completions

View file

@ -0,0 +1,441 @@
Name Description Introduced Deprecated
ABS() Return the absolute value
ACOS() Return the arc cosine
ADDDATE() Add time values (intervals) to a date value
ADDTIME() Add time
AES_DECRYPT() Decrypt using AES
AES_ENCRYPT() Encrypt using AES
AND, && Logical AND
ANY_VALUE() Suppress ONLY_FULL_GROUP_BY value rejection
ASCII() Return numeric value of left-most character
ASIN() Return the arc sine
asynchronous_connection_failover_add_managed() Add group member source server configuration information to a replication channel source list 8.0.23
asynchronous_connection_failover_add_source() Add source server configuration information server to a replication channel source list 8.0.22
asynchronous_connection_failover_delete_managed() Remove a managed group from a replication channel source list 8.0.23
asynchronous_connection_failover_delete_source() Remove a source server from a replication channel source list 8.0.22
asynchronous_connection_failover_reset() Remove all settings relating to group replication asynchronous failover 8.0.27
ATAN() Return the arc tangent
ATAN2(), ATAN() Return the arc tangent of the two arguments
AVG() Return the average value of the argument
BENCHMARK() Repeatedly execute an expression
BETWEEN ... AND ... Whether a value is within a range of values
BIN() Return a string containing binary representation of a number
BIN_TO_UUID() Convert binary UUID to string
BINARY Cast a string to a binary string 8.0.27
BIT_AND() Return bitwise AND
BIT_COUNT() Return the number of bits that are set
BIT_LENGTH() Return length of argument in bits
BIT_OR() Return bitwise OR
BIT_XOR() Return bitwise XOR
CAN_ACCESS_COLUMN() Internal use only
CAN_ACCESS_DATABASE() Internal use only
CAN_ACCESS_TABLE() Internal use only
CAN_ACCESS_USER() Internal use only 8.0.22
CAN_ACCESS_VIEW() Internal use only
CASE Case operator
CAST() Cast a value as a certain type
CEIL() Return the smallest integer value not less than the argument
CEILING() Return the smallest integer value not less than the argument
CHAR() Return the character for each integer passed
CHAR_LENGTH() Return number of characters in argument
CHARACTER_LENGTH() Synonym for CHAR_LENGTH()
CHARSET() Return the character set of the argument
COALESCE() Return the first non-NULL argument
COERCIBILITY() Return the collation coercibility value of the string argument
COLLATION() Return the collation of the string argument
COMPRESS() Return result as a binary string
CONCAT() Return concatenated string
CONCAT_WS() Return concatenate with separator
CONNECTION_ID() Return the connection ID (thread ID) for the connection
CONV() Convert numbers between different number bases
CONVERT() Cast a value as a certain type
CONVERT_TZ() Convert from one time zone to another
COS() Return the cosine
COT() Return the cotangent
COUNT() Return a count of the number of rows returned
COUNT(DISTINCT) Return the count of a number of different values
CRC32() Compute a cyclic redundancy check value
CUME_DIST() Cumulative distribution value
CURDATE() Return the current date
CURRENT_DATE(), CURRENT_DATE Synonyms for CURDATE()
CURRENT_ROLE() Return the current active roles
CURRENT_TIME(), CURRENT_TIME Synonyms for CURTIME()
CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP Synonyms for NOW()
CURRENT_USER(), CURRENT_USER The authenticated user name and host name
CURTIME() Return the current time
DATABASE() Return the default (current) database name
DATE() Extract the date part of a date or datetime expression
DATE_ADD() Add time values (intervals) to a date value
DATE_FORMAT() Format date as specified
DATE_SUB() Subtract a time value (interval) from a date
DATEDIFF() Subtract two dates
DAY() Synonym for DAYOFMONTH()
DAYNAME() Return the name of the weekday
DAYOFMONTH() Return the day of the month (0-31)
DAYOFWEEK() Return the weekday index of the argument
DAYOFYEAR() Return the day of the year (1-366)
DEFAULT() Return the default value for a table column
DEGREES() Convert radians to degrees
DENSE_RANK() Rank of current row within its partition, without gaps
DIV Integer division
ELT() Return string at index number
EXP() Raise to the power of
EXPORT_SET() Return a string such that for every bit set in the value bits, you get an on string and for every unset bit, you get an off string
EXTRACT() Extract part of a date
ExtractValue() Extract a value from an XML string using XPath notation
FIELD() Index (position) of first argument in subsequent arguments
FIND_IN_SET() Index (position) of first argument within second argument
FIRST_VALUE() Value of argument from first row of window frame
FLOOR() Return the largest integer value not greater than the argument
FORMAT() Return a number formatted to specified number of decimal places
FORMAT_BYTES() Convert byte count to value with units 8.0.16
FORMAT_PICO_TIME() Convert time in picoseconds to value with units 8.0.16
FOUND_ROWS() For a SELECT with a LIMIT clause, the number of rows that would be returned were there no LIMIT clause
FROM_BASE64() Decode base64 encoded string and return result
FROM_DAYS() Convert a day number to a date
FROM_UNIXTIME() Format Unix timestamp as a date
GeomCollection() Construct geometry collection from geometries
GeometryCollection() Construct geometry collection from geometries
GET_DD_COLUMN_PRIVILEGES() Internal use only
GET_DD_CREATE_OPTIONS() Internal use only
GET_DD_INDEX_SUB_PART_LENGTH() Internal use only
GET_FORMAT() Return a date format string
GET_LOCK() Get a named lock
GREATEST() Return the largest argument
GROUP_CONCAT() Return a concatenated string
group_replication_disable_member_action() Disable member action for event specified 8.0.26
group_replication_enable_member_action() Enable member action for event specified 8.0.26
group_replication_get_communication_protocol() Get version of group replication communication protocol currently in use 8.0.16
group_replication_get_write_concurrency() Get maximum number of consensus instances currently set for group 8.0.13
group_replication_reset_member_actions() Reset all member actions to defaults and configuration version number to 1 8.0.26
group_replication_set_as_primary() Make a specific group member the primary 8.0.29
group_replication_set_communication_protocol() Set version for group replication communication protocol to use 8.0.16
group_replication_set_write_concurrency() Set maximum number of consensus instances that can be executed in parallel 8.0.13
group_replication_switch_to_multi_primary_mode() Changes the mode of a group running in single-primary mode to multi-primary mode 8.0.13
group_replication_switch_to_single_primary_mode() Changes the mode of a group running in multi-primary mode to single-primary mode 8.0.13
GROUPING() Distinguish super-aggregate ROLLUP rows from regular rows
GTID_SUBSET() Return true if all GTIDs in subset are also in set; otherwise false.
GTID_SUBTRACT() Return all GTIDs in set that are not in subset.
HEX() Hexadecimal representation of decimal or string value
HOUR() Extract the hour
ICU_VERSION() ICU library version
IF() If/else construct
IFNULL() Null if/else construct
IN() Whether a value is within a set of values
INET_ATON() Return the numeric value of an IP address
INET_NTOA() Return the IP address from a numeric value
INET6_ATON() Return the numeric value of an IPv6 address
INET6_NTOA() Return the IPv6 address from a numeric value
INSERT() Insert substring at specified position up to specified number of characters
INSTR() Return the index of the first occurrence of substring
INTERNAL_AUTO_INCREMENT() Internal use only
INTERNAL_AVG_ROW_LENGTH() Internal use only
INTERNAL_CHECK_TIME() Internal use only
INTERNAL_CHECKSUM() Internal use only
INTERNAL_DATA_FREE() Internal use only
INTERNAL_DATA_LENGTH() Internal use only
INTERNAL_DD_CHAR_LENGTH() Internal use only
INTERNAL_GET_COMMENT_OR_ERROR() Internal use only
INTERNAL_GET_ENABLED_ROLE_JSON() Internal use only 8.0.19
INTERNAL_GET_HOSTNAME() Internal use only 8.0.19
INTERNAL_GET_USERNAME() Internal use only 8.0.19
INTERNAL_GET_VIEW_WARNING_OR_ERROR() Internal use only
INTERNAL_INDEX_COLUMN_CARDINALITY() Internal use only
INTERNAL_INDEX_LENGTH() Internal use only
INTERNAL_IS_ENABLED_ROLE() Internal use only 8.0.19
INTERNAL_IS_MANDATORY_ROLE() Internal use only 8.0.19
INTERNAL_KEYS_DISABLED() Internal use only
INTERNAL_MAX_DATA_LENGTH() Internal use only
INTERNAL_TABLE_ROWS() Internal use only
INTERNAL_UPDATE_TIME() Internal use only
INTERVAL() Return the index of the argument that is less than the first argument
IS Test a value against a boolean
IS_FREE_LOCK() Whether the named lock is free
IS_IPV4() Whether argument is an IPv4 address
IS_IPV4_COMPAT() Whether argument is an IPv4-compatible address
IS_IPV4_MAPPED() Whether argument is an IPv4-mapped address
IS_IPV6() Whether argument is an IPv6 address
IS NOT Test a value against a boolean
IS NOT NULL NOT NULL value test
IS NULL NULL value test
IS_USED_LOCK() Whether the named lock is in use; return connection identifier if true
IS_UUID() Whether argument is a valid UUID
ISNULL() Test whether the argument is NULL
JSON_ARRAY() Create JSON array
JSON_ARRAY_APPEND() Append data to JSON document
JSON_ARRAY_INSERT() Insert into JSON array
JSON_ARRAYAGG() Return result set as a single JSON array
JSON_CONTAINS() Whether JSON document contains specific object at path
JSON_CONTAINS_PATH() Whether JSON document contains any data at path
JSON_DEPTH() Maximum depth of JSON document
JSON_EXTRACT() Return data from JSON document
JSON_INSERT() Insert data into JSON document
JSON_KEYS() Array of keys from JSON document
JSON_LENGTH() Number of elements in JSON document
JSON_MERGE() Merge JSON documents, preserving duplicate keys. Deprecated synonym for JSON_MERGE_PRESERVE() Yes
JSON_MERGE_PATCH() Merge JSON documents, replacing values of duplicate keys
JSON_MERGE_PRESERVE() Merge JSON documents, preserving duplicate keys
JSON_OBJECT() Create JSON object
JSON_OBJECTAGG() Return result set as a single JSON object
JSON_OVERLAPS() Compares two JSON documents, returns TRUE (1) if these have any key-value pairs or array elements in common, otherwise FALSE (0) 8.0.17
JSON_PRETTY() Print a JSON document in human-readable format
JSON_QUOTE() Quote JSON document
JSON_REMOVE() Remove data from JSON document
JSON_REPLACE() Replace values in JSON document
JSON_SCHEMA_VALID() Validate JSON document against JSON schema; returns TRUE/1 if document validates against schema, or FALSE/0 if it does not 8.0.17
JSON_SCHEMA_VALIDATION_REPORT() Validate JSON document against JSON schema; returns report in JSON format on outcome on validation including success or failure and reasons for failure 8.0.17
JSON_SEARCH() Path to value within JSON document
JSON_SET() Insert data into JSON document
JSON_STORAGE_FREE() Freed space within binary representation of JSON column value following partial update
JSON_STORAGE_SIZE() Space used for storage of binary representation of a JSON document
JSON_TABLE() Return data from a JSON expression as a relational table
JSON_TYPE() Type of JSON value
JSON_UNQUOTE() Unquote JSON value
JSON_VALID() Whether JSON value is valid
JSON_VALUE() Extract value from JSON document at location pointed to by path provided; return this value as VARCHAR(512) or specified type 8.0.21
LAG() Value of argument from row lagging current row within partition
LAST_DAY Return the last day of the month for the argument
LAST_INSERT_ID() Value of the AUTOINCREMENT column for the last INSERT
LAST_VALUE() Value of argument from last row of window frame
LCASE() Synonym for LOWER()
LEAD() Value of argument from row leading current row within partition
LEAST() Return the smallest argument
LEFT() Return the leftmost number of characters as specified
LENGTH() Return the length of a string in bytes
LIKE Simple pattern matching
LineString() Construct LineString from Point values
LN() Return the natural logarithm of the argument
LOAD_FILE() Load the named file
LOCALTIME(), LOCALTIME Synonym for NOW()
LOCALTIMESTAMP, LOCALTIMESTAMP() Synonym for NOW()
LOCATE() Return the position of the first occurrence of substring
LOG() Return the natural logarithm of the first argument
LOG10() Return the base-10 logarithm of the argument
LOG2() Return the base-2 logarithm of the argument
LOWER() Return the argument in lowercase
LPAD() Return the string argument, left-padded with the specified string
LTRIM() Remove leading spaces
MAKE_SET() Return a set of comma-separated strings that have the corresponding bit in bits set
MAKEDATE() Create a date from the year and day of year
MAKETIME() Create time from hour, minute, second
MASTER_POS_WAIT() Block until the replica has read and applied all updates up to the specified position 8.0.26
MATCH() Perform full-text search
MAX() Return the maximum value
MBRContains() Whether MBR of one geometry contains MBR of another
MBRCoveredBy() Whether one MBR is covered by another
MBRCovers() Whether one MBR covers another
MBRDisjoint() Whether MBRs of two geometries are disjoint
MBREquals() Whether MBRs of two geometries are equal
MBRIntersects() Whether MBRs of two geometries intersect
MBROverlaps() Whether MBRs of two geometries overlap
MBRTouches() Whether MBRs of two geometries touch
MBRWithin() Whether MBR of one geometry is within MBR of another
MD5() Calculate MD5 checksum
MEMBER OF() Returns true (1) if first operand matches any element of JSON array passed as second operand, otherwise returns false (0) 8.0.17
MICROSECOND() Return the microseconds from argument
MID() Return a substring starting from the specified position
MIN() Return the minimum value
MINUTE() Return the minute from the argument
MOD() Return the remainder
MONTH() Return the month from the date passed
MONTHNAME() Return the name of the month
MultiLineString() Contruct MultiLineString from LineString values
MultiPoint() Construct MultiPoint from Point values
MultiPolygon() Construct MultiPolygon from Polygon values
NAME_CONST() Cause the column to have the given name
NOT, ! Negates value
NOT BETWEEN ... AND ... Whether a value is not within a range of values
NOT IN() Whether a value is not within a set of values
NOT LIKE Negation of simple pattern matching
NOT REGEXP Negation of REGEXP
NOW() Return the current date and time
NTH_VALUE() Value of argument from N-th row of window frame
NTILE() Bucket number of current row within its partition.
NULLIF() Return NULL if expr1 = expr2
OCT() Return a string containing octal representation of a number
OCTET_LENGTH() Synonym for LENGTH()
OR, || Logical OR
ORD() Return character code for leftmost character of the argument
PERCENT_RANK() Percentage rank value
PERIOD_ADD() Add a period to a year-month
PERIOD_DIFF() Return the number of months between periods
PI() Return the value of pi
Point() Construct Point from coordinates
Polygon() Construct Polygon from LineString arguments
POSITION() Synonym for LOCATE()
POW() Return the argument raised to the specified power
POWER() Return the argument raised to the specified power
PS_CURRENT_THREAD_ID() Performance Schema thread ID for current thread 8.0.16
PS_THREAD_ID() Performance Schema thread ID for given thread 8.0.16
QUARTER() Return the quarter from a date argument
QUOTE() Escape the argument for use in an SQL statement
RADIANS() Return argument converted to radians
RAND() Return a random floating-point value
RANDOM_BYTES() Return a random byte vector
RANK() Rank of current row within its partition, with gaps
REGEXP Whether string matches regular expression
REGEXP_INSTR() Starting index of substring matching regular expression
REGEXP_LIKE() Whether string matches regular expression
REGEXP_REPLACE() Replace substrings matching regular expression
REGEXP_SUBSTR() Return substring matching regular expression
RELEASE_ALL_LOCKS() Release all current named locks
RELEASE_LOCK() Release the named lock
REPEAT() Repeat a string the specified number of times
REPLACE() Replace occurrences of a specified string
REVERSE() Reverse the characters in a string
RIGHT() Return the specified rightmost number of characters
RLIKE Whether string matches regular expression
ROLES_GRAPHML() Return a GraphML document representing memory role subgraphs
ROUND() Round the argument
ROW_COUNT() The number of rows updated
ROW_NUMBER() Number of current row within its partition
RPAD() Append string the specified number of times
RTRIM() Remove trailing spaces
SCHEMA() Synonym for DATABASE()
SEC_TO_TIME() Converts seconds to 'hh:mm:ss' format
SECOND() Return the second (0-59)
SESSION_USER() Synonym for USER()
SHA1(), SHA() Calculate an SHA-1 160-bit checksum
SHA2() Calculate an SHA-2 checksum
SIGN() Return the sign of the argument
SIN() Return the sine of the argument
SLEEP() Sleep for a number of seconds
SOUNDEX() Return a soundex string
SOUNDS LIKE Compare sounds
SOURCE_POS_WAIT() Block until the replica has read and applied all updates up to the specified position 8.0.26
SPACE() Return a string of the specified number of spaces
SQRT() Return the square root of the argument
ST_Area() Return Polygon or MultiPolygon area
ST_AsBinary(), ST_AsWKB() Convert from internal geometry format to WKB
ST_AsGeoJSON() Generate GeoJSON object from geometry
ST_AsText(), ST_AsWKT() Convert from internal geometry format to WKT
ST_Buffer() Return geometry of points within given distance from geometry
ST_Buffer_Strategy() Produce strategy option for ST_Buffer()
ST_Centroid() Return centroid as a point
ST_Collect() Aggregate spatial values into collection 8.0.24
ST_Contains() Whether one geometry contains another
ST_ConvexHull() Return convex hull of geometry
ST_Crosses() Whether one geometry crosses another
ST_Difference() Return point set difference of two geometries
ST_Dimension() Dimension of geometry
ST_Disjoint() Whether one geometry is disjoint from another
ST_Distance() The distance of one geometry from another
ST_Distance_Sphere() Minimum distance on earth between two geometries
ST_EndPoint() End Point of LineString
ST_Envelope() Return MBR of geometry
ST_Equals() Whether one geometry is equal to another
ST_ExteriorRing() Return exterior ring of Polygon
ST_FrechetDistance() The discrete Fréchet distance of one geometry from another 8.0.23
ST_GeoHash() Produce a geohash value
ST_GeomCollFromText(), ST_GeometryCollectionFromText(), ST_GeomCollFromTxt() Return geometry collection from WKT
ST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB() Return geometry collection from WKB
ST_GeometryN() Return N-th geometry from geometry collection
ST_GeometryType() Return name of geometry type
ST_GeomFromGeoJSON() Generate geometry from GeoJSON object
ST_GeomFromText(), ST_GeometryFromText() Return geometry from WKT
ST_GeomFromWKB(), ST_GeometryFromWKB() Return geometry from WKB
ST_HausdorffDistance() The discrete Hausdorff distance of one geometry from another 8.0.23
ST_InteriorRingN() Return N-th interior ring of Polygon
ST_Intersection() Return point set intersection of two geometries
ST_Intersects() Whether one geometry intersects another
ST_IsClosed() Whether a geometry is closed and simple
ST_IsEmpty() Whether a geometry is empty
ST_IsSimple() Whether a geometry is simple
ST_IsValid() Whether a geometry is valid
ST_LatFromGeoHash() Return latitude from geohash value
ST_Latitude() Return latitude of Point 8.0.12
ST_Length() Return length of LineString
ST_LineFromText(), ST_LineStringFromText() Construct LineString from WKT
ST_LineFromWKB(), ST_LineStringFromWKB() Construct LineString from WKB
ST_LineInterpolatePoint() The point a given percentage along a LineString 8.0.24
ST_LineInterpolatePoints() The points a given percentage along a LineString 8.0.24
ST_LongFromGeoHash() Return longitude from geohash value
ST_Longitude() Return longitude of Point 8.0.12
ST_MakeEnvelope() Rectangle around two points
ST_MLineFromText(), ST_MultiLineStringFromText() Construct MultiLineString from WKT
ST_MLineFromWKB(), ST_MultiLineStringFromWKB() Construct MultiLineString from WKB
ST_MPointFromText(), ST_MultiPointFromText() Construct MultiPoint from WKT
ST_MPointFromWKB(), ST_MultiPointFromWKB() Construct MultiPoint from WKB
ST_MPolyFromText(), ST_MultiPolygonFromText() Construct MultiPolygon from WKT
ST_MPolyFromWKB(), ST_MultiPolygonFromWKB() Construct MultiPolygon from WKB
ST_NumGeometries() Return number of geometries in geometry collection
ST_NumInteriorRing(), ST_NumInteriorRings() Return number of interior rings in Polygon
ST_NumPoints() Return number of points in LineString
ST_Overlaps() Whether one geometry overlaps another
ST_PointAtDistance() The point a given distance along a LineString 8.0.24
ST_PointFromGeoHash() Convert geohash value to POINT value
ST_PointFromText() Construct Point from WKT
ST_PointFromWKB() Construct Point from WKB
ST_PointN() Return N-th point from LineString
ST_PolyFromText(), ST_PolygonFromText() Construct Polygon from WKT
ST_PolyFromWKB(), ST_PolygonFromWKB() Construct Polygon from WKB
ST_Simplify() Return simplified geometry
ST_SRID() Return spatial reference system ID for geometry
ST_StartPoint() Start Point of LineString
ST_SwapXY() Return argument with X/Y coordinates swapped
ST_SymDifference() Return point set symmetric difference of two geometries
ST_Touches() Whether one geometry touches another
ST_Transform() Transform coordinates of geometry 8.0.13
ST_Union() Return point set union of two geometries
ST_Validate() Return validated geometry
ST_Within() Whether one geometry is within another
ST_X() Return X coordinate of Point
ST_Y() Return Y coordinate of Point
STATEMENT_DIGEST() Compute statement digest hash value
STATEMENT_DIGEST_TEXT() Compute normalized statement digest
STD() Return the population standard deviation
STDDEV() Return the population standard deviation
STDDEV_POP() Return the population standard deviation
STDDEV_SAMP() Return the sample standard deviation
STR_TO_DATE() Convert a string to a date
STRCMP() Compare two strings
SUBDATE() Synonym for DATE_SUB() when invoked with three arguments
SUBSTR() Return the substring as specified
SUBSTRING() Return the substring as specified
SUBSTRING_INDEX() Return a substring from a string before the specified number of occurrences of the delimiter
SUBTIME() Subtract times
SUM() Return the sum
SYSDATE() Return the time at which the function executes
SYSTEM_USER() Synonym for USER()
TAN() Return the tangent of the argument
TIME() Extract the time portion of the expression passed
TIME_FORMAT() Format as time
TIME_TO_SEC() Return the argument converted to seconds
TIMEDIFF() Subtract time
TIMESTAMP() With a single argument, this function returns the date or datetime expression; with two arguments, the sum of the arguments
TIMESTAMPADD() Add an interval to a datetime expression
TIMESTAMPDIFF() Return the difference of two datetime expressions, using the units specified
TO_BASE64() Return the argument converted to a base-64 string
TO_DAYS() Return the date argument converted to days
TO_SECONDS() Return the date or datetime argument converted to seconds since Year 0
TRIM() Remove leading and trailing spaces
TRUNCATE() Truncate to specified number of decimal places
UCASE() Synonym for UPPER()
UNCOMPRESS() Uncompress a string compressed
UNCOMPRESSED_LENGTH() Return the length of a string before compression
UNHEX() Return a string containing hex representation of a number
UNIX_TIMESTAMP() Return a Unix timestamp
UpdateXML() Return replaced XML fragment
UPPER() Convert to uppercase
USER() The user name and host name provided by the client
UTC_DATE() Return the current UTC date
UTC_TIME() Return the current UTC time
UTC_TIMESTAMP() Return the current UTC date and time
UUID() Return a Universal Unique Identifier (UUID)
UUID_SHORT() Return an integer-valued universal identifier
UUID_TO_BIN() Convert string UUID to binary
VALIDATE_PASSWORD_STRENGTH() Determine strength of password
VALUES() Define the values to be used during an INSERT
VAR_POP() Return the population standard variance
VAR_SAMP() Return the sample variance
VARIANCE() Return the population standard variance
VERSION() Return a string that indicates the MySQL server version
WAIT_FOR_EXECUTED_GTID_SET() Wait until the given GTIDs have executed on the replica.
WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() Use WAIT_FOR_EXECUTED_GTID_SET(). 8.0.18
WEEK() Return the week number
WEEKDAY() Return the weekday index
WEEKOFYEAR() Return the calendar week of the date (1-53)
WEIGHT_STRING() Return the weight string for a string
XOR Logical XOR
YEAR() Return the year
YEARWEEK() Return the year and week
1 Name Description Introduced Deprecated
2 ABS() Return the absolute value
3 ACOS() Return the arc cosine
4 ADDDATE() Add time values (intervals) to a date value
5 ADDTIME() Add time
6 AES_DECRYPT() Decrypt using AES
7 AES_ENCRYPT() Encrypt using AES
8 AND, && Logical AND
9 ANY_VALUE() Suppress ONLY_FULL_GROUP_BY value rejection
10 ASCII() Return numeric value of left-most character
11 ASIN() Return the arc sine
12 asynchronous_connection_failover_add_managed() Add group member source server configuration information to a replication channel source list 8.0.23
13 asynchronous_connection_failover_add_source() Add source server configuration information server to a replication channel source list 8.0.22
14 asynchronous_connection_failover_delete_managed() Remove a managed group from a replication channel source list 8.0.23
15 asynchronous_connection_failover_delete_source() Remove a source server from a replication channel source list 8.0.22
16 asynchronous_connection_failover_reset() Remove all settings relating to group replication asynchronous failover 8.0.27
17 ATAN() Return the arc tangent
18 ATAN2(), ATAN() Return the arc tangent of the two arguments
19 AVG() Return the average value of the argument
20 BENCHMARK() Repeatedly execute an expression
21 BETWEEN ... AND ... Whether a value is within a range of values
22 BIN() Return a string containing binary representation of a number
23 BIN_TO_UUID() Convert binary UUID to string
24 BINARY Cast a string to a binary string 8.0.27
25 BIT_AND() Return bitwise AND
26 BIT_COUNT() Return the number of bits that are set
27 BIT_LENGTH() Return length of argument in bits
28 BIT_OR() Return bitwise OR
29 BIT_XOR() Return bitwise XOR
30 CAN_ACCESS_COLUMN() Internal use only
31 CAN_ACCESS_DATABASE() Internal use only
32 CAN_ACCESS_TABLE() Internal use only
33 CAN_ACCESS_USER() Internal use only 8.0.22
34 CAN_ACCESS_VIEW() Internal use only
35 CASE Case operator
36 CAST() Cast a value as a certain type
37 CEIL() Return the smallest integer value not less than the argument
38 CEILING() Return the smallest integer value not less than the argument
39 CHAR() Return the character for each integer passed
40 CHAR_LENGTH() Return number of characters in argument
41 CHARACTER_LENGTH() Synonym for CHAR_LENGTH()
42 CHARSET() Return the character set of the argument
43 COALESCE() Return the first non-NULL argument
44 COERCIBILITY() Return the collation coercibility value of the string argument
45 COLLATION() Return the collation of the string argument
46 COMPRESS() Return result as a binary string
47 CONCAT() Return concatenated string
48 CONCAT_WS() Return concatenate with separator
49 CONNECTION_ID() Return the connection ID (thread ID) for the connection
50 CONV() Convert numbers between different number bases
51 CONVERT() Cast a value as a certain type
52 CONVERT_TZ() Convert from one time zone to another
53 COS() Return the cosine
54 COT() Return the cotangent
55 COUNT() Return a count of the number of rows returned
56 COUNT(DISTINCT) Return the count of a number of different values
57 CRC32() Compute a cyclic redundancy check value
58 CUME_DIST() Cumulative distribution value
59 CURDATE() Return the current date
60 CURRENT_DATE(), CURRENT_DATE Synonyms for CURDATE()
61 CURRENT_ROLE() Return the current active roles
62 CURRENT_TIME(), CURRENT_TIME Synonyms for CURTIME()
63 CURRENT_TIMESTAMP(), CURRENT_TIMESTAMP Synonyms for NOW()
64 CURRENT_USER(), CURRENT_USER The authenticated user name and host name
65 CURTIME() Return the current time
66 DATABASE() Return the default (current) database name
67 DATE() Extract the date part of a date or datetime expression
68 DATE_ADD() Add time values (intervals) to a date value
69 DATE_FORMAT() Format date as specified
70 DATE_SUB() Subtract a time value (interval) from a date
71 DATEDIFF() Subtract two dates
72 DAY() Synonym for DAYOFMONTH()
73 DAYNAME() Return the name of the weekday
74 DAYOFMONTH() Return the day of the month (0-31)
75 DAYOFWEEK() Return the weekday index of the argument
76 DAYOFYEAR() Return the day of the year (1-366)
77 DEFAULT() Return the default value for a table column
78 DEGREES() Convert radians to degrees
79 DENSE_RANK() Rank of current row within its partition, without gaps
80 DIV Integer division
81 ELT() Return string at index number
82 EXP() Raise to the power of
83 EXPORT_SET() Return a string such that for every bit set in the value bits, you get an on string and for every unset bit, you get an off string
84 EXTRACT() Extract part of a date
85 ExtractValue() Extract a value from an XML string using XPath notation
86 FIELD() Index (position) of first argument in subsequent arguments
87 FIND_IN_SET() Index (position) of first argument within second argument
88 FIRST_VALUE() Value of argument from first row of window frame
89 FLOOR() Return the largest integer value not greater than the argument
90 FORMAT() Return a number formatted to specified number of decimal places
91 FORMAT_BYTES() Convert byte count to value with units 8.0.16
92 FORMAT_PICO_TIME() Convert time in picoseconds to value with units 8.0.16
93 FOUND_ROWS() For a SELECT with a LIMIT clause, the number of rows that would be returned were there no LIMIT clause
94 FROM_BASE64() Decode base64 encoded string and return result
95 FROM_DAYS() Convert a day number to a date
96 FROM_UNIXTIME() Format Unix timestamp as a date
97 GeomCollection() Construct geometry collection from geometries
98 GeometryCollection() Construct geometry collection from geometries
99 GET_DD_COLUMN_PRIVILEGES() Internal use only
100 GET_DD_CREATE_OPTIONS() Internal use only
101 GET_DD_INDEX_SUB_PART_LENGTH() Internal use only
102 GET_FORMAT() Return a date format string
103 GET_LOCK() Get a named lock
104 GREATEST() Return the largest argument
105 GROUP_CONCAT() Return a concatenated string
106 group_replication_disable_member_action() Disable member action for event specified 8.0.26
107 group_replication_enable_member_action() Enable member action for event specified 8.0.26
108 group_replication_get_communication_protocol() Get version of group replication communication protocol currently in use 8.0.16
109 group_replication_get_write_concurrency() Get maximum number of consensus instances currently set for group 8.0.13
110 group_replication_reset_member_actions() Reset all member actions to defaults and configuration version number to 1 8.0.26
111 group_replication_set_as_primary() Make a specific group member the primary 8.0.29
112 group_replication_set_communication_protocol() Set version for group replication communication protocol to use 8.0.16
113 group_replication_set_write_concurrency() Set maximum number of consensus instances that can be executed in parallel 8.0.13
114 group_replication_switch_to_multi_primary_mode() Changes the mode of a group running in single-primary mode to multi-primary mode 8.0.13
115 group_replication_switch_to_single_primary_mode() Changes the mode of a group running in multi-primary mode to single-primary mode 8.0.13
116 GROUPING() Distinguish super-aggregate ROLLUP rows from regular rows
117 GTID_SUBSET() Return true if all GTIDs in subset are also in set; otherwise false.
118 GTID_SUBTRACT() Return all GTIDs in set that are not in subset.
119 HEX() Hexadecimal representation of decimal or string value
120 HOUR() Extract the hour
121 ICU_VERSION() ICU library version
122 IF() If/else construct
123 IFNULL() Null if/else construct
124 IN() Whether a value is within a set of values
125 INET_ATON() Return the numeric value of an IP address
126 INET_NTOA() Return the IP address from a numeric value
127 INET6_ATON() Return the numeric value of an IPv6 address
128 INET6_NTOA() Return the IPv6 address from a numeric value
129 INSERT() Insert substring at specified position up to specified number of characters
130 INSTR() Return the index of the first occurrence of substring
131 INTERNAL_AUTO_INCREMENT() Internal use only
132 INTERNAL_AVG_ROW_LENGTH() Internal use only
133 INTERNAL_CHECK_TIME() Internal use only
134 INTERNAL_CHECKSUM() Internal use only
135 INTERNAL_DATA_FREE() Internal use only
136 INTERNAL_DATA_LENGTH() Internal use only
137 INTERNAL_DD_CHAR_LENGTH() Internal use only
138 INTERNAL_GET_COMMENT_OR_ERROR() Internal use only
139 INTERNAL_GET_ENABLED_ROLE_JSON() Internal use only 8.0.19
140 INTERNAL_GET_HOSTNAME() Internal use only 8.0.19
141 INTERNAL_GET_USERNAME() Internal use only 8.0.19
142 INTERNAL_GET_VIEW_WARNING_OR_ERROR() Internal use only
143 INTERNAL_INDEX_COLUMN_CARDINALITY() Internal use only
144 INTERNAL_INDEX_LENGTH() Internal use only
145 INTERNAL_IS_ENABLED_ROLE() Internal use only 8.0.19
146 INTERNAL_IS_MANDATORY_ROLE() Internal use only 8.0.19
147 INTERNAL_KEYS_DISABLED() Internal use only
148 INTERNAL_MAX_DATA_LENGTH() Internal use only
149 INTERNAL_TABLE_ROWS() Internal use only
150 INTERNAL_UPDATE_TIME() Internal use only
151 INTERVAL() Return the index of the argument that is less than the first argument
152 IS Test a value against a boolean
153 IS_FREE_LOCK() Whether the named lock is free
154 IS_IPV4() Whether argument is an IPv4 address
155 IS_IPV4_COMPAT() Whether argument is an IPv4-compatible address
156 IS_IPV4_MAPPED() Whether argument is an IPv4-mapped address
157 IS_IPV6() Whether argument is an IPv6 address
158 IS NOT Test a value against a boolean
159 IS NOT NULL NOT NULL value test
160 IS NULL NULL value test
161 IS_USED_LOCK() Whether the named lock is in use; return connection identifier if true
162 IS_UUID() Whether argument is a valid UUID
163 ISNULL() Test whether the argument is NULL
164 JSON_ARRAY() Create JSON array
165 JSON_ARRAY_APPEND() Append data to JSON document
166 JSON_ARRAY_INSERT() Insert into JSON array
167 JSON_ARRAYAGG() Return result set as a single JSON array
168 JSON_CONTAINS() Whether JSON document contains specific object at path
169 JSON_CONTAINS_PATH() Whether JSON document contains any data at path
170 JSON_DEPTH() Maximum depth of JSON document
171 JSON_EXTRACT() Return data from JSON document
172 JSON_INSERT() Insert data into JSON document
173 JSON_KEYS() Array of keys from JSON document
174 JSON_LENGTH() Number of elements in JSON document
175 JSON_MERGE() Merge JSON documents, preserving duplicate keys. Deprecated synonym for JSON_MERGE_PRESERVE() Yes
176 JSON_MERGE_PATCH() Merge JSON documents, replacing values of duplicate keys
177 JSON_MERGE_PRESERVE() Merge JSON documents, preserving duplicate keys
178 JSON_OBJECT() Create JSON object
179 JSON_OBJECTAGG() Return result set as a single JSON object
180 JSON_OVERLAPS() Compares two JSON documents, returns TRUE (1) if these have any key-value pairs or array elements in common, otherwise FALSE (0) 8.0.17
181 JSON_PRETTY() Print a JSON document in human-readable format
182 JSON_QUOTE() Quote JSON document
183 JSON_REMOVE() Remove data from JSON document
184 JSON_REPLACE() Replace values in JSON document
185 JSON_SCHEMA_VALID() Validate JSON document against JSON schema; returns TRUE/1 if document validates against schema, or FALSE/0 if it does not 8.0.17
186 JSON_SCHEMA_VALIDATION_REPORT() Validate JSON document against JSON schema; returns report in JSON format on outcome on validation including success or failure and reasons for failure 8.0.17
187 JSON_SEARCH() Path to value within JSON document
188 JSON_SET() Insert data into JSON document
189 JSON_STORAGE_FREE() Freed space within binary representation of JSON column value following partial update
190 JSON_STORAGE_SIZE() Space used for storage of binary representation of a JSON document
191 JSON_TABLE() Return data from a JSON expression as a relational table
192 JSON_TYPE() Type of JSON value
193 JSON_UNQUOTE() Unquote JSON value
194 JSON_VALID() Whether JSON value is valid
195 JSON_VALUE() Extract value from JSON document at location pointed to by path provided; return this value as VARCHAR(512) or specified type 8.0.21
196 LAG() Value of argument from row lagging current row within partition
197 LAST_DAY Return the last day of the month for the argument
198 LAST_INSERT_ID() Value of the AUTOINCREMENT column for the last INSERT
199 LAST_VALUE() Value of argument from last row of window frame
200 LCASE() Synonym for LOWER()
201 LEAD() Value of argument from row leading current row within partition
202 LEAST() Return the smallest argument
203 LEFT() Return the leftmost number of characters as specified
204 LENGTH() Return the length of a string in bytes
205 LIKE Simple pattern matching
206 LineString() Construct LineString from Point values
207 LN() Return the natural logarithm of the argument
208 LOAD_FILE() Load the named file
209 LOCALTIME(), LOCALTIME Synonym for NOW()
210 LOCALTIMESTAMP, LOCALTIMESTAMP() Synonym for NOW()
211 LOCATE() Return the position of the first occurrence of substring
212 LOG() Return the natural logarithm of the first argument
213 LOG10() Return the base-10 logarithm of the argument
214 LOG2() Return the base-2 logarithm of the argument
215 LOWER() Return the argument in lowercase
216 LPAD() Return the string argument, left-padded with the specified string
217 LTRIM() Remove leading spaces
218 MAKE_SET() Return a set of comma-separated strings that have the corresponding bit in bits set
219 MAKEDATE() Create a date from the year and day of year
220 MAKETIME() Create time from hour, minute, second
221 MASTER_POS_WAIT() Block until the replica has read and applied all updates up to the specified position 8.0.26
222 MATCH() Perform full-text search
223 MAX() Return the maximum value
224 MBRContains() Whether MBR of one geometry contains MBR of another
225 MBRCoveredBy() Whether one MBR is covered by another
226 MBRCovers() Whether one MBR covers another
227 MBRDisjoint() Whether MBRs of two geometries are disjoint
228 MBREquals() Whether MBRs of two geometries are equal
229 MBRIntersects() Whether MBRs of two geometries intersect
230 MBROverlaps() Whether MBRs of two geometries overlap
231 MBRTouches() Whether MBRs of two geometries touch
232 MBRWithin() Whether MBR of one geometry is within MBR of another
233 MD5() Calculate MD5 checksum
234 MEMBER OF() Returns true (1) if first operand matches any element of JSON array passed as second operand, otherwise returns false (0) 8.0.17
235 MICROSECOND() Return the microseconds from argument
236 MID() Return a substring starting from the specified position
237 MIN() Return the minimum value
238 MINUTE() Return the minute from the argument
239 MOD() Return the remainder
240 MONTH() Return the month from the date passed
241 MONTHNAME() Return the name of the month
242 MultiLineString() Contruct MultiLineString from LineString values
243 MultiPoint() Construct MultiPoint from Point values
244 MultiPolygon() Construct MultiPolygon from Polygon values
245 NAME_CONST() Cause the column to have the given name
246 NOT, ! Negates value
247 NOT BETWEEN ... AND ... Whether a value is not within a range of values
248 NOT IN() Whether a value is not within a set of values
249 NOT LIKE Negation of simple pattern matching
250 NOT REGEXP Negation of REGEXP
251 NOW() Return the current date and time
252 NTH_VALUE() Value of argument from N-th row of window frame
253 NTILE() Bucket number of current row within its partition.
254 NULLIF() Return NULL if expr1 = expr2
255 OCT() Return a string containing octal representation of a number
256 OCTET_LENGTH() Synonym for LENGTH()
257 OR, || Logical OR
258 ORD() Return character code for leftmost character of the argument
259 PERCENT_RANK() Percentage rank value
260 PERIOD_ADD() Add a period to a year-month
261 PERIOD_DIFF() Return the number of months between periods
262 PI() Return the value of pi
263 Point() Construct Point from coordinates
264 Polygon() Construct Polygon from LineString arguments
265 POSITION() Synonym for LOCATE()
266 POW() Return the argument raised to the specified power
267 POWER() Return the argument raised to the specified power
268 PS_CURRENT_THREAD_ID() Performance Schema thread ID for current thread 8.0.16
269 PS_THREAD_ID() Performance Schema thread ID for given thread 8.0.16
270 QUARTER() Return the quarter from a date argument
271 QUOTE() Escape the argument for use in an SQL statement
272 RADIANS() Return argument converted to radians
273 RAND() Return a random floating-point value
274 RANDOM_BYTES() Return a random byte vector
275 RANK() Rank of current row within its partition, with gaps
276 REGEXP Whether string matches regular expression
277 REGEXP_INSTR() Starting index of substring matching regular expression
278 REGEXP_LIKE() Whether string matches regular expression
279 REGEXP_REPLACE() Replace substrings matching regular expression
280 REGEXP_SUBSTR() Return substring matching regular expression
281 RELEASE_ALL_LOCKS() Release all current named locks
282 RELEASE_LOCK() Release the named lock
283 REPEAT() Repeat a string the specified number of times
284 REPLACE() Replace occurrences of a specified string
285 REVERSE() Reverse the characters in a string
286 RIGHT() Return the specified rightmost number of characters
287 RLIKE Whether string matches regular expression
288 ROLES_GRAPHML() Return a GraphML document representing memory role subgraphs
289 ROUND() Round the argument
290 ROW_COUNT() The number of rows updated
291 ROW_NUMBER() Number of current row within its partition
292 RPAD() Append string the specified number of times
293 RTRIM() Remove trailing spaces
294 SCHEMA() Synonym for DATABASE()
295 SEC_TO_TIME() Converts seconds to 'hh:mm:ss' format
296 SECOND() Return the second (0-59)
297 SESSION_USER() Synonym for USER()
298 SHA1(), SHA() Calculate an SHA-1 160-bit checksum
299 SHA2() Calculate an SHA-2 checksum
300 SIGN() Return the sign of the argument
301 SIN() Return the sine of the argument
302 SLEEP() Sleep for a number of seconds
303 SOUNDEX() Return a soundex string
304 SOUNDS LIKE Compare sounds
305 SOURCE_POS_WAIT() Block until the replica has read and applied all updates up to the specified position 8.0.26
306 SPACE() Return a string of the specified number of spaces
307 SQRT() Return the square root of the argument
308 ST_Area() Return Polygon or MultiPolygon area
309 ST_AsBinary(), ST_AsWKB() Convert from internal geometry format to WKB
310 ST_AsGeoJSON() Generate GeoJSON object from geometry
311 ST_AsText(), ST_AsWKT() Convert from internal geometry format to WKT
312 ST_Buffer() Return geometry of points within given distance from geometry
313 ST_Buffer_Strategy() Produce strategy option for ST_Buffer()
314 ST_Centroid() Return centroid as a point
315 ST_Collect() Aggregate spatial values into collection 8.0.24
316 ST_Contains() Whether one geometry contains another
317 ST_ConvexHull() Return convex hull of geometry
318 ST_Crosses() Whether one geometry crosses another
319 ST_Difference() Return point set difference of two geometries
320 ST_Dimension() Dimension of geometry
321 ST_Disjoint() Whether one geometry is disjoint from another
322 ST_Distance() The distance of one geometry from another
323 ST_Distance_Sphere() Minimum distance on earth between two geometries
324 ST_EndPoint() End Point of LineString
325 ST_Envelope() Return MBR of geometry
326 ST_Equals() Whether one geometry is equal to another
327 ST_ExteriorRing() Return exterior ring of Polygon
328 ST_FrechetDistance() The discrete Fréchet distance of one geometry from another 8.0.23
329 ST_GeoHash() Produce a geohash value
330 ST_GeomCollFromText(), ST_GeometryCollectionFromText(), ST_GeomCollFromTxt() Return geometry collection from WKT
331 ST_GeomCollFromWKB(), ST_GeometryCollectionFromWKB() Return geometry collection from WKB
332 ST_GeometryN() Return N-th geometry from geometry collection
333 ST_GeometryType() Return name of geometry type
334 ST_GeomFromGeoJSON() Generate geometry from GeoJSON object
335 ST_GeomFromText(), ST_GeometryFromText() Return geometry from WKT
336 ST_GeomFromWKB(), ST_GeometryFromWKB() Return geometry from WKB
337 ST_HausdorffDistance() The discrete Hausdorff distance of one geometry from another 8.0.23
338 ST_InteriorRingN() Return N-th interior ring of Polygon
339 ST_Intersection() Return point set intersection of two geometries
340 ST_Intersects() Whether one geometry intersects another
341 ST_IsClosed() Whether a geometry is closed and simple
342 ST_IsEmpty() Whether a geometry is empty
343 ST_IsSimple() Whether a geometry is simple
344 ST_IsValid() Whether a geometry is valid
345 ST_LatFromGeoHash() Return latitude from geohash value
346 ST_Latitude() Return latitude of Point 8.0.12
347 ST_Length() Return length of LineString
348 ST_LineFromText(), ST_LineStringFromText() Construct LineString from WKT
349 ST_LineFromWKB(), ST_LineStringFromWKB() Construct LineString from WKB
350 ST_LineInterpolatePoint() The point a given percentage along a LineString 8.0.24
351 ST_LineInterpolatePoints() The points a given percentage along a LineString 8.0.24
352 ST_LongFromGeoHash() Return longitude from geohash value
353 ST_Longitude() Return longitude of Point 8.0.12
354 ST_MakeEnvelope() Rectangle around two points
355 ST_MLineFromText(), ST_MultiLineStringFromText() Construct MultiLineString from WKT
356 ST_MLineFromWKB(), ST_MultiLineStringFromWKB() Construct MultiLineString from WKB
357 ST_MPointFromText(), ST_MultiPointFromText() Construct MultiPoint from WKT
358 ST_MPointFromWKB(), ST_MultiPointFromWKB() Construct MultiPoint from WKB
359 ST_MPolyFromText(), ST_MultiPolygonFromText() Construct MultiPolygon from WKT
360 ST_MPolyFromWKB(), ST_MultiPolygonFromWKB() Construct MultiPolygon from WKB
361 ST_NumGeometries() Return number of geometries in geometry collection
362 ST_NumInteriorRing(), ST_NumInteriorRings() Return number of interior rings in Polygon
363 ST_NumPoints() Return number of points in LineString
364 ST_Overlaps() Whether one geometry overlaps another
365 ST_PointAtDistance() The point a given distance along a LineString 8.0.24
366 ST_PointFromGeoHash() Convert geohash value to POINT value
367 ST_PointFromText() Construct Point from WKT
368 ST_PointFromWKB() Construct Point from WKB
369 ST_PointN() Return N-th point from LineString
370 ST_PolyFromText(), ST_PolygonFromText() Construct Polygon from WKT
371 ST_PolyFromWKB(), ST_PolygonFromWKB() Construct Polygon from WKB
372 ST_Simplify() Return simplified geometry
373 ST_SRID() Return spatial reference system ID for geometry
374 ST_StartPoint() Start Point of LineString
375 ST_SwapXY() Return argument with X/Y coordinates swapped
376 ST_SymDifference() Return point set symmetric difference of two geometries
377 ST_Touches() Whether one geometry touches another
378 ST_Transform() Transform coordinates of geometry 8.0.13
379 ST_Union() Return point set union of two geometries
380 ST_Validate() Return validated geometry
381 ST_Within() Whether one geometry is within another
382 ST_X() Return X coordinate of Point
383 ST_Y() Return Y coordinate of Point
384 STATEMENT_DIGEST() Compute statement digest hash value
385 STATEMENT_DIGEST_TEXT() Compute normalized statement digest
386 STD() Return the population standard deviation
387 STDDEV() Return the population standard deviation
388 STDDEV_POP() Return the population standard deviation
389 STDDEV_SAMP() Return the sample standard deviation
390 STR_TO_DATE() Convert a string to a date
391 STRCMP() Compare two strings
392 SUBDATE() Synonym for DATE_SUB() when invoked with three arguments
393 SUBSTR() Return the substring as specified
394 SUBSTRING() Return the substring as specified
395 SUBSTRING_INDEX() Return a substring from a string before the specified number of occurrences of the delimiter
396 SUBTIME() Subtract times
397 SUM() Return the sum
398 SYSDATE() Return the time at which the function executes
399 SYSTEM_USER() Synonym for USER()
400 TAN() Return the tangent of the argument
401 TIME() Extract the time portion of the expression passed
402 TIME_FORMAT() Format as time
403 TIME_TO_SEC() Return the argument converted to seconds
404 TIMEDIFF() Subtract time
405 TIMESTAMP() With a single argument, this function returns the date or datetime expression; with two arguments, the sum of the arguments
406 TIMESTAMPADD() Add an interval to a datetime expression
407 TIMESTAMPDIFF() Return the difference of two datetime expressions, using the units specified
408 TO_BASE64() Return the argument converted to a base-64 string
409 TO_DAYS() Return the date argument converted to days
410 TO_SECONDS() Return the date or datetime argument converted to seconds since Year 0
411 TRIM() Remove leading and trailing spaces
412 TRUNCATE() Truncate to specified number of decimal places
413 UCASE() Synonym for UPPER()
414 UNCOMPRESS() Uncompress a string compressed
415 UNCOMPRESSED_LENGTH() Return the length of a string before compression
416 UNHEX() Return a string containing hex representation of a number
417 UNIX_TIMESTAMP() Return a Unix timestamp
418 UpdateXML() Return replaced XML fragment
419 UPPER() Convert to uppercase
420 USER() The user name and host name provided by the client
421 UTC_DATE() Return the current UTC date
422 UTC_TIME() Return the current UTC time
423 UTC_TIMESTAMP() Return the current UTC date and time
424 UUID() Return a Universal Unique Identifier (UUID)
425 UUID_SHORT() Return an integer-valued universal identifier
426 UUID_TO_BIN() Convert string UUID to binary
427 VALIDATE_PASSWORD_STRENGTH() Determine strength of password
428 VALUES() Define the values to be used during an INSERT
429 VAR_POP() Return the population standard variance
430 VAR_SAMP() Return the sample variance
431 VARIANCE() Return the population standard variance
432 VERSION() Return a string that indicates the MySQL server version
433 WAIT_FOR_EXECUTED_GTID_SET() Wait until the given GTIDs have executed on the replica.
434 WAIT_UNTIL_SQL_THREAD_AFTER_GTIDS() Use WAIT_FOR_EXECUTED_GTID_SET(). 8.0.18
435 WEEK() Return the week number
436 WEEKDAY() Return the weekday index
437 WEEKOFYEAR() Return the calendar week of the date (1-53)
438 WEIGHT_STRING() Return the weight string for a string
439 XOR Logical XOR
440 YEAR() Return the year
441 YEARWEEK() Return the year and week

View file

@ -0,0 +1,113 @@
from __future__ import annotations
from textwrap import dedent
from typing import TYPE_CHECKING, Literal, Sequence
from harlequin.catalog import CatalogItem
from harlequin.exception import HarlequinQueryError
if TYPE_CHECKING:
from harlequin.driver import HarlequinDriver
from harlequin_mysql.catalog import (
ColumnCatalogItem,
DatabaseCatalogItem,
RelationCatalogItem,
)
def execute_use_statement(
item: "DatabaseCatalogItem",
driver: "HarlequinDriver",
) -> None:
if item.connection is None:
return
try:
item.connection.execute(f"use {item.label}")
except HarlequinQueryError:
driver.notify("Could not switch context", severity="error")
raise
else:
driver.notify(f"Editor context switched to {item.label}")
def execute_drop_database_statement(
item: "DatabaseCatalogItem",
driver: "HarlequinDriver",
) -> None:
def _drop_database() -> None:
if item.connection is None:
return
try:
item.connection.execute(f"drop database {item.qualified_identifier}")
except HarlequinQueryError:
driver.notify(f"Could not drop database {item.label}", severity="error")
raise
else:
driver.notify(f"Dropped database {item.label}")
driver.refresh_catalog()
if item.children or item.fetch_children():
driver.confirm_and_execute(callback=_drop_database)
else:
_drop_database()
def execute_drop_relation_statement(
item: "RelationCatalogItem",
driver: "HarlequinDriver",
relation_type: Literal["view", "table", "foreign table"],
) -> None:
def _drop_relation() -> None:
if item.connection is None:
return
try:
item.connection.execute(f"drop {relation_type} {item.qualified_identifier}")
except HarlequinQueryError:
driver.notify(
f"Could not drop {relation_type} {item.label}", severity="error"
)
raise
else:
driver.notify(f"Dropped {relation_type} {item.label}")
driver.refresh_catalog()
driver.confirm_and_execute(callback=_drop_relation)
def execute_drop_table_statement(
item: "RelationCatalogItem", driver: "HarlequinDriver"
) -> None:
execute_drop_relation_statement(item=item, driver=driver, relation_type="table")
def execute_drop_view_statement(
item: "RelationCatalogItem", driver: "HarlequinDriver"
) -> None:
execute_drop_relation_statement(item=item, driver=driver, relation_type="view")
def show_select_star(
item: "RelationCatalogItem",
driver: "HarlequinDriver",
) -> None:
driver.insert_text_in_new_buffer(
dedent(
f"""
select *
from {item.qualified_identifier}
limit 100
""".strip("\n")
)
)
def insert_columns_at_cursor(
item: "RelationCatalogItem",
driver: "HarlequinDriver",
) -> None:
if item.loaded:
cols: Sequence["CatalogItem" | "ColumnCatalogItem"] = item.children
else:
cols = item.fetch_children()
driver.insert_text_at_selection(text=",\n".join(c.query_name for c in cols))

View file

@ -0,0 +1,892 @@
ACCESSIBLE,False,False
ACCOUNT,False,False
ACTION,False,False
ACTIVE,False,False
ADD,False,False
ADMIN,False,False
AFTER,False,False
AGAINST,False,False
AGGREGATE,False,False
ALGORITHM,False,False
ALL,False,False
ALTER,False,False
ALWAYS,False,False
ANALYSE,False,True
ANALYZE,False,False
AND,False,False
ANY,False,False
ARRAY,False,False
AS,False,False
ASC,False,False
ASCII,False,False
ASENSITIVE,False,False
AT,False,False
ATTRIBUTE,False,False
AUTHENTICATION,False,False
AUTOEXTEND_SIZE,False,False
AUTO_INCREMENT,False,False
AVG,False,False
AVG_ROW_LENGTH,False,False
BACKUP,False,False
BEFORE,False,False
BEGIN,False,False
BETWEEN,False,False
BIGINT,False,False
BINARY,False,False
BINLOG,False,False
BIT,False,False
BLOB,False,False
BLOCK,False,False
BOOL,False,False
BOOLEAN,False,False
BOTH,False,False
BTREE,False,False
BUCKETS,False,False
BULK,False,False
BY,False,False
BYTE,False,False
CACHE,False,False
CALL,False,False
CASCADE,False,False
CASCADED,False,False
CASE,False,False
CATALOG_NAME,False,False
CHAIN,False,False
CHALLENGE_RESPONSE,False,False
CHANGE,False,False
CHANGED,False,False
CHANNEL,False,False
CHAR,False,False
CHARACTER,False,False
CHARSET,False,False
CHECK,False,False
CHECKSUM,False,False
CIPHER,False,False
CLASS_ORIGIN,False,False
CLIENT,False,False
CLONE,False,False
CLOSE,False,False
COALESCE,False,False
CODE,False,False
COLLATE,False,False
COLLATION,False,False
COLUMN,False,False
COLUMNS,False,False
COLUMN_FORMAT,False,False
COLUMN_NAME,False,False
COMMENT,False,False
COMMIT,False,False
COMMITTED,False,False
COMPACT,False,False
COMPLETION,False,False
COMPONENT,False,False
COMPRESSED,False,False
COMPRESSION,False,False
CONCURRENT,False,False
CONDITION,False,False
CONNECTION,False,False
CONSISTENT,False,False
CONSTRAINT,False,False
CONSTRAINT_CATALOG,False,False
CONSTRAINT_NAME,False,False
CONSTRAINT_SCHEMA,False,False
CONTAINS,False,False
CONTEXT,False,False
CONTINUE,False,False
CONVERT,False,False
CPU,False,False
CREATE,False,False
CROSS,False,False
CUBE,False,False
CUME_DIST,False,False
CURRENT,False,False
CURRENT_DATE,False,False
CURRENT_TIME,False,False
CURRENT_TIMESTAMP,False,False
CURRENT_USER,False,False
CURSOR,False,False
CURSOR_NAME,False,False
DATA,False,False
DATABASE,False,False
DATABASES,False,False
DATAFILE,False,False
DATE,False,False
DATETIME,False,False
DAY,False,False
DAY_HOUR,False,False
DAY_MICROSECOND,False,False
DAY_MINUTE,False,False
DAY_SECOND,False,False
DEALLOCATE,False,False
DEC,False,False
DECIMAL,False,False
DECLARE,False,False
DEFAULT,False,False
DEFAULT_AUTH,False,False
DEFINER,False,False
DEFINITION,False,False
DELAYED,False,False
DELAY_KEY_WRITE,False,False
DELETE,False,False
DENSE_RANK,False,False
DESC,False,False
DESCRIBE,False,False
DESCRIPTION,False,False
DES_KEY_FILE,False,True
DETERMINISTIC,False,False
DIAGNOSTICS,False,False
DIRECTORY,False,False
DISABLE,False,False
DISCARD,False,False
DISK,False,False
DISTINCT,False,False
DISTINCTROW,False,False
DIV,False,False
DO,False,False
DOUBLE,False,False
DROP,False,False
DUAL,False,False
DUMPFILE,False,False
DUPLICATE,False,False
DYNAMIC,False,False
EACH,False,False
ELSE,False,False
ELSEIF,False,False
EMPTY,False,False
ENABLE,False,False
ENCLOSED,False,False
ENCRYPTION,False,False
END,False,False
ENDS,False,False
ENFORCED,False,False
ENGINE,False,False
ENGINES,False,False
ENGINE_ATTRIBUTE,False,False
ENUM,False,False
ERROR,False,False
ERRORS,False,False
ESCAPE,False,False
ESCAPED,False,False
EVENT,False,False
EVENTS,False,False
EVERY,False,False
EXCEPT,False,False
EXCHANGE,False,False
EXCLUDE,False,False
EXECUTE,False,False
EXISTS,False,False
EXIT,False,False
EXPANSION,False,False
EXPIRE,False,False
EXPLAIN,False,False
EXPORT,False,False
EXTENDED,False,False
EXTENT_SIZE,False,False
FACTOR,False,False
FAILED_LOGIN_ATTEMPTS,False,False
FALSE,False,False
FAST,False,False
FAULTS,False,False
FETCH,False,False
FIELDS,False,False
FILE,False,False
FILE_BLOCK_SIZE,False,False
FILTER,False,False
FINISH,False,False
FIRST,False,False
FIRST_VALUE,False,False
FIXED,False,False
FLOAT,False,False
FLOAT4,False,False
FLOAT8,False,False
FLUSH,False,False
FOLLOWING,False,False
FOLLOWS,False,False
FOR,False,False
FORCE,False,False
FOREIGN,False,False
FORMAT,False,False
FOUND,False,False
FROM,False,False
FULL,False,False
FULLTEXT,False,False
FUNCTION,False,False
GENERAL,False,False
GENERATE,False,False
GENERATED,False,False
GEOMCOLLECTION,False,False
GEOMETRY,False,False
GEOMETRYCOLLECTION,False,False
GET,False,False
GET_FORMAT,False,False
GET_MASTER_PUBLIC_KEY,False,False
GET_SOURCE_PUBLIC_KEY,False,False
GLOBAL,False,False
GRANT,False,False
GRANTS,False,False
GROUP,False,False
GROUPING,False,False
GROUPS,False,False
GROUP_REPLICATION,False,False
GTID_ONLY,False,False
HANDLER,False,False
HASH,False,False
HAVING,False,False
HELP,False,False
HIGH_PRIORITY,False,False
HISTOGRAM,False,False
HISTORY,False,False
HOST,False,False
HOSTS,False,False
HOUR,False,False
HOUR_MICROSECOND,False,False
HOUR_MINUTE,False,False
HOUR_SECOND,False,False
IDENTIFIED,False,False
IF,False,False
IGNORE,False,False
IGNORE_SERVER_IDS,False,False
IMPORT,False,False
IN,False,False
INACTIVE,False,False
INDEX,False,False
INDEXES,False,False
INFILE,False,False
INITIAL,False,False
INITIAL_SIZE,False,False
INITIATE,False,False
INNER,False,False
INOUT,False,False
INSENSITIVE,False,False
INSERT,False,False
INSERT_METHOD,False,False
INSTALL,False,False
INSTANCE,False,False
INT,False,False
INT1,False,False
INT2,False,False
INT3,False,False
INT4,False,False
INT8,False,False
INTEGER,False,False
INTERSECT,False,False
INTERVAL,False,False
INTO,False,False
INVISIBLE,False,False
INVOKER,False,False
IO,False,False
IO_AFTER_GTIDS,False,False
IO_BEFORE_GTIDS,False,False
IO_THREAD,False,False
IPC,False,False
IS,False,False
ISOLATION,False,False
ISSUER,False,False
ITERATE,False,False
JOIN,False,False
JSON,False,False
JSON_TABLE,False,False
JSON_VALUE,False,False
KEY,False,False
KEYRING,False,False
KEYS,False,False
KEY_BLOCK_SIZE,False,False
KILL,False,False
LAG,False,False
LANGUAGE,False,False
LAST,False,False
LAST_VALUE,False,False
LATERAL,False,False
LEAD,False,False
LEADING,False,False
LEAVE,False,False
LEAVES,False,False
LEFT,False,False
LESS,False,False
LEVEL,False,False
LIKE,False,False
LIMIT,False,False
LINEAR,False,False
LINES,False,False
LINESTRING,False,False
LIST,False,False
LOAD,False,False
LOCAL,False,False
LOCALTIME,False,False
LOCALTIMESTAMP,False,False
LOCK,False,False
LOCKED,False,False
LOCKS,False,False
LOGFILE,False,False
LOGS,False,False
LONG,False,False
LONGBLOB,False,False
LONGTEXT,False,False
LOOP,False,False
LOW_PRIORITY,False,False
MASTER,False,False
MASTER_AUTO_POSITION,False,False
MASTER_BIND,False,False
MASTER_COMPRESSION_ALGORITHMS,False,False
MASTER_CONNECT_RETRY,False,False
MASTER_DELAY,False,False
MASTER_HEARTBEAT_PERIOD,False,False
MASTER_HOST,False,False
MASTER_LOG_FILE,False,False
MASTER_LOG_POS,False,False
MASTER_PASSWORD,False,False
MASTER_PORT,False,False
MASTER_PUBLIC_KEY_PATH,False,False
MASTER_RETRY_COUNT,False,False
MASTER_SERVER_ID,False,True
MASTER_SSL,False,False
MASTER_SSL_CA,False,False
MASTER_SSL_CAPATH,False,False
MASTER_SSL_CERT,False,False
MASTER_SSL_CIPHER,False,False
MASTER_SSL_CRL,False,False
MASTER_SSL_CRLPATH,False,False
MASTER_SSL_KEY,False,False
MASTER_SSL_VERIFY_SERVER_CERT,False,False
MASTER_TLS_CIPHERSUITES,False,False
MASTER_TLS_VERSION,False,False
MASTER_USER,False,False
MASTER_ZSTD_COMPRESSION_LEVEL,False,False
MATCH,False,False
MAXVALUE,False,False
MAX_CONNECTIONS_PER_HOUR,False,False
MAX_QUERIES_PER_HOUR,False,False
MAX_ROWS,False,False
MAX_SIZE,False,False
MAX_UPDATES_PER_HOUR,False,False
MAX_USER_CONNECTIONS,False,False
MEDIUM,False,False
MEDIUMBLOB,False,False
MEDIUMINT,False,False
MEDIUMTEXT,False,False
MEMBER,False,False
MEMORY,False,False
MERGE,False,False
MESSAGE_TEXT,False,False
MICROSECOND,False,False
MIDDLEINT,False,False
MIGRATE,False,False
MINUTE,False,False
MINUTE_MICROSECOND,False,False
MINUTE_SECOND,False,False
MIN_ROWS,False,False
MOD,False,False
MODE,False,False
MODIFIES,False,False
MODIFY,False,False
MONTH,False,False
MULTILINESTRING,False,False
MULTIPOINT,False,False
MULTIPOLYGON,False,False
MUTEX,False,False
MYSQL_ERRNO,False,False
NAME,False,False
NAMES,False,False
NATIONAL,False,False
NATURAL,False,False
NCHAR,False,False
NDB,False,False
NDBCLUSTER,False,False
NESTED,False,False
NETWORK_NAMESPACE,False,False
NEVER,False,False
NEW,False,False
NEXT,False,False
NO,False,False
NODEGROUP,False,False
NONE,False,False
NOT,False,False
NOWAIT,False,False
NO_WAIT,False,False
NO_WRITE_TO_BINLOG,False,False
NTH_VALUE,False,False
NTILE,False,False
NULL,False,False
NULLS,False,False
NUMBER,False,False
NUMERIC,False,False
NVARCHAR,False,False
OF,False,False
OFF,False,False
OFFSET,False,False
OJ,False,False
OLD,False,False
ON,False,False
ONE,False,False
ONLY,False,False
OPEN,False,False
OPTIMIZE,False,False
OPTIMIZER_COSTS,False,False
OPTION,False,False
OPTIONAL,False,False
OPTIONALLY,False,False
OPTIONS,False,False
OR,False,False
ORDER,False,False
ORDINALITY,False,False
ORGANIZATION,False,False
OTHERS,False,False
OUT,False,False
OUTER,False,False
OUTFILE,False,False
OVER,False,False
OWNER,False,False
PACK_KEYS,False,False
PAGE,False,False
PARSER,False,False
PARTIAL,False,False
PARTITION,False,False
PARTITIONING,False,False
PARTITIONS,False,False
PASSWORD,False,False
PASSWORD_LOCK_TIME,False,False
PATH,False,False
PERCENT_RANK,False,False
PERSIST,False,False
PERSIST_ONLY,False,False
PHASE,False,False
PLUGIN,False,False
PLUGINS,False,False
PLUGIN_DIR,False,False
POINT,False,False
POLYGON,False,False
PORT,False,False
PRECEDES,False,False
PRECEDING,False,False
PRECISION,False,False
PREPARE,False,False
PRESERVE,False,False
PREV,False,False
PRIMARY,False,False
PRIVILEGES,False,False
PRIVILEGE_CHECKS_USER,False,False
PROCEDURE,False,False
PROCESS,False,False
PROCESSLIST,False,False
PROFILE,False,False
PROFILES,False,False
PROXY,False,False
PURGE,False,False
QUARTER,False,False
QUERY,False,False
QUICK,False,False
RANDOM,False,False
RANGE,False,False
RANK,False,False
READ,False,False
READS,False,False
READ_ONLY,False,False
READ_WRITE,False,False
REAL,False,False
REBUILD,False,False
RECOVER,False,False
RECURSIVE,False,False
REDOFILE,False,True
REDO_BUFFER_SIZE,False,False
REDUNDANT,False,False
REFERENCE,False,False
REFERENCES,False,False
REGEXP,False,False
REGISTRATION,False,False
RELAY,False,False
RELAYLOG,False,False
RELAY_LOG_FILE,False,False
RELAY_LOG_POS,False,False
RELAY_THREAD,False,False
RELEASE,False,False
RELOAD,False,False
REMOTE,False,True
REMOVE,False,False
RENAME,False,False
REORGANIZE,False,False
REPAIR,False,False
REPEAT,False,False
REPEATABLE,False,False
REPLACE,False,False
REPLICA,False,False
REPLICAS,False,False
REPLICATE_DO_DB,False,False
REPLICATE_DO_TABLE,False,False
REPLICATE_IGNORE_DB,False,False
REPLICATE_IGNORE_TABLE,False,False
REPLICATE_REWRITE_DB,False,False
REPLICATE_WILD_DO_TABLE,False,False
REPLICATE_WILD_IGNORE_TABLE,False,False
REPLICATION,False,False
REQUIRE,False,False
REQUIRE_ROW_FORMAT,False,False
RESET,False,False
RESIGNAL,False,False
RESOURCE,False,False
RESPECT,False,False
RESTART,False,False
RESTORE,False,False
RESTRICT,False,False
RESUME,False,False
RETAIN,False,False
RETURN,False,False
RETURNED_SQLSTATE,False,False
RETURNING,False,False
RETURNS,False,False
REUSE,False,False
REVERSE,False,False
REVOKE,False,False
RIGHT,False,False
RLIKE,False,False
ROLE,False,False
ROLLBACK,False,False
ROLLUP,False,False
ROTATE,False,False
ROUTINE,False,False
ROW,False,False
ROWS,False,False
ROW_COUNT,False,False
ROW_FORMAT,False,False
ROW_NUMBER,False,False
RTREE,False,False
SAVEPOINT,False,False
SCHEDULE,False,False
SCHEMA,False,False
SCHEMAS,False,False
SCHEMA_NAME,False,False
SECOND,False,False
SECONDARY,False,False
SECONDARY_ENGINE,False,False
SECONDARY_ENGINE_ATTRIBUTE,False,False
SECONDARY_LOAD,False,False
SECONDARY_UNLOAD,False,False
SECOND_MICROSECOND,False,False
SECURITY,False,False
SELECT,False,False
SENSITIVE,False,False
SEPARATOR,False,False
SERIAL,False,False
SERIALIZABLE,False,False
SERVER,False,False
SESSION,False,False
SET,False,False
SHARE,False,False
SHOW,False,False
SHUTDOWN,False,False
SIGNAL,False,False
SIGNED,False,False
SIMPLE,False,False
SKIP,False,False
SLAVE,False,False
SLOW,False,False
SMALLINT,False,False
SNAPSHOT,False,False
SOCKET,False,False
SOME,False,False
SONAME,False,False
SOUNDS,False,False
SOURCE,False,False
SOURCE_AUTO_POSITION,False,False
SOURCE_BIND,False,False
SOURCE_COMPRESSION_ALGORITHMS,False,False
SOURCE_CONNECT_RETRY,False,False
SOURCE_DELAY,False,False
SOURCE_HEARTBEAT_PERIOD,False,False
SOURCE_HOST,False,False
SOURCE_LOG_FILE,False,False
SOURCE_LOG_POS,False,False
SOURCE_PASSWORD,False,False
SOURCE_PORT,False,False
SOURCE_PUBLIC_KEY_PATH,False,False
SOURCE_RETRY_COUNT,False,False
SOURCE_SSL,False,False
SOURCE_SSL_CA,False,False
SOURCE_SSL_CAPATH,False,False
SOURCE_SSL_CERT,False,False
SOURCE_SSL_CIPHER,False,False
SOURCE_SSL_CRL,False,False
SOURCE_SSL_CRLPATH,False,False
SOURCE_SSL_KEY,False,False
SOURCE_SSL_VERIFY_SERVER_CERT,False,False
SOURCE_TLS_CIPHERSUITES,False,False
SOURCE_TLS_VERSION,False,False
SOURCE_USER,False,False
SOURCE_ZSTD_COMPRESSION_LEVEL,False,False
SPATIAL,False,False
SPECIFIC,False,False
SQL,False,False
SQLEXCEPTION,False,False
SQLSTATE,False,False
SQLWARNING,False,False
SQL_AFTER_GTIDS,False,False
SQL_AFTER_MTS_GAPS,False,False
SQL_BEFORE_GTIDS,False,False
SQL_BIG_RESULT,False,False
SQL_BUFFER_RESULT,False,False
SQL_CACHE,False,True
SQL_CALC_FOUND_ROWS,False,False
SQL_NO_CACHE,False,False
SQL_SMALL_RESULT,False,False
SQL_THREAD,False,False
SQL_TSI_DAY,False,False
SQL_TSI_HOUR,False,False
SQL_TSI_MINUTE,False,False
SQL_TSI_MONTH,False,False
SQL_TSI_QUARTER,False,False
SQL_TSI_SECOND,False,False
SQL_TSI_WEEK,False,False
SQL_TSI_YEAR,False,False
SRID,False,False
SSL,False,False
STACKED,False,False
START,False,False
STARTING,False,False
STARTS,False,False
STATS_AUTO_RECALC,False,False
STATS_PERSISTENT,False,False
STATS_SAMPLE_PAGES,False,False
STATUS,False,False
STOP,False,False
STORAGE,False,False
STORED,False,False
STRAIGHT_JOIN,False,False
STREAM,False,False
STRING,False,False
SUBCLASS_ORIGIN,False,False
SUBJECT,False,False
SUBPARTITION,False,False
SUBPARTITIONS,False,False
SUPER,False,False
SUSPEND,False,False
SWAPS,False,False
SWITCHES,False,False
SYSTEM,False,False
TABLE,False,False
TABLES,False,False
TABLESPACE,False,False
TABLE_CHECKSUM,False,False
TABLE_NAME,False,False
TEMPORARY,False,False
TEMPTABLE,False,False
TERMINATED,False,False
TEXT,False,False
THAN,False,False
THEN,False,False
THREAD_PRIORITY,False,False
TIES,False,False
TIME,False,False
TIMESTAMP,False,False
TIMESTAMPADD,False,False
TIMESTAMPDIFF,False,False
TINYBLOB,False,False
TINYINT,False,False
TINYTEXT,False,False
TLS,False,False
TO,False,False
TRAILING,False,False
TRANSACTION,False,False
TRIGGER,False,False
TRIGGERS,False,False
TRUE,False,False
TRUNCATE,False,False
TYPE,False,False
TYPES,False,False
UNBOUNDED,False,False
UNCOMMITTED,False,False
UNDEFINED,False,False
UNDO,False,False
UNDOFILE,False,False
UNDO_BUFFER_SIZE,False,False
UNICODE,False,False
UNINSTALL,False,False
UNION,False,False
UNIQUE,False,False
UNKNOWN,False,False
UNLOCK,False,False
UNREGISTER,False,False
UNSIGNED,False,False
UNTIL,False,False
UPDATE,False,False
UPGRADE,False,False
URL,False,False
USAGE,False,False
USE,False,False
USER,False,False
USER_RESOURCES,False,False
USE_FRM,False,False
USING,False,False
UTC_DATE,False,False
UTC_TIME,False,False
UTC_TIMESTAMP,False,False
VALIDATION,False,False
VALUE,False,False
VALUES,False,False
VARBINARY,False,False
VARCHAR,False,False
VARCHARACTER,False,False
VARIABLES,False,False
VARYING,False,False
VCPU,False,False
VIEW,False,False
VIRTUAL,False,False
VISIBLE,False,False
WAIT,False,False
WARNINGS,False,False
WEEK,False,False
WEIGHT_STRING,False,False
WHEN,False,False
WHERE,False,False
WHILE,False,False
WINDOW,False,False
WITH,False,False
WITHOUT,False,False
WORK,False,False
WRAPPER,False,False
WRITE,False,False
X509,False,False
XA,False,False
XID,False,False
XML,False,False
XOR,False,False
YEAR,False,False
YEAR_MONTH,False,False
ZEROFILL,False,False
ZONE,False,False
MySQL,False,False
The,False,False
A,False,False
ACTIVE,False,False
ADMIN,False,False
ARRAY,False,False
ATTRIBUTE,False,False
AUTHENTICATION,False,False
BUCKETS,False,False
BULK,False,False
CHALLENGE_RESPONSE,False,False
CLONE,False,False
COMPONENT,False,False
CUME_DIST,False,False
DEFINITION,False,False
DENSE_RANK,False,False
DESCRIPTION,False,False
EMPTY,False,False
ENFORCED,False,False
ENGINE_ATTRIBUTE,False,False
EXCEPT,False,False
EXCLUDE,False,False
FACTOR,False,False
FAILED_LOGIN_ATTEMPTS,False,False
FINISH,False,False
FIRST_VALUE,False,False
FOLLOWING,False,False
GENERATE,False,False
GEOMCOLLECTION,False,False
GET_MASTER_PUBLIC_KEY,False,False
GET_SOURCE_PUBLIC_KEY,False,False
GROUPING,False,False
GROUPS,False,False
GTID_ONLY,False,False
HISTOGRAM,False,False
HISTORY,False,False
INACTIVE,False,False
INITIAL,False,False
INITIATE,False,False
INTERSECT,False,False
INVISIBLE,False,False
JSON_TABLE,False,False
JSON_VALUE,False,False
KEYRING,False,False
LAG,False,False
LAST_VALUE,False,False
LATERAL,False,False
LEAD,False,False
LOCKED,False,False
MASTER_COMPRESSION_ALGORITHMS,False,False
MASTER_PUBLIC_KEY_PATH,False,False
MASTER_TLS_CIPHERSUITES,False,False
MASTER_ZSTD_COMPRESSION_LEVEL,False,False
MEMBER,False,False
NESTED,False,False
NETWORK_NAMESPACE,False,False
NOWAIT,False,False
NTH_VALUE,False,False
NTILE,False,False
NULLS,False,False
OF,False,False
OFF,False,False
OJ,False,False
OLD,False,False
OPTIONAL,False,False
ORDINALITY,False,False
ORGANIZATION,False,False
OTHERS,False,False
OVER,False,False
PASSWORD_LOCK_TIME,False,False
PATH,False,False
PERCENT_RANK,False,False
PERSIST,False,False
PERSIST_ONLY,False,False
PRECEDING,False,False
PRIVILEGE_CHECKS_USER,False,False
PROCESS,False,False
RANDOM,False,False
RANK,False,False
RECURSIVE,False,False
REFERENCE,False,False
REGISTRATION,False,False
REPLICA,False,False
REPLICAS,False,False
REQUIRE_ROW_FORMAT,False,False
RESOURCE,False,False
RESPECT,False,False
RESTART,False,False
RETAIN,False,False
RETURNING,False,False
REUSE,False,False
ROLE,False,False
ROW_NUMBER,False,False
SECONDARY,False,False
SECONDARY_ENGINE,False,False
SECONDARY_ENGINE_ATTRIBUTE,False,False
SECONDARY_LOAD,False,False
SECONDARY_UNLOAD,False,False
SKIP,False,False
SOURCE_AUTO_POSITION,False,False
SOURCE_BIND,False,False
SOURCE_COMPRESSION_ALGORITHMS,False,False
SOURCE_CONNECT_RETRY,False,False
SOURCE_DELAY,False,False
SOURCE_HEARTBEAT_PERIOD,False,False
SOURCE_HOST,False,False
SOURCE_LOG_FILE,False,False
SOURCE_LOG_POS,False,False
SOURCE_PASSWORD,False,False
SOURCE_PORT,False,False
SOURCE_PUBLIC_KEY_PATH,False,False
SOURCE_RETRY_COUNT,False,False
SOURCE_SSL,False,False
SOURCE_SSL_CA,False,False
SOURCE_SSL_CAPATH,False,False
SOURCE_SSL_CERT,False,False
SOURCE_SSL_CIPHER,False,False
SOURCE_SSL_CRL,False,False
SOURCE_SSL_CRLPATH,False,False
SOURCE_SSL_KEY,False,False
SOURCE_SSL_VERIFY_SERVER_CERT,False,False
SOURCE_TLS_CIPHERSUITES,False,False
SOURCE_TLS_VERSION,False,False
SOURCE_USER,False,False
SOURCE_ZSTD_COMPRESSION_LEVEL,False,False
SRID,False,False
STREAM,False,False
SYSTEM,False,False
THREAD_PRIORITY,False,False
TIES,False,False
TLS,False,False
UNBOUNDED,False,False
UNREGISTER,False,False
URL,False,False
VCPU,False,False
VISIBLE,False,False
WINDOW,False,False
ZONE,False,False
1 ACCESSIBLE False False
2 ACCOUNT False False
3 ACTION False False
4 ACTIVE False False
5 ADD False False
6 ADMIN False False
7 AFTER False False
8 AGAINST False False
9 AGGREGATE False False
10 ALGORITHM False False
11 ALL False False
12 ALTER False False
13 ALWAYS False False
14 ANALYSE False True
15 ANALYZE False False
16 AND False False
17 ANY False False
18 ARRAY False False
19 AS False False
20 ASC False False
21 ASCII False False
22 ASENSITIVE False False
23 AT False False
24 ATTRIBUTE False False
25 AUTHENTICATION False False
26 AUTOEXTEND_SIZE False False
27 AUTO_INCREMENT False False
28 AVG False False
29 AVG_ROW_LENGTH False False
30 BACKUP False False
31 BEFORE False False
32 BEGIN False False
33 BETWEEN False False
34 BIGINT False False
35 BINARY False False
36 BINLOG False False
37 BIT False False
38 BLOB False False
39 BLOCK False False
40 BOOL False False
41 BOOLEAN False False
42 BOTH False False
43 BTREE False False
44 BUCKETS False False
45 BULK False False
46 BY False False
47 BYTE False False
48 CACHE False False
49 CALL False False
50 CASCADE False False
51 CASCADED False False
52 CASE False False
53 CATALOG_NAME False False
54 CHAIN False False
55 CHALLENGE_RESPONSE False False
56 CHANGE False False
57 CHANGED False False
58 CHANNEL False False
59 CHAR False False
60 CHARACTER False False
61 CHARSET False False
62 CHECK False False
63 CHECKSUM False False
64 CIPHER False False
65 CLASS_ORIGIN False False
66 CLIENT False False
67 CLONE False False
68 CLOSE False False
69 COALESCE False False
70 CODE False False
71 COLLATE False False
72 COLLATION False False
73 COLUMN False False
74 COLUMNS False False
75 COLUMN_FORMAT False False
76 COLUMN_NAME False False
77 COMMENT False False
78 COMMIT False False
79 COMMITTED False False
80 COMPACT False False
81 COMPLETION False False
82 COMPONENT False False
83 COMPRESSED False False
84 COMPRESSION False False
85 CONCURRENT False False
86 CONDITION False False
87 CONNECTION False False
88 CONSISTENT False False
89 CONSTRAINT False False
90 CONSTRAINT_CATALOG False False
91 CONSTRAINT_NAME False False
92 CONSTRAINT_SCHEMA False False
93 CONTAINS False False
94 CONTEXT False False
95 CONTINUE False False
96 CONVERT False False
97 CPU False False
98 CREATE False False
99 CROSS False False
100 CUBE False False
101 CUME_DIST False False
102 CURRENT False False
103 CURRENT_DATE False False
104 CURRENT_TIME False False
105 CURRENT_TIMESTAMP False False
106 CURRENT_USER False False
107 CURSOR False False
108 CURSOR_NAME False False
109 DATA False False
110 DATABASE False False
111 DATABASES False False
112 DATAFILE False False
113 DATE False False
114 DATETIME False False
115 DAY False False
116 DAY_HOUR False False
117 DAY_MICROSECOND False False
118 DAY_MINUTE False False
119 DAY_SECOND False False
120 DEALLOCATE False False
121 DEC False False
122 DECIMAL False False
123 DECLARE False False
124 DEFAULT False False
125 DEFAULT_AUTH False False
126 DEFINER False False
127 DEFINITION False False
128 DELAYED False False
129 DELAY_KEY_WRITE False False
130 DELETE False False
131 DENSE_RANK False False
132 DESC False False
133 DESCRIBE False False
134 DESCRIPTION False False
135 DES_KEY_FILE False True
136 DETERMINISTIC False False
137 DIAGNOSTICS False False
138 DIRECTORY False False
139 DISABLE False False
140 DISCARD False False
141 DISK False False
142 DISTINCT False False
143 DISTINCTROW False False
144 DIV False False
145 DO False False
146 DOUBLE False False
147 DROP False False
148 DUAL False False
149 DUMPFILE False False
150 DUPLICATE False False
151 DYNAMIC False False
152 EACH False False
153 ELSE False False
154 ELSEIF False False
155 EMPTY False False
156 ENABLE False False
157 ENCLOSED False False
158 ENCRYPTION False False
159 END False False
160 ENDS False False
161 ENFORCED False False
162 ENGINE False False
163 ENGINES False False
164 ENGINE_ATTRIBUTE False False
165 ENUM False False
166 ERROR False False
167 ERRORS False False
168 ESCAPE False False
169 ESCAPED False False
170 EVENT False False
171 EVENTS False False
172 EVERY False False
173 EXCEPT False False
174 EXCHANGE False False
175 EXCLUDE False False
176 EXECUTE False False
177 EXISTS False False
178 EXIT False False
179 EXPANSION False False
180 EXPIRE False False
181 EXPLAIN False False
182 EXPORT False False
183 EXTENDED False False
184 EXTENT_SIZE False False
185 FACTOR False False
186 FAILED_LOGIN_ATTEMPTS False False
187 FALSE False False
188 FAST False False
189 FAULTS False False
190 FETCH False False
191 FIELDS False False
192 FILE False False
193 FILE_BLOCK_SIZE False False
194 FILTER False False
195 FINISH False False
196 FIRST False False
197 FIRST_VALUE False False
198 FIXED False False
199 FLOAT False False
200 FLOAT4 False False
201 FLOAT8 False False
202 FLUSH False False
203 FOLLOWING False False
204 FOLLOWS False False
205 FOR False False
206 FORCE False False
207 FOREIGN False False
208 FORMAT False False
209 FOUND False False
210 FROM False False
211 FULL False False
212 FULLTEXT False False
213 FUNCTION False False
214 GENERAL False False
215 GENERATE False False
216 GENERATED False False
217 GEOMCOLLECTION False False
218 GEOMETRY False False
219 GEOMETRYCOLLECTION False False
220 GET False False
221 GET_FORMAT False False
222 GET_MASTER_PUBLIC_KEY False False
223 GET_SOURCE_PUBLIC_KEY False False
224 GLOBAL False False
225 GRANT False False
226 GRANTS False False
227 GROUP False False
228 GROUPING False False
229 GROUPS False False
230 GROUP_REPLICATION False False
231 GTID_ONLY False False
232 HANDLER False False
233 HASH False False
234 HAVING False False
235 HELP False False
236 HIGH_PRIORITY False False
237 HISTOGRAM False False
238 HISTORY False False
239 HOST False False
240 HOSTS False False
241 HOUR False False
242 HOUR_MICROSECOND False False
243 HOUR_MINUTE False False
244 HOUR_SECOND False False
245 IDENTIFIED False False
246 IF False False
247 IGNORE False False
248 IGNORE_SERVER_IDS False False
249 IMPORT False False
250 IN False False
251 INACTIVE False False
252 INDEX False False
253 INDEXES False False
254 INFILE False False
255 INITIAL False False
256 INITIAL_SIZE False False
257 INITIATE False False
258 INNER False False
259 INOUT False False
260 INSENSITIVE False False
261 INSERT False False
262 INSERT_METHOD False False
263 INSTALL False False
264 INSTANCE False False
265 INT False False
266 INT1 False False
267 INT2 False False
268 INT3 False False
269 INT4 False False
270 INT8 False False
271 INTEGER False False
272 INTERSECT False False
273 INTERVAL False False
274 INTO False False
275 INVISIBLE False False
276 INVOKER False False
277 IO False False
278 IO_AFTER_GTIDS False False
279 IO_BEFORE_GTIDS False False
280 IO_THREAD False False
281 IPC False False
282 IS False False
283 ISOLATION False False
284 ISSUER False False
285 ITERATE False False
286 JOIN False False
287 JSON False False
288 JSON_TABLE False False
289 JSON_VALUE False False
290 KEY False False
291 KEYRING False False
292 KEYS False False
293 KEY_BLOCK_SIZE False False
294 KILL False False
295 LAG False False
296 LANGUAGE False False
297 LAST False False
298 LAST_VALUE False False
299 LATERAL False False
300 LEAD False False
301 LEADING False False
302 LEAVE False False
303 LEAVES False False
304 LEFT False False
305 LESS False False
306 LEVEL False False
307 LIKE False False
308 LIMIT False False
309 LINEAR False False
310 LINES False False
311 LINESTRING False False
312 LIST False False
313 LOAD False False
314 LOCAL False False
315 LOCALTIME False False
316 LOCALTIMESTAMP False False
317 LOCK False False
318 LOCKED False False
319 LOCKS False False
320 LOGFILE False False
321 LOGS False False
322 LONG False False
323 LONGBLOB False False
324 LONGTEXT False False
325 LOOP False False
326 LOW_PRIORITY False False
327 MASTER False False
328 MASTER_AUTO_POSITION False False
329 MASTER_BIND False False
330 MASTER_COMPRESSION_ALGORITHMS False False
331 MASTER_CONNECT_RETRY False False
332 MASTER_DELAY False False
333 MASTER_HEARTBEAT_PERIOD False False
334 MASTER_HOST False False
335 MASTER_LOG_FILE False False
336 MASTER_LOG_POS False False
337 MASTER_PASSWORD False False
338 MASTER_PORT False False
339 MASTER_PUBLIC_KEY_PATH False False
340 MASTER_RETRY_COUNT False False
341 MASTER_SERVER_ID False True
342 MASTER_SSL False False
343 MASTER_SSL_CA False False
344 MASTER_SSL_CAPATH False False
345 MASTER_SSL_CERT False False
346 MASTER_SSL_CIPHER False False
347 MASTER_SSL_CRL False False
348 MASTER_SSL_CRLPATH False False
349 MASTER_SSL_KEY False False
350 MASTER_SSL_VERIFY_SERVER_CERT False False
351 MASTER_TLS_CIPHERSUITES False False
352 MASTER_TLS_VERSION False False
353 MASTER_USER False False
354 MASTER_ZSTD_COMPRESSION_LEVEL False False
355 MATCH False False
356 MAXVALUE False False
357 MAX_CONNECTIONS_PER_HOUR False False
358 MAX_QUERIES_PER_HOUR False False
359 MAX_ROWS False False
360 MAX_SIZE False False
361 MAX_UPDATES_PER_HOUR False False
362 MAX_USER_CONNECTIONS False False
363 MEDIUM False False
364 MEDIUMBLOB False False
365 MEDIUMINT False False
366 MEDIUMTEXT False False
367 MEMBER False False
368 MEMORY False False
369 MERGE False False
370 MESSAGE_TEXT False False
371 MICROSECOND False False
372 MIDDLEINT False False
373 MIGRATE False False
374 MINUTE False False
375 MINUTE_MICROSECOND False False
376 MINUTE_SECOND False False
377 MIN_ROWS False False
378 MOD False False
379 MODE False False
380 MODIFIES False False
381 MODIFY False False
382 MONTH False False
383 MULTILINESTRING False False
384 MULTIPOINT False False
385 MULTIPOLYGON False False
386 MUTEX False False
387 MYSQL_ERRNO False False
388 NAME False False
389 NAMES False False
390 NATIONAL False False
391 NATURAL False False
392 NCHAR False False
393 NDB False False
394 NDBCLUSTER False False
395 NESTED False False
396 NETWORK_NAMESPACE False False
397 NEVER False False
398 NEW False False
399 NEXT False False
400 NO False False
401 NODEGROUP False False
402 NONE False False
403 NOT False False
404 NOWAIT False False
405 NO_WAIT False False
406 NO_WRITE_TO_BINLOG False False
407 NTH_VALUE False False
408 NTILE False False
409 NULL False False
410 NULLS False False
411 NUMBER False False
412 NUMERIC False False
413 NVARCHAR False False
414 OF False False
415 OFF False False
416 OFFSET False False
417 OJ False False
418 OLD False False
419 ON False False
420 ONE False False
421 ONLY False False
422 OPEN False False
423 OPTIMIZE False False
424 OPTIMIZER_COSTS False False
425 OPTION False False
426 OPTIONAL False False
427 OPTIONALLY False False
428 OPTIONS False False
429 OR False False
430 ORDER False False
431 ORDINALITY False False
432 ORGANIZATION False False
433 OTHERS False False
434 OUT False False
435 OUTER False False
436 OUTFILE False False
437 OVER False False
438 OWNER False False
439 PACK_KEYS False False
440 PAGE False False
441 PARSER False False
442 PARTIAL False False
443 PARTITION False False
444 PARTITIONING False False
445 PARTITIONS False False
446 PASSWORD False False
447 PASSWORD_LOCK_TIME False False
448 PATH False False
449 PERCENT_RANK False False
450 PERSIST False False
451 PERSIST_ONLY False False
452 PHASE False False
453 PLUGIN False False
454 PLUGINS False False
455 PLUGIN_DIR False False
456 POINT False False
457 POLYGON False False
458 PORT False False
459 PRECEDES False False
460 PRECEDING False False
461 PRECISION False False
462 PREPARE False False
463 PRESERVE False False
464 PREV False False
465 PRIMARY False False
466 PRIVILEGES False False
467 PRIVILEGE_CHECKS_USER False False
468 PROCEDURE False False
469 PROCESS False False
470 PROCESSLIST False False
471 PROFILE False False
472 PROFILES False False
473 PROXY False False
474 PURGE False False
475 QUARTER False False
476 QUERY False False
477 QUICK False False
478 RANDOM False False
479 RANGE False False
480 RANK False False
481 READ False False
482 READS False False
483 READ_ONLY False False
484 READ_WRITE False False
485 REAL False False
486 REBUILD False False
487 RECOVER False False
488 RECURSIVE False False
489 REDOFILE False True
490 REDO_BUFFER_SIZE False False
491 REDUNDANT False False
492 REFERENCE False False
493 REFERENCES False False
494 REGEXP False False
495 REGISTRATION False False
496 RELAY False False
497 RELAYLOG False False
498 RELAY_LOG_FILE False False
499 RELAY_LOG_POS False False
500 RELAY_THREAD False False
501 RELEASE False False
502 RELOAD False False
503 REMOTE False True
504 REMOVE False False
505 RENAME False False
506 REORGANIZE False False
507 REPAIR False False
508 REPEAT False False
509 REPEATABLE False False
510 REPLACE False False
511 REPLICA False False
512 REPLICAS False False
513 REPLICATE_DO_DB False False
514 REPLICATE_DO_TABLE False False
515 REPLICATE_IGNORE_DB False False
516 REPLICATE_IGNORE_TABLE False False
517 REPLICATE_REWRITE_DB False False
518 REPLICATE_WILD_DO_TABLE False False
519 REPLICATE_WILD_IGNORE_TABLE False False
520 REPLICATION False False
521 REQUIRE False False
522 REQUIRE_ROW_FORMAT False False
523 RESET False False
524 RESIGNAL False False
525 RESOURCE False False
526 RESPECT False False
527 RESTART False False
528 RESTORE False False
529 RESTRICT False False
530 RESUME False False
531 RETAIN False False
532 RETURN False False
533 RETURNED_SQLSTATE False False
534 RETURNING False False
535 RETURNS False False
536 REUSE False False
537 REVERSE False False
538 REVOKE False False
539 RIGHT False False
540 RLIKE False False
541 ROLE False False
542 ROLLBACK False False
543 ROLLUP False False
544 ROTATE False False
545 ROUTINE False False
546 ROW False False
547 ROWS False False
548 ROW_COUNT False False
549 ROW_FORMAT False False
550 ROW_NUMBER False False
551 RTREE False False
552 SAVEPOINT False False
553 SCHEDULE False False
554 SCHEMA False False
555 SCHEMAS False False
556 SCHEMA_NAME False False
557 SECOND False False
558 SECONDARY False False
559 SECONDARY_ENGINE False False
560 SECONDARY_ENGINE_ATTRIBUTE False False
561 SECONDARY_LOAD False False
562 SECONDARY_UNLOAD False False
563 SECOND_MICROSECOND False False
564 SECURITY False False
565 SELECT False False
566 SENSITIVE False False
567 SEPARATOR False False
568 SERIAL False False
569 SERIALIZABLE False False
570 SERVER False False
571 SESSION False False
572 SET False False
573 SHARE False False
574 SHOW False False
575 SHUTDOWN False False
576 SIGNAL False False
577 SIGNED False False
578 SIMPLE False False
579 SKIP False False
580 SLAVE False False
581 SLOW False False
582 SMALLINT False False
583 SNAPSHOT False False
584 SOCKET False False
585 SOME False False
586 SONAME False False
587 SOUNDS False False
588 SOURCE False False
589 SOURCE_AUTO_POSITION False False
590 SOURCE_BIND False False
591 SOURCE_COMPRESSION_ALGORITHMS False False
592 SOURCE_CONNECT_RETRY False False
593 SOURCE_DELAY False False
594 SOURCE_HEARTBEAT_PERIOD False False
595 SOURCE_HOST False False
596 SOURCE_LOG_FILE False False
597 SOURCE_LOG_POS False False
598 SOURCE_PASSWORD False False
599 SOURCE_PORT False False
600 SOURCE_PUBLIC_KEY_PATH False False
601 SOURCE_RETRY_COUNT False False
602 SOURCE_SSL False False
603 SOURCE_SSL_CA False False
604 SOURCE_SSL_CAPATH False False
605 SOURCE_SSL_CERT False False
606 SOURCE_SSL_CIPHER False False
607 SOURCE_SSL_CRL False False
608 SOURCE_SSL_CRLPATH False False
609 SOURCE_SSL_KEY False False
610 SOURCE_SSL_VERIFY_SERVER_CERT False False
611 SOURCE_TLS_CIPHERSUITES False False
612 SOURCE_TLS_VERSION False False
613 SOURCE_USER False False
614 SOURCE_ZSTD_COMPRESSION_LEVEL False False
615 SPATIAL False False
616 SPECIFIC False False
617 SQL False False
618 SQLEXCEPTION False False
619 SQLSTATE False False
620 SQLWARNING False False
621 SQL_AFTER_GTIDS False False
622 SQL_AFTER_MTS_GAPS False False
623 SQL_BEFORE_GTIDS False False
624 SQL_BIG_RESULT False False
625 SQL_BUFFER_RESULT False False
626 SQL_CACHE False True
627 SQL_CALC_FOUND_ROWS False False
628 SQL_NO_CACHE False False
629 SQL_SMALL_RESULT False False
630 SQL_THREAD False False
631 SQL_TSI_DAY False False
632 SQL_TSI_HOUR False False
633 SQL_TSI_MINUTE False False
634 SQL_TSI_MONTH False False
635 SQL_TSI_QUARTER False False
636 SQL_TSI_SECOND False False
637 SQL_TSI_WEEK False False
638 SQL_TSI_YEAR False False
639 SRID False False
640 SSL False False
641 STACKED False False
642 START False False
643 STARTING False False
644 STARTS False False
645 STATS_AUTO_RECALC False False
646 STATS_PERSISTENT False False
647 STATS_SAMPLE_PAGES False False
648 STATUS False False
649 STOP False False
650 STORAGE False False
651 STORED False False
652 STRAIGHT_JOIN False False
653 STREAM False False
654 STRING False False
655 SUBCLASS_ORIGIN False False
656 SUBJECT False False
657 SUBPARTITION False False
658 SUBPARTITIONS False False
659 SUPER False False
660 SUSPEND False False
661 SWAPS False False
662 SWITCHES False False
663 SYSTEM False False
664 TABLE False False
665 TABLES False False
666 TABLESPACE False False
667 TABLE_CHECKSUM False False
668 TABLE_NAME False False
669 TEMPORARY False False
670 TEMPTABLE False False
671 TERMINATED False False
672 TEXT False False
673 THAN False False
674 THEN False False
675 THREAD_PRIORITY False False
676 TIES False False
677 TIME False False
678 TIMESTAMP False False
679 TIMESTAMPADD False False
680 TIMESTAMPDIFF False False
681 TINYBLOB False False
682 TINYINT False False
683 TINYTEXT False False
684 TLS False False
685 TO False False
686 TRAILING False False
687 TRANSACTION False False
688 TRIGGER False False
689 TRIGGERS False False
690 TRUE False False
691 TRUNCATE False False
692 TYPE False False
693 TYPES False False
694 UNBOUNDED False False
695 UNCOMMITTED False False
696 UNDEFINED False False
697 UNDO False False
698 UNDOFILE False False
699 UNDO_BUFFER_SIZE False False
700 UNICODE False False
701 UNINSTALL False False
702 UNION False False
703 UNIQUE False False
704 UNKNOWN False False
705 UNLOCK False False
706 UNREGISTER False False
707 UNSIGNED False False
708 UNTIL False False
709 UPDATE False False
710 UPGRADE False False
711 URL False False
712 USAGE False False
713 USE False False
714 USER False False
715 USER_RESOURCES False False
716 USE_FRM False False
717 USING False False
718 UTC_DATE False False
719 UTC_TIME False False
720 UTC_TIMESTAMP False False
721 VALIDATION False False
722 VALUE False False
723 VALUES False False
724 VARBINARY False False
725 VARCHAR False False
726 VARCHARACTER False False
727 VARIABLES False False
728 VARYING False False
729 VCPU False False
730 VIEW False False
731 VIRTUAL False False
732 VISIBLE False False
733 WAIT False False
734 WARNINGS False False
735 WEEK False False
736 WEIGHT_STRING False False
737 WHEN False False
738 WHERE False False
739 WHILE False False
740 WINDOW False False
741 WITH False False
742 WITHOUT False False
743 WORK False False
744 WRAPPER False False
745 WRITE False False
746 X509 False False
747 XA False False
748 XID False False
749 XML False False
750 XOR False False
751 YEAR False False
752 YEAR_MONTH False False
753 ZEROFILL False False
754 ZONE False False
755 MySQL False False
756 The False False
757 A False False
758 ACTIVE False False
759 ADMIN False False
760 ARRAY False False
761 ATTRIBUTE False False
762 AUTHENTICATION False False
763 BUCKETS False False
764 BULK False False
765 CHALLENGE_RESPONSE False False
766 CLONE False False
767 COMPONENT False False
768 CUME_DIST False False
769 DEFINITION False False
770 DENSE_RANK False False
771 DESCRIPTION False False
772 EMPTY False False
773 ENFORCED False False
774 ENGINE_ATTRIBUTE False False
775 EXCEPT False False
776 EXCLUDE False False
777 FACTOR False False
778 FAILED_LOGIN_ATTEMPTS False False
779 FINISH False False
780 FIRST_VALUE False False
781 FOLLOWING False False
782 GENERATE False False
783 GEOMCOLLECTION False False
784 GET_MASTER_PUBLIC_KEY False False
785 GET_SOURCE_PUBLIC_KEY False False
786 GROUPING False False
787 GROUPS False False
788 GTID_ONLY False False
789 HISTOGRAM False False
790 HISTORY False False
791 INACTIVE False False
792 INITIAL False False
793 INITIATE False False
794 INTERSECT False False
795 INVISIBLE False False
796 JSON_TABLE False False
797 JSON_VALUE False False
798 KEYRING False False
799 LAG False False
800 LAST_VALUE False False
801 LATERAL False False
802 LEAD False False
803 LOCKED False False
804 MASTER_COMPRESSION_ALGORITHMS False False
805 MASTER_PUBLIC_KEY_PATH False False
806 MASTER_TLS_CIPHERSUITES False False
807 MASTER_ZSTD_COMPRESSION_LEVEL False False
808 MEMBER False False
809 NESTED False False
810 NETWORK_NAMESPACE False False
811 NOWAIT False False
812 NTH_VALUE False False
813 NTILE False False
814 NULLS False False
815 OF False False
816 OFF False False
817 OJ False False
818 OLD False False
819 OPTIONAL False False
820 ORDINALITY False False
821 ORGANIZATION False False
822 OTHERS False False
823 OVER False False
824 PASSWORD_LOCK_TIME False False
825 PATH False False
826 PERCENT_RANK False False
827 PERSIST False False
828 PERSIST_ONLY False False
829 PRECEDING False False
830 PRIVILEGE_CHECKS_USER False False
831 PROCESS False False
832 RANDOM False False
833 RANK False False
834 RECURSIVE False False
835 REFERENCE False False
836 REGISTRATION False False
837 REPLICA False False
838 REPLICAS False False
839 REQUIRE_ROW_FORMAT False False
840 RESOURCE False False
841 RESPECT False False
842 RESTART False False
843 RETAIN False False
844 RETURNING False False
845 REUSE False False
846 ROLE False False
847 ROW_NUMBER False False
848 SECONDARY False False
849 SECONDARY_ENGINE False False
850 SECONDARY_ENGINE_ATTRIBUTE False False
851 SECONDARY_LOAD False False
852 SECONDARY_UNLOAD False False
853 SKIP False False
854 SOURCE_AUTO_POSITION False False
855 SOURCE_BIND False False
856 SOURCE_COMPRESSION_ALGORITHMS False False
857 SOURCE_CONNECT_RETRY False False
858 SOURCE_DELAY False False
859 SOURCE_HEARTBEAT_PERIOD False False
860 SOURCE_HOST False False
861 SOURCE_LOG_FILE False False
862 SOURCE_LOG_POS False False
863 SOURCE_PASSWORD False False
864 SOURCE_PORT False False
865 SOURCE_PUBLIC_KEY_PATH False False
866 SOURCE_RETRY_COUNT False False
867 SOURCE_SSL False False
868 SOURCE_SSL_CA False False
869 SOURCE_SSL_CAPATH False False
870 SOURCE_SSL_CERT False False
871 SOURCE_SSL_CIPHER False False
872 SOURCE_SSL_CRL False False
873 SOURCE_SSL_CRLPATH False False
874 SOURCE_SSL_KEY False False
875 SOURCE_SSL_VERIFY_SERVER_CERT False False
876 SOURCE_TLS_CIPHERSUITES False False
877 SOURCE_TLS_VERSION False False
878 SOURCE_USER False False
879 SOURCE_ZSTD_COMPRESSION_LEVEL False False
880 SRID False False
881 STREAM False False
882 SYSTEM False False
883 THREAD_PRIORITY False False
884 TIES False False
885 TLS False False
886 UNBOUNDED False False
887 UNREGISTER False False
888 URL False False
889 VCPU False False
890 VISIBLE False False
891 WINDOW False False
892 ZONE False False

View file

43
tests/conftest.py Normal file
View file

@ -0,0 +1,43 @@
from __future__ import annotations
from typing import Generator
import pytest
from mysql.connector import connect
from harlequin_mysql.adapter import (
HarlequinMySQLAdapter,
HarlequinMySQLConnection,
)
@pytest.fixture
def connection() -> Generator[HarlequinMySQLConnection, None, None]:
mysqlconn = connect(
host="localhost",
user="root",
password="example",
database="mysql",
autocommit=True,
)
cur = mysqlconn.cursor()
cur.execute("drop database if exists test;")
cur.execute("drop database if exists one;")
cur.execute("drop database if exists two;")
cur.execute("drop database if exists three;")
cur.execute("create database test;")
cur.close()
conn = HarlequinMySQLAdapter(
conn_str=tuple(),
host="localhost",
user="root",
password="example",
database="test",
).connect()
yield conn
cur = mysqlconn.cursor()
cur.execute("drop database if exists test;")
cur.execute("drop database if exists one;")
cur.execute("drop database if exists two;")
cur.execute("drop database if exists three;")
cur.close()

220
tests/test_adapter.py Normal file
View file

@ -0,0 +1,220 @@
from __future__ import annotations
import sys
import pytest
from harlequin import (
HarlequinAdapter,
HarlequinCompletion,
HarlequinConnection,
HarlequinCursor,
)
from harlequin.catalog import Catalog, CatalogItem
from harlequin.exception import HarlequinConnectionError, HarlequinQueryError
from mysql.connector.cursor import MySQLCursor
from mysql.connector.pooling import PooledMySQLConnection
from textual_fastdatatable.backend import create_backend
from harlequin_mysql.adapter import (
HarlequinMySQLAdapter,
HarlequinMySQLConnection,
)
if sys.version_info < (3, 10):
from importlib_metadata import entry_points
else:
from importlib.metadata import entry_points
def test_plugin_discovery() -> None:
PLUGIN_NAME = "mysql"
eps = entry_points(group="harlequin.adapter")
assert eps[PLUGIN_NAME]
adapter_cls = eps[PLUGIN_NAME].load()
assert issubclass(adapter_cls, HarlequinAdapter)
assert adapter_cls == HarlequinMySQLAdapter
def test_connect() -> None:
conn = HarlequinMySQLAdapter(
conn_str=tuple(), user="root", password="example"
).connect()
assert isinstance(conn, HarlequinConnection)
def test_init_extra_kwargs() -> None:
assert HarlequinMySQLAdapter(
conn_str=tuple(), user="root", password="example", foo=1, bar="baz"
).connect()
def test_connect_raises_connection_error() -> None:
with pytest.raises(HarlequinConnectionError):
_ = HarlequinMySQLAdapter(conn_str=("foo",)).connect()
@pytest.mark.parametrize(
"options,expected",
[
({}, "127.0.0.1:3306/"),
({"host": "foo.bar"}, "foo.bar:3306/"),
({"host": "foo.bar", "port": "3305"}, "foo.bar:3305/"),
({"unix_socket": "/foo/bar"}, "/foo/bar:3306/"),
({"unix_socket": "/foo/bar", "database": "baz"}, "/foo/bar:3306/baz"),
],
)
def test_connection_id(options: dict[str, str | int | None], expected: str) -> None:
adapter = HarlequinMySQLAdapter(
conn_str=tuple(),
**options, # type: ignore[arg-type]
)
assert adapter.connection_id == expected
def test_get_catalog(connection: HarlequinMySQLConnection) -> None:
catalog = connection.get_catalog()
assert isinstance(catalog, Catalog)
assert catalog.items
assert isinstance(catalog.items[0], CatalogItem)
assert any(
item.label == "test" and item.type_label == "db" for item in catalog.items
)
def test_get_completions(connection: HarlequinMySQLConnection) -> None:
completions = connection.get_completions()
assert completions
assert isinstance(completions[0], HarlequinCompletion)
expected = ["action", "var_pop"]
filtered = list(filter(lambda x: x.label in expected, completions))
assert len(filtered) == len(expected)
def test_execute_ddl(connection: HarlequinMySQLConnection) -> None:
cur = connection.execute("create table foo (a int)")
assert cur is None
def test_execute_select(connection: HarlequinMySQLConnection) -> None:
cur = connection.execute("select 1 as a")
assert isinstance(cur, HarlequinCursor)
assert cur.columns() == [("a", "##")]
data = cur.fetchall()
backend = create_backend(data)
assert backend.column_count == 1
assert backend.row_count == 1
def test_execute_select_no_records(connection: HarlequinMySQLConnection) -> None:
cur = connection.execute("select 1 as a where false")
assert isinstance(cur, HarlequinCursor)
assert cur.columns() == [("a", "##")]
data = cur.fetchall()
backend = create_backend(data)
assert backend.row_count == 0
def test_execute_select_dupe_cols(connection: HarlequinMySQLConnection) -> None:
cur = connection.execute("select 1 as a, 2 as a, 3 as a")
assert isinstance(cur, HarlequinCursor)
assert len(cur.columns()) == 3
data = cur.fetchall()
backend = create_backend(data)
assert backend.column_count == 3
assert backend.row_count == 1
def test_set_limit(connection: HarlequinMySQLConnection) -> None:
cur = connection.execute("select 1 as a union all select 2 union all select 3")
assert isinstance(cur, HarlequinCursor)
cur = cur.set_limit(2)
assert isinstance(cur, HarlequinCursor)
data = cur.fetchall()
backend = create_backend(data)
assert backend.column_count == 1
assert backend.row_count == 2
def test_execute_raises_query_error(connection: HarlequinMySQLConnection) -> None:
with pytest.raises(HarlequinQueryError):
_ = connection.execute("selec;")
def test_can_execute_pool_size_queries(connection: HarlequinMySQLConnection) -> None:
pool_size = connection._pool.pool_size
cursors: list[HarlequinCursor] = []
for _ in range(pool_size):
cur = connection.execute("select 1")
assert cur is not None
cursors.append(cur)
assert len(cursors) == pool_size
def test_can_execute_pool_size_ddl(connection: HarlequinMySQLConnection) -> None:
pool_size = connection._pool.pool_size
cursors: list[None] = []
for i in range(pool_size):
cur = connection.execute(f"create table t_{i} as select {i}")
assert cur is None
cursors.append(cur)
assert len(cursors) == pool_size
def test_execute_more_than_pool_size_queries_does_not_raise(
connection: HarlequinMySQLConnection,
) -> None:
pool_size = connection._pool.pool_size
cursors: list[HarlequinCursor] = []
for _ in range(pool_size * 2):
cur = connection.execute("select 1")
if cur is not None:
cursors.append(cur)
assert len(cursors) == pool_size
def test_execute_more_than_pool_size_ddl_does_not_raise(
connection: HarlequinMySQLConnection,
) -> None:
pool_size = connection._pool.pool_size
number_of_ddl_queries = pool_size * 2
cursors: list[None] = []
for i in range(number_of_ddl_queries):
cur = connection.execute(f"create table t_{i} as select {i}")
assert cur is None
cursors.append(cur)
assert len(cursors) == number_of_ddl_queries
def test_use_database_updates_pool(connection: HarlequinMySQLConnection) -> None:
conn, cur = connection.safe_get_mysql_cursor()
assert conn is not None
assert cur is not None
assert conn.database == "test"
cur.close()
conn.close()
connection.execute("use mysql")
pool_size = connection._pool.pool_size
conns: list[PooledMySQLConnection] = []
curs: list[MySQLCursor] = []
for _ in range(pool_size):
conn, cur = connection.safe_get_mysql_cursor()
assert conn is not None
assert cur is not None
assert conn.database == "mysql"
conns.append(conn)
curs.append(cur)
assert len(conns) == pool_size
for cur in curs:
cur.close()
for conn in conns:
conn.close()
def test_close(connection: HarlequinMySQLConnection) -> None:
connection.close()
# run again to test error handling.
connection.close()

85
tests/test_catalog.py Normal file
View file

@ -0,0 +1,85 @@
import pytest
from harlequin_mysql.adapter import HarlequinMySQLConnection
from harlequin_mysql.catalog import (
ColumnCatalogItem,
DatabaseCatalogItem,
RelationCatalogItem,
TableCatalogItem,
ViewCatalogItem,
)
@pytest.fixture
def connection_with_objects(
connection: HarlequinMySQLConnection,
) -> HarlequinMySQLConnection:
connection.execute("create database one")
connection.execute("create table one.foo as select 1 as a, '2' as b")
connection.execute("create table one.bar as select 1 as a, '2' as b")
connection.execute("create table one.baz as select 1 as a, '2' as b")
connection.execute("create database two")
connection.execute("create view two.qux as select * from one.foo")
connection.execute("create database three")
# the original connection fixture will clean this up.
return connection
def test_catalog(connection_with_objects: HarlequinMySQLConnection) -> None:
conn = connection_with_objects
catalog = conn.get_catalog()
# five databases: dev, test, one, two, and three.
assert len(catalog.items) == 5
database_items = catalog.items
assert all(isinstance(item, DatabaseCatalogItem) for item in database_items)
[database_one_item] = filter(lambda item: item.label == "one", database_items)
assert isinstance(database_one_item, DatabaseCatalogItem)
assert not database_one_item.children
assert not database_one_item.loaded
table_items = database_one_item.fetch_children()
assert all(isinstance(item, RelationCatalogItem) for item in table_items)
[foo_item] = filter(lambda item: item.label == "foo", table_items)
assert isinstance(foo_item, TableCatalogItem)
assert not foo_item.children
assert not foo_item.loaded
foo_column_items = foo_item.fetch_children()
assert all(isinstance(item, ColumnCatalogItem) for item in foo_column_items)
[database_two_item] = filter(lambda item: item.label == "two", database_items)
assert isinstance(database_two_item, DatabaseCatalogItem)
assert not database_two_item.children
assert not database_two_item.loaded
view_items = database_two_item.fetch_children()
assert all(isinstance(item, ViewCatalogItem) for item in view_items)
[qux_item] = filter(lambda item: item.label == "qux", view_items)
assert isinstance(qux_item, ViewCatalogItem)
assert not qux_item.children
assert not qux_item.loaded
qux_column_items = qux_item.fetch_children()
assert all(isinstance(item, ColumnCatalogItem) for item in qux_column_items)
assert [item.label for item in foo_column_items] == [
item.label for item in qux_column_items
]
# ensure calling fetch_children on cols doesn't raise
children_items = foo_column_items[0].fetch_children()
assert not children_items
[database_three_item] = filter(lambda item: item.label == "three", database_items)
assert isinstance(database_three_item, DatabaseCatalogItem)
assert not database_three_item.children
assert not database_three_item.loaded
three_children = database_three_item.fetch_children()
assert not three_children