home / github

Menu
  • Search all tables
  • GraphQL API

issue_comments

Table actions
  • GraphQL API for issue_comments

28 rows where author_association = "OWNER" and "updated_at" is on date 2021-12-19 sorted by updated_at descending

✎ View and edit SQL

This data as json, CSV (advanced)

Suggested facets: issue_url, created_at (date), updated_at (date)

issue 9

  • Optimize all those calls to index_list and foreign_key_list 13
  • Documented JavaScript variables on different templates made available for plugins 5
  • Writable canned queries fail to load custom templates 2
  • `sqlite-utils insert --convert` option 2
  • Release Datasette 0.60 2
  • Complete refactor of TableView and table.html template 1
  • Custom pages don't work on windows 1
  • Separate db.execute_write() into three methods 1
  • Make trace() a documented internal API 1

user 1

  • simonw 28

author_association 1

  • OWNER · 28 ✖
id html_url issue_url node_id user created_at updated_at ▲ author_association body reactions issue performed_via_github_app
997486156 https://github.com/simonw/sqlite-utils/issues/356#issuecomment-997486156 https://api.github.com/repos/simonw/sqlite-utils/issues/356 IC_kwDOCGYnMM47dG5M simonw 9599 2021-12-19T23:51:02Z 2021-12-19T23:51:02Z OWNER

This is going to need a --import multi option too.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
`sqlite-utils insert --convert` option 1077431957  
997485361 https://github.com/simonw/sqlite-utils/issues/356#issuecomment-997485361 https://api.github.com/repos/simonw/sqlite-utils/issues/356 IC_kwDOCGYnMM47dGsx simonw 9599 2021-12-19T23:45:30Z 2021-12-19T23:45:30Z OWNER

Really interesting example input for this: https://blog.timac.org/2021/1219-state-of-swift-and-swiftui-ios15/iOS13.txt - see https://blog.timac.org/2021/1219-state-of-swift-and-swiftui-ios15/

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
`sqlite-utils insert --convert` option 1077431957  
997474022 https://github.com/simonw/datasette/issues/1565#issuecomment-997474022 https://api.github.com/repos/simonw/datasette/issues/1565 IC_kwDOBm6k_c47dD7m simonw 9599 2021-12-19T22:36:49Z 2021-12-19T22:37:29Z OWNER

No way with a tagged template literal to pass an extra database name argument, so instead I need a method that returns a callable that can be used for the tagged template literal for a specific database - or the default database.

This could work (bit weird looking though): javascript var rows = await datasette.query("fixtures")`select * from foo`;

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Documented JavaScript variables on different templates made available for plugins 1083657868  
997473856 https://github.com/simonw/datasette/issues/1565#issuecomment-997473856 https://api.github.com/repos/simonw/datasette/issues/1565 IC_kwDOBm6k_c47dD5A simonw 9599 2021-12-19T22:35:20Z 2021-12-19T22:35:20Z OWNER

Quick prototype of that tagged template query function:

