datasette-explain 0.2__tar.gz → 0.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {datasette-explain-0.2 → datasette_explain-0.2.2}/PKG-INFO +21 -29
- {datasette-explain-0.2 → datasette_explain-0.2.2}/README.md +12 -16
- {datasette-explain-0.2 → datasette_explain-0.2.2}/datasette_explain/__init__.py +4 -1
- datasette_explain-0.2.2/pyproject.toml +38 -0
- datasette_explain-0.2.2/pyproject.toml.orig +40 -0
- datasette-explain-0.2/datasette_explain.egg-info/PKG-INFO +0 -58
- datasette-explain-0.2/datasette_explain.egg-info/SOURCES.txt +0 -11
- datasette-explain-0.2/datasette_explain.egg-info/dependency_links.txt +0 -1
- datasette-explain-0.2/datasette_explain.egg-info/entry_points.txt +0 -2
- datasette-explain-0.2/datasette_explain.egg-info/requires.txt +0 -5
- datasette-explain-0.2/datasette_explain.egg-info/top_level.txt +0 -1
- datasette-explain-0.2/setup.cfg +0 -4
- datasette-explain-0.2/setup.py +0 -38
- datasette-explain-0.2/tests/test_explain.py +0 -98
- {datasette-explain-0.2 → datasette_explain-0.2.2}/LICENSE +0 -0
|
@@ -1,22 +1,18 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: datasette-explain
|
|
3
|
-
Version: 0.2
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: Explain SQL queries executed using Datasette
|
|
5
|
-
Home-page: https://github.com/simonw/datasette-explain
|
|
6
5
|
Author: Simon Willison
|
|
7
|
-
License: Apache
|
|
6
|
+
License-Expression: Apache-2.0
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Classifier: Framework :: Datasette
|
|
9
|
+
Requires-Dist: datasette
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Project-URL: Homepage, https://datasette.io/plugins/datasette-explain
|
|
12
|
+
Project-URL: Changelog, https://github.com/simonw/datasette-explain/releases
|
|
8
13
|
Project-URL: Issues, https://github.com/simonw/datasette-explain/issues
|
|
9
14
|
Project-URL: CI, https://github.com/simonw/datasette-explain/actions
|
|
10
|
-
Project-URL: Changelog, https://github.com/simonw/datasette-explain/releases
|
|
11
|
-
Classifier: Framework :: Datasette
|
|
12
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
-
Requires-Python: >=3.7
|
|
14
15
|
Description-Content-Type: text/markdown
|
|
15
|
-
License-File: LICENSE
|
|
16
|
-
Requires-Dist: datasette
|
|
17
|
-
Provides-Extra: test
|
|
18
|
-
Requires-Dist: pytest; extra == "test"
|
|
19
|
-
Requires-Dist: pytest-asyncio; extra == "test"
|
|
20
16
|
|
|
21
17
|
# datasette-explain
|
|
22
18
|
|
|
@@ -30,29 +26,25 @@ Explain SQL queries executed using Datasette
|
|
|
30
26
|
## Installation
|
|
31
27
|
|
|
32
28
|
Install this plugin in the same environment as Datasette.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
This plugin requires a Datasette 1.0 alpha or higher.
|
|
37
|
-
|
|
29
|
+
```bash
|
|
30
|
+
datasette install datasette-explain
|
|
31
|
+
```
|
|
38
32
|
## Usage
|
|
39
33
|
|
|
40
34
|
The plugin adds JavaScript to the query editor page which will constantly update the page with information gained from running EXPLAIN QUERY PLAN queries against the entered SQL.
|
|
41
35
|
|
|
42
36
|
This may result in an error message, or it may show the query plan along with any tables used by the query.
|
|
43
37
|
|
|
44
|
-
##
|
|
38
|
+
## Demo
|
|
45
39
|
|
|
46
|
-
|
|
40
|
+
You can see this plugin in action on [datasette.simonwillison.net](https://datasette.simonwillison.net/simonwillisonblog?sql=select%0D%0A++blog_tag.tag%2C%0D%0A++blog_blogmark.link_title%2C%0D%0A++blog_blogmark.link_url%0D%0Afrom%0D%0A++blog_blogmark_tags%0D%0A++join+blog_tag+on+tag_id+%3D+blog_tag.id%0D%0A++join+blog_blogmark+on+blog_blogmark_tags.blogmark_id+%3D+blog_blogmark.id%0D%0Aorder+by+blog_blogmark.id+desc).
|
|
47
41
|
|
|
48
|
-
|
|
49
|
-
python3 -m venv venv
|
|
50
|
-
source venv/bin/activate
|
|
42
|
+
<img src="https://raw.githubusercontent.com/simonw/datasette-explain/main/datasette-explain-screenshot.jpg" alt="Demo of this plugin - a SQL query shows the explain plan as well as the three tables that were used in the query (their names and columns)" width="832">
|
|
51
43
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
pip install -e '.[test]'
|
|
55
|
-
|
|
56
|
-
To run the tests:
|
|
44
|
+
## Development
|
|
57
45
|
|
|
58
|
-
|
|
46
|
+
To set up this plugin locally, first checkout the code. Then run the tests using [uv](https://docs.astral.sh/uv/):
|
|
47
|
+
```bash
|
|
48
|
+
cd datasette-explain
|
|
49
|
+
uv run pytest
|
|
50
|
+
```
|
|
@@ -10,29 +10,25 @@ Explain SQL queries executed using Datasette
|
|
|
10
10
|
## Installation
|
|
11
11
|
|
|
12
12
|
Install this plugin in the same environment as Datasette.
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
This plugin requires a Datasette 1.0 alpha or higher.
|
|
17
|
-
|
|
13
|
+
```bash
|
|
14
|
+
datasette install datasette-explain
|
|
15
|
+
```
|
|
18
16
|
## Usage
|
|
19
17
|
|
|
20
18
|
The plugin adds JavaScript to the query editor page which will constantly update the page with information gained from running EXPLAIN QUERY PLAN queries against the entered SQL.
|
|
21
19
|
|
|
22
20
|
This may result in an error message, or it may show the query plan along with any tables used by the query.
|
|
23
21
|
|
|
24
|
-
##
|
|
22
|
+
## Demo
|
|
25
23
|
|
|
26
|
-
|
|
24
|
+
You can see this plugin in action on [datasette.simonwillison.net](https://datasette.simonwillison.net/simonwillisonblog?sql=select%0D%0A++blog_tag.tag%2C%0D%0A++blog_blogmark.link_title%2C%0D%0A++blog_blogmark.link_url%0D%0Afrom%0D%0A++blog_blogmark_tags%0D%0A++join+blog_tag+on+tag_id+%3D+blog_tag.id%0D%0A++join+blog_blogmark+on+blog_blogmark_tags.blogmark_id+%3D+blog_blogmark.id%0D%0Aorder+by+blog_blogmark.id+desc).
|
|
27
25
|
|
|
28
|
-
|
|
29
|
-
python3 -m venv venv
|
|
30
|
-
source venv/bin/activate
|
|
26
|
+
<img src="https://raw.githubusercontent.com/simonw/datasette-explain/main/datasette-explain-screenshot.jpg" alt="Demo of this plugin - a SQL query shows the explain plan as well as the three tables that were used in the query (their names and columns)" width="832">
|
|
31
27
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
pip install -e '.[test]'
|
|
35
|
-
|
|
36
|
-
To run the tests:
|
|
28
|
+
## Development
|
|
37
29
|
|
|
38
|
-
|
|
30
|
+
To set up this plugin locally, first checkout the code. Then run the tests using [uv](https://docs.astral.sh/uv/):
|
|
31
|
+
```bash
|
|
32
|
+
cd datasette-explain
|
|
33
|
+
uv run pytest
|
|
34
|
+
```
|
|
@@ -102,13 +102,16 @@ JS = """
|
|
|
102
102
|
}
|
|
103
103
|
let previousSql = '';
|
|
104
104
|
const sqlForm = document.querySelector('form.sql');
|
|
105
|
+
if (!sqlForm) return;
|
|
105
106
|
const div = document.createElement('div');
|
|
106
107
|
div.style.marginTop = '1em';
|
|
107
108
|
div.style.marginBottom = '1em';
|
|
108
109
|
sqlForm.appendChild(div);
|
|
109
110
|
setInterval(() => {
|
|
110
111
|
const formData = Object.fromEntries(new FormData(sqlForm).entries());
|
|
111
|
-
const sql = editor.state.doc.toString()
|
|
112
|
+
const sql = window.editor ? window.editor.state.doc.toString()
|
|
113
|
+
: (document.querySelector('pre#sql-query')?.textContent
|
|
114
|
+
|| formData.sql || '');
|
|
112
115
|
formData.sql = sql;
|
|
113
116
|
const params = new URLSearchParams(formData).toString();
|
|
114
117
|
if (sql !== previousSql) {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "datasette-explain"
|
|
3
|
+
version = "0.2.2"
|
|
4
|
+
description = "Explain SQL queries executed using Datasette"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "Apache-2.0"
|
|
7
|
+
license-files = ["LICENSE"]
|
|
8
|
+
classifiers = ["Framework :: Datasette"]
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = ["datasette"]
|
|
11
|
+
|
|
12
|
+
[[project.authors]]
|
|
13
|
+
name = "Simon Willison"
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Homepage = "https://datasette.io/plugins/datasette-explain"
|
|
17
|
+
Changelog = "https://github.com/simonw/datasette-explain/releases"
|
|
18
|
+
Issues = "https://github.com/simonw/datasette-explain/issues"
|
|
19
|
+
CI = "https://github.com/simonw/datasette-explain/actions"
|
|
20
|
+
|
|
21
|
+
[project.entry-points.datasette]
|
|
22
|
+
explain = "datasette_explain"
|
|
23
|
+
|
|
24
|
+
[dependency-groups]
|
|
25
|
+
dev = [
|
|
26
|
+
"pytest",
|
|
27
|
+
"pytest-asyncio",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[tool.pytest.ini_options]
|
|
31
|
+
asyncio_mode = "strict"
|
|
32
|
+
|
|
33
|
+
[tool.uv.build-backend]
|
|
34
|
+
module-root = ""
|
|
35
|
+
|
|
36
|
+
[build-system]
|
|
37
|
+
requires = ["uv_build>=0.12.9,<0.13.0"]
|
|
38
|
+
build-backend = "uv_build"
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "datasette-explain"
|
|
3
|
+
version = "0.2.2"
|
|
4
|
+
description = "Explain SQL queries executed using Datasette"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [{name = "Simon Willison"}]
|
|
7
|
+
license = "Apache-2.0"
|
|
8
|
+
license-files = ["LICENSE"]
|
|
9
|
+
classifiers = [
|
|
10
|
+
"Framework :: Datasette",
|
|
11
|
+
]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
dependencies = [
|
|
14
|
+
"datasette",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.urls]
|
|
18
|
+
Homepage = "https://datasette.io/plugins/datasette-explain"
|
|
19
|
+
Changelog = "https://github.com/simonw/datasette-explain/releases"
|
|
20
|
+
Issues = "https://github.com/simonw/datasette-explain/issues"
|
|
21
|
+
CI = "https://github.com/simonw/datasette-explain/actions"
|
|
22
|
+
|
|
23
|
+
[project.entry-points.datasette]
|
|
24
|
+
explain = "datasette_explain"
|
|
25
|
+
|
|
26
|
+
[dependency-groups]
|
|
27
|
+
dev = [
|
|
28
|
+
"pytest",
|
|
29
|
+
"pytest-asyncio",
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
asyncio_mode = "strict"
|
|
34
|
+
|
|
35
|
+
[build-system]
|
|
36
|
+
requires = ["uv_build>=0.12.9,<0.13.0"]
|
|
37
|
+
build-backend = "uv_build"
|
|
38
|
+
|
|
39
|
+
[tool.uv.build-backend]
|
|
40
|
+
module-root = ""
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: datasette-explain
|
|
3
|
-
Version: 0.2
|
|
4
|
-
Summary: Explain SQL queries executed using Datasette
|
|
5
|
-
Home-page: https://github.com/simonw/datasette-explain
|
|
6
|
-
Author: Simon Willison
|
|
7
|
-
License: Apache License, Version 2.0
|
|
8
|
-
Project-URL: Issues, https://github.com/simonw/datasette-explain/issues
|
|
9
|
-
Project-URL: CI, https://github.com/simonw/datasette-explain/actions
|
|
10
|
-
Project-URL: Changelog, https://github.com/simonw/datasette-explain/releases
|
|
11
|
-
Classifier: Framework :: Datasette
|
|
12
|
-
Classifier: License :: OSI Approved :: Apache Software License
|
|
13
|
-
Requires-Python: >=3.7
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
License-File: LICENSE
|
|
16
|
-
Requires-Dist: datasette
|
|
17
|
-
Provides-Extra: test
|
|
18
|
-
Requires-Dist: pytest; extra == "test"
|
|
19
|
-
Requires-Dist: pytest-asyncio; extra == "test"
|
|
20
|
-
|
|
21
|
-
# datasette-explain
|
|
22
|
-
|
|
23
|
-
[](https://pypi.org/project/datasette-explain/)
|
|
24
|
-
[](https://github.com/simonw/datasette-explain/releases)
|
|
25
|
-
[](https://github.com/simonw/datasette-explain/actions?query=workflow%3ATest)
|
|
26
|
-
[](https://github.com/simonw/datasette-explain/blob/main/LICENSE)
|
|
27
|
-
|
|
28
|
-
Explain SQL queries executed using Datasette
|
|
29
|
-
|
|
30
|
-
## Installation
|
|
31
|
-
|
|
32
|
-
Install this plugin in the same environment as Datasette.
|
|
33
|
-
|
|
34
|
-
datasette install datasette-explain
|
|
35
|
-
|
|
36
|
-
This plugin requires a Datasette 1.0 alpha or higher.
|
|
37
|
-
|
|
38
|
-
## Usage
|
|
39
|
-
|
|
40
|
-
The plugin adds JavaScript to the query editor page which will constantly update the page with information gained from running EXPLAIN QUERY PLAN queries against the entered SQL.
|
|
41
|
-
|
|
42
|
-
This may result in an error message, or it may show the query plan along with any tables used by the query.
|
|
43
|
-
|
|
44
|
-
## Development
|
|
45
|
-
|
|
46
|
-
To set up this plugin locally, first checkout the code. Then create a new virtual environment:
|
|
47
|
-
|
|
48
|
-
cd datasette-explain
|
|
49
|
-
python3 -m venv venv
|
|
50
|
-
source venv/bin/activate
|
|
51
|
-
|
|
52
|
-
Now install the dependencies and test dependencies:
|
|
53
|
-
|
|
54
|
-
pip install -e '.[test]'
|
|
55
|
-
|
|
56
|
-
To run the tests:
|
|
57
|
-
|
|
58
|
-
pytest
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
LICENSE
|
|
2
|
-
README.md
|
|
3
|
-
setup.py
|
|
4
|
-
datasette_explain/__init__.py
|
|
5
|
-
datasette_explain.egg-info/PKG-INFO
|
|
6
|
-
datasette_explain.egg-info/SOURCES.txt
|
|
7
|
-
datasette_explain.egg-info/dependency_links.txt
|
|
8
|
-
datasette_explain.egg-info/entry_points.txt
|
|
9
|
-
datasette_explain.egg-info/requires.txt
|
|
10
|
-
datasette_explain.egg-info/top_level.txt
|
|
11
|
-
tests/test_explain.py
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
datasette_explain
|
datasette-explain-0.2/setup.cfg
DELETED
datasette-explain-0.2/setup.py
DELETED
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
from setuptools import setup
|
|
2
|
-
import os
|
|
3
|
-
|
|
4
|
-
VERSION = "0.2"
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
def get_long_description():
|
|
8
|
-
with open(
|
|
9
|
-
os.path.join(os.path.dirname(os.path.abspath(__file__)), "README.md"),
|
|
10
|
-
encoding="utf8",
|
|
11
|
-
) as fp:
|
|
12
|
-
return fp.read()
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
setup(
|
|
16
|
-
name="datasette-explain",
|
|
17
|
-
description="Explain SQL queries executed using Datasette",
|
|
18
|
-
long_description=get_long_description(),
|
|
19
|
-
long_description_content_type="text/markdown",
|
|
20
|
-
author="Simon Willison",
|
|
21
|
-
url="https://github.com/simonw/datasette-explain",
|
|
22
|
-
project_urls={
|
|
23
|
-
"Issues": "https://github.com/simonw/datasette-explain/issues",
|
|
24
|
-
"CI": "https://github.com/simonw/datasette-explain/actions",
|
|
25
|
-
"Changelog": "https://github.com/simonw/datasette-explain/releases",
|
|
26
|
-
},
|
|
27
|
-
license="Apache License, Version 2.0",
|
|
28
|
-
classifiers=[
|
|
29
|
-
"Framework :: Datasette",
|
|
30
|
-
"License :: OSI Approved :: Apache Software License",
|
|
31
|
-
],
|
|
32
|
-
version=VERSION,
|
|
33
|
-
packages=["datasette_explain"],
|
|
34
|
-
entry_points={"datasette": ["explain = datasette_explain"]},
|
|
35
|
-
install_requires=["datasette"],
|
|
36
|
-
extras_require={"test": ["pytest", "pytest-asyncio"]},
|
|
37
|
-
python_requires=">=3.7",
|
|
38
|
-
)
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
from datasette.app import Datasette
|
|
2
|
-
import pytest
|
|
3
|
-
import pytest_asyncio
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
@pytest_asyncio.fixture
|
|
7
|
-
async def ds():
|
|
8
|
-
datasette = Datasette(memory=True)
|
|
9
|
-
db = datasette.add_memory_database("test")
|
|
10
|
-
await db.execute_write("create table if not exists t1 (id integer primary key)")
|
|
11
|
-
await db.execute_write("create table if not exists t2 (id integer primary key)")
|
|
12
|
-
return datasette
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
@pytest.mark.asyncio
|
|
16
|
-
@pytest.mark.parametrize(
|
|
17
|
-
"sql,expected",
|
|
18
|
-
(
|
|
19
|
-
(
|
|
20
|
-
"select 1",
|
|
21
|
-
{
|
|
22
|
-
"ok": True,
|
|
23
|
-
"explain_tree": [{"detail": "SCAN CONSTANT ROW", "children": []}],
|
|
24
|
-
"tables": [],
|
|
25
|
-
},
|
|
26
|
-
),
|
|
27
|
-
(
|
|
28
|
-
"select * from t1",
|
|
29
|
-
{
|
|
30
|
-
"ok": True,
|
|
31
|
-
"explain_tree": [{"detail": "SCAN t1", "children": []}],
|
|
32
|
-
"tables": [{"name": "t1", "columns": ["id"]}],
|
|
33
|
-
},
|
|
34
|
-
),
|
|
35
|
-
(
|
|
36
|
-
"select * from t1 where id > :id",
|
|
37
|
-
{
|
|
38
|
-
"ok": True,
|
|
39
|
-
"explain_tree": [
|
|
40
|
-
{
|
|
41
|
-
"detail": "SEARCH t1 USING INTEGER PRIMARY KEY (rowid>?)",
|
|
42
|
-
"children": [],
|
|
43
|
-
}
|
|
44
|
-
],
|
|
45
|
-
"tables": [{"name": "t1", "columns": ["id"]}],
|
|
46
|
-
},
|
|
47
|
-
),
|
|
48
|
-
(
|
|
49
|
-
"select id, (select id from t2 where t2.id = t1.id) from t1",
|
|
50
|
-
{
|
|
51
|
-
"ok": True,
|
|
52
|
-
"explain_tree": [
|
|
53
|
-
{"detail": "SCAN t1", "children": []},
|
|
54
|
-
{
|
|
55
|
-
"detail": "CORRELATED SCALAR SUBQUERY 1",
|
|
56
|
-
"children": [
|
|
57
|
-
{
|
|
58
|
-
"detail": "SEARCH t2 USING INTEGER PRIMARY KEY (rowid=?)",
|
|
59
|
-
"children": [],
|
|
60
|
-
}
|
|
61
|
-
],
|
|
62
|
-
},
|
|
63
|
-
],
|
|
64
|
-
"tables": [
|
|
65
|
-
{"name": "t1", "columns": ["id"]},
|
|
66
|
-
{"name": "t2", "columns": ["id"]},
|
|
67
|
-
],
|
|
68
|
-
},
|
|
69
|
-
),
|
|
70
|
-
(
|
|
71
|
-
"select count(*) from t1 where id > :id",
|
|
72
|
-
{
|
|
73
|
-
"ok": True,
|
|
74
|
-
"explain_tree": [
|
|
75
|
-
{
|
|
76
|
-
"detail": "SEARCH t1 USING INTEGER PRIMARY KEY (rowid>?)",
|
|
77
|
-
"children": [],
|
|
78
|
-
}
|
|
79
|
-
],
|
|
80
|
-
"tables": [{"name": "t1", "columns": ["id"]}],
|
|
81
|
-
},
|
|
82
|
-
),
|
|
83
|
-
(
|
|
84
|
-
"explain select count(*) from t1",
|
|
85
|
-
{
|
|
86
|
-
"ok": True,
|
|
87
|
-
"explain_tree": [],
|
|
88
|
-
"tables": [],
|
|
89
|
-
},
|
|
90
|
-
),
|
|
91
|
-
),
|
|
92
|
-
)
|
|
93
|
-
async def test_explain(ds, sql, expected):
|
|
94
|
-
params = {"sql": sql}
|
|
95
|
-
response = await ds.client.get("/test/-/explain", params=params)
|
|
96
|
-
assert response.status_code == 200
|
|
97
|
-
data = response.json()
|
|
98
|
-
assert data == expected
|
|
File without changes
|