Rough prototype of cross-database-joins, refs #283

This is a quick-and-dirty proof of concept.
cross-database-joins
Simon Willison 2018-05-23 21:22:26 -07:00
rodzic bd30c696e1
commit 7a3040f578
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 17E2DEA2588B7F52
4 zmienionych plików z 28 dodań i 5 usunięć

Wyświetl plik

@ -16,7 +16,7 @@
{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}
<form class="sql" action="/{{ database }}-{{ database_hash }}" method="get">
<form class="sql" action="/{{ database }}{% if database_hash %}-{{ database_hash }}{% endif %}" method="get">
<h3>Custom SQL query</h3>
<p><textarea name="sql">select * from {{ tables[0].name|escape_sqlite }}</textarea></p>
<p><input type="submit" value="Run SQL"></p>

Wyświetl plik

@ -23,7 +23,7 @@
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}">{{ database }}</h1>
<form class="sql" action="/{{ database }}-{{ database_hash }}{% if canned_query %}/{{ canned_query }}{% endif %}" method="get">
<form class="sql" action="/{{ database }}{% if database_hash %}-{{ database_hash }}{% endif %}{% if canned_query %}/{{ canned_query }}{% endif %}" method="get">
<h3>Custom SQL query{% if rows %} returning {% if truncated %}more than {% endif %}{{ "{:,}".format(rows|length) }} row{% if rows|length == 1 %}{% else %}s{% endif %}{% endif %}</h3>
{% if editable %}
<p><textarea name="sql">{% if query and query.sql %}{{ query.sql }}{% else %}select * from {{ tables[0].name|escape_sqlite }}{% endif %}</textarea></p>

Wyświetl plik

@ -107,6 +107,8 @@ class BaseView(RenderMixin):
hash = None
else:
name = db_name
if name == "memory":
return "memory", "", None
# Verify the hash
try:
info = databases[name]
@ -143,14 +145,25 @@ class BaseView(RenderMixin):
def sql_operation_in_thread():
conn = getattr(connections, db_name, None)
if not conn:
info = self.ds.inspect()[db_name]
if db_name == "memory":
filename = ":memory:"
else:
info = self.ds.inspect()[db_name]
filename = info["file"]
conn = sqlite3.connect(
"file:{}?immutable=1".format(info["file"]),
"file:{}?immutable=1".format(filename),
uri=True,
check_same_thread=False,
)
self.ds.prepare_connection(conn)
setattr(connections, db_name, conn)
if db_name == "memory":
# Loop through and attach all the other DBs
for dbname, dbinfo in self.ds.inspect().items():
sql2 = 'ATTACH DATABASE "file:{}?immutable=1" AS [{}];'.format(
dbinfo["file"], dbname
)
conn.execute(sql2)
time_limit_ms = self.ds.sql_time_limit_ms
if custom_time_limit and custom_time_limit < self.ds.sql_time_limit_ms:

Wyświetl plik

@ -15,7 +15,17 @@ class DatabaseView(BaseView):
validate_sql_select(sql)
return await self.custom_sql(request, name, hash, sql)
info = self.ds.inspect()[name]
if name == "memory":
info = {"tables": {
"sqlite_master": {
"name": "sqlite_master",
"hidden": False,
"columns": [],
"count": 0,
}
}, "views": []}
else:
info = self.ds.inspect()[name]
metadata = self.ds.metadata.get("databases", {}).get(name, {})
self.ds.update_with_inherited_metadata(metadata)
tables = list(info["tables"].values())