``javascript function query(pieces, ...parameters) { var qs = new URLSearchParams(); var sql = pieces[0]; parameters.forEach((param, i) => { sql +=:p${i}${pieces[i + 1]}; qs.append(p${i}`, param); }); qs.append("sql", sql); return qs.toString(); }

var id = 4; console.log(queryselect * from ids where id > ${id}); Outputs: p0=4&sql=select+*+from+ids+where+id+%3E+%3Ap0 ```

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Documented JavaScript variables on different templates made available for plugins 1083657868  
997472639 https://github.com/simonw/datasette/issues/1565#issuecomment-997472639 https://api.github.com/repos/simonw/datasette/issues/1565 IC_kwDOBm6k_c47dDl_ simonw 9599 2021-12-19T22:25:50Z 2021-12-19T22:25:50Z OWNER

Or... javascript rows = await datasette.query`select * from searchable where id > ${id}`; And it knows how to turn that into a parameterized call using tagged template literals.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Documented JavaScript variables on different templates made available for plugins 1083657868  
997472509 https://github.com/simonw/datasette/issues/1565#issuecomment-997472509 https://api.github.com/repos/simonw/datasette/issues/1565 IC_kwDOBm6k_c47dDj9 simonw 9599 2021-12-19T22:24:50Z 2021-12-19T22:24:50Z OWNER

... huh, it could even expose a JavaScript function that can be called to execute a SQL query.

javascript datasette.query("select * from blah").then(...) Maybe it takes an optional second argument that specifies the database - defaulting to the one for the current page.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Documented JavaScript variables on different templates made available for plugins 1083657868  
997472370 https://github.com/simonw/datasette/issues/1565#issuecomment-997472370 https://api.github.com/repos/simonw/datasette/issues/1565 IC_kwDOBm6k_c47dDhy simonw 9599 2021-12-19T22:23:36Z 2021-12-19T22:23:36Z OWNER

This should also expose the JSON API endpoints used to execute SQL against this database.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Documented JavaScript variables on different templates made available for plugins 1083657868  
997472214 https://github.com/simonw/datasette/issues/1518#issuecomment-997472214 https://api.github.com/repos/simonw/datasette/issues/1518 IC_kwDOBm6k_c47dDfW simonw 9599 2021-12-19T22:22:08Z 2021-12-19T22:22:08Z OWNER

I sketched out a chained SQL builder pattern that might be useful for further tidying up this code - though with the new plugin hook I'm less excited about it than I was:

```python class TableQuery: def init(self, table, columns, pks, is_view=False, prev=None): self.table = table self.columns = columns self.pks = pks self.is_view = is_view self.prev = prev

    # These can be changed for different instances in the chain:
    self._where_clauses = None
    self._order_by = None
    self._page_size = None
    self._offset = None
    self._select_columns = None

    self.select_all_columns = '*'
    self.select_specified_columns = '*'

@property
def where_clauses(self):
    wheres = []
    current = self
    while current:
        if current._where_clauses is not None:
            wheres.extend(current._where_clauses)
        current = current.prev
    return list(reversed(wheres))

def where(self, where):
    new_cls = TableQuery(self.table, self.columns, self.pks, self.is_view, self)
    new_cls._where_clauses = [where]
    return new_cls

@classmethod
async def introspect(cls, db, table):
    return cls(
        table,
        columns = await db.table_columns(table),
        pks = await db.primary_keys(table),
        is_view = bool(await db.get_view_definition(table))
    )

@property
def sql_from(self):
    return f"from {self.table}{self.sql_where}"

@property
def sql_where(self):
    if not self.where_clauses:
        return ""
    else:
        return f" where {' and '.join(self.where_clauses)}"

@property
def sql_no_order_no_limit(self):
    return f"select {self.select_all_columns} from {self.table}{self.sql_where}"

@property
def sql(self):
    return f"select {self.select_specified_columns} from {self.table} {self.sql_where}{self._order_by} limit {self._page_size}{self._offset}"

@property
def sql_count(self):
    return f"select count(*) {self.sql_from}"


def __repr__(self):
    return f"<TableQuery sql={self.sql}>"

Usage:python from datasette.app import Datasette ds = Datasette(memory=True, files=["/Users/simon/Dropbox/Development/datasette/fixtures.db"]) db = ds.get_database("fixtures") query = await TableQuery.introspect(db, "facetable") print(query.where("foo = bar").where("baz = 1").sql_count)

'select count(*) from facetable where foo = bar and baz = 1'

```

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Complete refactor of TableView and table.html template 1058072543  
997471672 https://github.com/simonw/datasette/issues/1547#issuecomment-997471672 https://api.github.com/repos/simonw/datasette/issues/1547 IC_kwDOBm6k_c47dDW4 simonw 9599 2021-12-19T22:18:26Z 2021-12-19T22:18:26Z OWNER

I released this in an alpha, so you can try out this fix using:

pip install datasette==0.60a1
{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Writable canned queries fail to load custom templates 1076388044  
997470633 https://github.com/simonw/datasette/issues/1566#issuecomment-997470633 https://api.github.com/repos/simonw/datasette/issues/1566 IC_kwDOBm6k_c47dDGp simonw 9599 2021-12-19T22:12:00Z 2021-12-19T22:12:00Z OWNER

Released another alpha, 0.60a1: https://github.com/simonw/datasette/releases/tag/0.60a1

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Release Datasette 0.60 1083669410  
997462604 https://github.com/simonw/datasette/issues/1545#issuecomment-997462604 https://api.github.com/repos/simonw/datasette/issues/1545 IC_kwDOBm6k_c47dBJM simonw 9599 2021-12-19T21:17:08Z 2021-12-19T21:17:08Z OWNER

Here's the relevant code: https://github.com/simonw/datasette/blob/4094741c2881c2ada3f3f878b532fdaec7914953/datasette/app.py#L1204-L1219

It's using route_path.split("/") which should be OK because that's the incoming request.path path - which I would expect to use / even on Windows. Then it uses os.path.join which should do the right thing.

I need to get myself a proper Windows development environment setup to investigate this one.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Custom pages don't work on windows 1075893249  
997462117 https://github.com/simonw/datasette/issues/1573#issuecomment-997462117 https://api.github.com/repos/simonw/datasette/issues/1573 IC_kwDOBm6k_c47dBBl simonw 9599 2021-12-19T21:13:13Z 2021-12-19T21:13:13Z OWNER

This might also be the impetus I need to bring the https://datasette.io/plugins/datasette-pretty-traces plugin into Datasette core itself.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Make trace() a documented internal API 1084185188  
997460731 https://github.com/simonw/datasette/issues/1547#issuecomment-997460731 https://api.github.com/repos/simonw/datasette/issues/1547 IC_kwDOBm6k_c47dAr7 simonw 9599 2021-12-19T21:02:15Z 2021-12-19T21:02:15Z OWNER

Yes, this is a bug. It looks like the problem is with the if write: branch in this code here: https://github.com/simonw/datasette/blob/5fac26aa221a111d7633f2dd92014641f7c0ade9/datasette/views/database.py#L252-L327

Is missing this bit of code:

https://github.com/simonw/datasette/blob/5fac26aa221a111d7633f2dd92014641f7c0ade9/datasette/views/database.py#L343-L347

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Writable canned queries fail to load custom templates 1076388044  
997460061 https://github.com/simonw/datasette/issues/1570#issuecomment-997460061 https://api.github.com/repos/simonw/datasette/issues/1570 IC_kwDOBm6k_c47dAhd simonw 9599 2021-12-19T20:56:54Z 2021-12-19T20:56:54Z OWNER

Documentation: https://docs.datasette.io/en/latest/internals.html#await-db-execute-write-sql-params-none-block-false

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Separate db.execute_write() into three methods 1083921371  
997459958 https://github.com/simonw/datasette/issues/1555#issuecomment-997459958 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47dAf2 simonw 9599 2021-12-19T20:55:59Z 2021-12-19T20:55:59Z OWNER

Closing this issue because I've optimized this a whole bunch, and it's definitely good enough for the moment.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997325189 https://github.com/simonw/datasette/issues/1555#issuecomment-997325189 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cfmF simonw 9599 2021-12-19T03:55:01Z 2021-12-19T20:54:51Z OWNER

It's a bit annoying that the queries no longer show up in the trace at all now, thanks to running in .execute_fn(). I wonder if there's something smart I can do about that - maybe have trace() record that function with a traceback even though it doesn't have the executed SQL string?

5fac26aa221a111d7633f2dd92014641f7c0ade9 has the same problem.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997459637 https://github.com/simonw/datasette/issues/1555#issuecomment-997459637 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47dAa1 simonw 9599 2021-12-19T20:53:46Z 2021-12-19T20:53:46Z OWNER

Using #1571 showed me that the DELETE FROM columns/foreign_keys/indexes WHERE database_name = ? and table_name = ? queries were running way more times than I expected. I came up with a new optimization that just does DELETE FROM columns/foreign_keys/indexes WHERE database_name = ? instead.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997457790 https://github.com/simonw/datasette/issues/1566#issuecomment-997457790 https://api.github.com/repos/simonw/datasette/issues/1566 IC_kwDOBm6k_c47c_9- simonw 9599 2021-12-19T20:40:50Z 2021-12-19T20:40:57Z OWNER

Also release new version of datasette-pretty-traces with this feature: - https://github.com/simonw/datasette-pretty-traces/issues/7

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Release Datasette 0.60 1083669410  
997342494 https://github.com/simonw/datasette/issues/1555#issuecomment-997342494 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cj0e simonw 9599 2021-12-19T07:22:04Z 2021-12-19T07:22:04Z OWNER

Another option would be to provide an abstraction that makes it easier to run a group of SQL queries in the same thread at the same time, and have them traced correctly.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997324666 https://github.com/simonw/datasette/issues/1555#issuecomment-997324666 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cfd6 simonw 9599 2021-12-19T03:47:51Z 2021-12-19T03:48:09Z OWNER

Here's a hacked together prototype of running all of that stuff inside a single function passed to .execute_fn():

```diff diff --git a/datasette/utils/internal_db.py b/datasette/utils/internal_db.py index 95055d8..58f9982 100644 --- a/datasette/utils/internal_db.py +++ b/datasette/utils/internal_db.py @@ -1,4 +1,5 @@ import textwrap +from datasette.utils import table_column_details

async def init_internal_db(db): @@ -70,49 +71,70 @@ async def populate_schema_tables(internal_db, db): "DELETE FROM tables WHERE database_name = ?", [database_name], block=True ) tables = (await db.execute("select * from sqlite_master WHERE type = 'table'")).rows - tables_to_insert = [] - columns_to_delete = [] - columns_to_insert = [] - foreign_keys_to_delete = [] - foreign_keys_to_insert = [] - indexes_to_delete = [] - indexes_to_insert = []

  • for table in tables:
  • table_name = table["name"]
  • tables_to_insert.append(
  • (database_name, table_name, table["rootpage"], table["sql"])
  • )
  • columns_to_delete.append((database_name, table_name))
  • columns = await db.table_column_details(table_name)
  • columns_to_insert.extend(
  • {
  • **{"database_name": database_name, "table_name": table_name},
  • **column._asdict(),
  • }
  • for column in columns
  • )
  • foreign_keys_to_delete.append((database_name, table_name))
  • foreign_keys = (
  • await db.execute(f"PRAGMA foreign_key_list([{table_name}])")
  • ).rows
  • foreign_keys_to_insert.extend(
  • {
  • **{"database_name": database_name, "table_name": table_name},
  • **dict(foreign_key),
  • }
  • for foreign_key in foreign_keys
  • )
  • indexes_to_delete.append((database_name, table_name))
  • indexes = (await db.execute(f"PRAGMA index_list([{table_name}])")).rows
  • indexes_to_insert.extend(
  • {
  • **{"database_name": database_name, "table_name": table_name},
  • **dict(index),
  • }
  • for index in indexes
  • def collect_info(conn):
  • tables_to_insert = []
  • columns_to_delete = []
  • columns_to_insert = []
  • foreign_keys_to_delete = []
  • foreign_keys_to_insert = []
  • indexes_to_delete = []
  • indexes_to_insert = [] +
  • for table in tables:
  • table_name = table["name"]
  • tables_to_insert.append(
  • (database_name, table_name, table["rootpage"], table["sql"])
  • )
  • columns_to_delete.append((database_name, table_name))
  • columns = table_column_details(conn, table_name)
  • columns_to_insert.extend(
  • {
  • **{"database_name": database_name, "table_name": table_name},
  • **column._asdict(),
  • }
  • for column in columns
  • )
  • foreign_keys_to_delete.append((database_name, table_name))
  • foreign_keys = conn.execute(
  • f"PRAGMA foreign_key_list([{table_name}])"
  • ).fetchall()
  • foreign_keys_to_insert.extend(
  • {
  • **{"database_name": database_name, "table_name": table_name},
  • **dict(foreign_key),
  • }
  • for foreign_key in foreign_keys
  • )
  • indexes_to_delete.append((database_name, table_name))
  • indexes = conn.execute(f"PRAGMA index_list([{table_name}])").fetchall()
  • indexes_to_insert.extend(
  • {
  • **{"database_name": database_name, "table_name": table_name},
  • **dict(index),
  • }
  • for index in indexes
  • )
  • return (
  • tables_to_insert,
  • columns_to_delete,
  • columns_to_insert,
  • foreign_keys_to_delete,
  • foreign_keys_to_insert,
  • indexes_to_delete,
  • indexes_to_insert, )

  • (

  • tables_to_insert,
  • columns_to_delete,
  • columns_to_insert,
  • foreign_keys_to_delete,
  • foreign_keys_to_insert,
  • indexes_to_delete,
  • indexes_to_insert,
  • ) = await db.execute_fn(collect_info) + await internal_db.execute_write_many( """ INSERT INTO tables (database_name, table_name, rootpage, sql) ``` First impressions: it looks like this helps a lot - as far as I can tell this is now taking around 21ms to get to the point at which all of those internal databases have been populated, where previously it took more than 180ms.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997324156 https://github.com/simonw/datasette/issues/1555#issuecomment-997324156 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cfV8 simonw 9599 2021-12-19T03:40:05Z 2021-12-19T03:40:05Z OWNER

Using the prototype of this: - https://github.com/simonw/datasette-pretty-traces/issues/5

I'm seeing about 180ms spent running all of these queries on startup!

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997321767 https://github.com/simonw/datasette/issues/1555#issuecomment-997321767 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cewn simonw 9599 2021-12-19T03:10:58Z 2021-12-19T03:10:58Z OWNER

I wonder how much overhead there is switching between the async event loop main code and the thread that runs the SQL queries.

Would there be a performance boost if I gathered all of the column/index information in a single function run on the thread using db.execute_fn() I wonder? It would eliminate a bunch of switching between threads.

Would be great to understand how much of an impact that would have.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997321653 https://github.com/simonw/datasette/issues/1555#issuecomment-997321653 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47ceu1 simonw 9599 2021-12-19T03:09:43Z 2021-12-19T03:09:43Z OWNER

On that same documentation page I just spotted this:

This feature is experimental and is subject to change. Further documentation will become available if and when the table-valued functions for PRAGMAs feature becomes officially supported.

This makes me nervous to rely on pragma function optimizations in Datasette itself.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997321477 https://github.com/simonw/datasette/issues/1555#issuecomment-997321477 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cesF simonw 9599 2021-12-19T03:07:33Z 2021-12-19T03:07:33Z OWNER

If I want to continue supporting SQLite prior to 3.16.0 (2017-01-02) I'll need this optimization to only kick in with versions that support table-valued PRAGMA functions, while keeping the old PRAGMA foreign_key_list(table) stuff working for those older versions.

That's feasible, but it's a bit more work - and I need to make sure I have robust testing in place for SQLite 3.15.0.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997321327 https://github.com/simonw/datasette/issues/1555#issuecomment-997321327 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cepv simonw 9599 2021-12-19T03:05:39Z 2021-12-19T03:05:44Z OWNER

This caught me out once before in: - https://github.com/simonw/datasette/issues/1276

Turns out Glitch was running SQLite 3.11.0 from 2016-02-15.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997321217 https://github.com/simonw/datasette/issues/1555#issuecomment-997321217 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47ceoB simonw 9599 2021-12-19T03:04:16Z 2021-12-19T03:04:16Z OWNER

One thing to watch out for though, from https://sqlite.org/pragma.html#pragfunc

The table-valued functions for PRAGMA feature was added in SQLite version 3.16.0 (2017-01-02). Prior versions of SQLite cannot use this feature.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997321115 https://github.com/simonw/datasette/issues/1555#issuecomment-997321115 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47cemb simonw 9599 2021-12-19T03:03:12Z 2021-12-19T03:03:12Z OWNER

Table columns is a bit harder, because table_xinfo is only in SQLite 3.26.0 or higher: https://github.com/simonw/datasette/blob/d637ed46762fdbbd8e32b86f258cd9a53c1cfdc7/datasette/utils/init.py#L565-L581

So if that function is available: https://latest.datasette.io/fixtures?sql=SELECT%0D%0A++sqlite_master.name%2C%0D%0A++table_xinfo.*%0D%0AFROM%0D%0A++sqlite_master%2C%0D%0A++pragma_table_xinfo%28sqlite_master.name%29+AS+table_xinfo%0D%0AWHERE%0D%0A++sqlite_master.type+%3D+%27table%27

sql SELECT sqlite_master.name, table_xinfo.* FROM sqlite_master, pragma_table_xinfo(sqlite_master.name) AS table_xinfo WHERE sqlite_master.type = 'table' And otherwise, using table_info: https://latest.datasette.io/fixtures?sql=SELECT%0D%0A++sqlite_master.name%2C%0D%0A++table_info.*%2C%0D%0A++0+as+hidden%0D%0AFROM%0D%0A++sqlite_master%2C%0D%0A++pragma_table_info%28sqlite_master.name%29+AS+table_info%0D%0AWHERE%0D%0A++sqlite_master.type+%3D+%27table%27

sql SELECT sqlite_master.name, table_info.*, 0 as hidden FROM sqlite_master, pragma_table_info(sqlite_master.name) AS table_info WHERE sqlite_master.type = 'table'

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  
997320824 https://github.com/simonw/datasette/issues/1555#issuecomment-997320824 https://api.github.com/repos/simonw/datasette/issues/1555 IC_kwDOBm6k_c47ceh4 simonw 9599 2021-12-19T02:59:57Z 2021-12-19T03:00:44Z OWNER

To list all indexes: https://latest.datasette.io/fixtures?sql=SELECT%0D%0A++sqlite_master.name%2C%0D%0A++index_list.*%0D%0AFROM%0D%0A++sqlite_master%2C%0D%0A++pragma_index_list%28sqlite_master.name%29+AS+index_list%0D%0AWHERE%0D%0A++sqlite_master.type+%3D+%27table%27

sql SELECT sqlite_master.name, index_list.* FROM sqlite_master, pragma_index_list(sqlite_master.name) AS index_list WHERE sqlite_master.type = 'table'

Foreign keys: https://latest.datasette.io/fixtures?sql=SELECT%0D%0A++sqlite_master.name%2C%0D%0A++foreign_key_list.*%0D%0AFROM%0D%0A++sqlite_master%2C%0D%0A++pragma_foreign_key_list%28sqlite_master.name%29+AS+foreign_key_list%0D%0AWHERE%0D%0A++sqlite_master.type+%3D+%27table%27

sql SELECT sqlite_master.name, foreign_key_list.* FROM sqlite_master, pragma_foreign_key_list(sqlite_master.name) AS foreign_key_list WHERE sqlite_master.type = 'table'

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Optimize all those calls to index_list and foreign_key_list 1079149656  

Advanced export

JSON shape: default, array, newline-delimited, object

CSV options:

CREATE TABLE [issue_comments] (
   [html_url] TEXT,
   [issue_url] TEXT,
   [id] INTEGER PRIMARY KEY,
   [node_id] TEXT,
   [user] INTEGER REFERENCES [users]([id]),
   [created_at] TEXT,
   [updated_at] TEXT,
   [author_association] TEXT,
   [body] TEXT,
   [reactions] TEXT,
   [issue] INTEGER REFERENCES [issues]([id])
, [performed_via_github_app] TEXT);
CREATE INDEX [idx_issue_comments_issue]
                ON [issue_comments] ([issue]);
CREATE INDEX [idx_issue_comments_user]
                ON [issue_comments] ([user]);
Powered by Datasette · Queries took 547.555ms · About: github-to-sqlite