home / github

Menu
  • Search all tables
  • GraphQL API

issue_comments

Table actions
  • GraphQL API for issue_comments

38 rows where "updated_at" is on date 2022-11-16 and user = 9599 sorted by updated_at descending

✖
✖
✖

✎ View and edit SQL

This data as json, CSV (advanced)

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

issue 6

  • Upgrade to CodeMirror 6, add SQL autocomplete 26
  • Autocomplete text entry for filter values that correspond to facets 4
  • mypy failures in CI 3
  • Serve schema JSON to the SQL editor to enable autocomplete 3
  • Update a single record in an existing table 1
  • Extract logic for resolving a URL to a database / table / row 1

user 1

  • simonw · 38 ✖

author_association 1

  • OWNER 38
id html_url issue_url node_id user created_at updated_at ▲ author_association body reactions issue performed_via_github_app
1317840727 https://github.com/simonw/datasette/issues/1897#issuecomment-1317840727 https://api.github.com/repos/simonw/datasette/issues/1897 IC_kwDOBm6k_c5OjKdX simonw 9599 2022-11-16T23:57:52Z 2022-11-16T23:57:52Z OWNER

In terms of permissions: if you have execute-sql permission for a database then it's OK for you to see the table columns for that database.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Serve schema JSON to the SQL editor to enable autocomplete 1452457263  
1317839781 https://github.com/simonw/datasette/issues/1897#issuecomment-1317839781 https://api.github.com/repos/simonw/datasette/issues/1897 IC_kwDOBm6k_c5OjKOl simonw 9599 2022-11-16T23:56:47Z 2022-11-16T23:56:47Z OWNER

I'm going to call this table_columns in the template context (because schema might mean CREATE TABLE ....

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Serve schema JSON to the SQL editor to enable autocomplete 1452457263  
1317838892 https://github.com/simonw/datasette/issues/1897#issuecomment-1317838892 https://api.github.com/repos/simonw/datasette/issues/1897 IC_kwDOBm6k_c5OjKAs simonw 9599 2022-11-16T23:55:42Z 2022-11-16T23:55:42Z OWNER

Here's where the schema is hard-coded at the moment: https://github.com/simonw/datasette/blob/00e233d7a7f6443cb95fb5227c23580c48551cad/datasette/templates/_codemirror_foot.html#L2-L7

I figured out how to extract that data from the _internal table in this comment: https://github.com/simonw/datasette/pull/1893#issuecomment-1317475720

Although that used JSON functions which may (in a real edge-case) not be available in the version of SQLite that Datasette is running on, so probably going to use a regular SQL query and then assemble the JSON separately.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Serve schema JSON to the SQL editor to enable autocomplete 1452457263  
1317837416 https://github.com/simonw/datasette/pull/1893#issuecomment-1317837416 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OjJpo simonw 9599 2022-11-16T23:54:02Z 2022-11-16T23:54:02Z OWNER

I'm going to tackle #1897 in the next few minutes.

Tests failed due to Prettier check, just pushed a fix so it would ignore .bundle.js too.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317831555 https://github.com/simonw/datasette/pull/1893#issuecomment-1317831555 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OjIOD simonw 9599 2022-11-16T23:47:13Z 2022-11-16T23:47:13Z OWNER

I'll open a follow-up issue to fix the schema.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317831425 https://github.com/simonw/datasette/pull/1893#issuecomment-1317831425 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OjIMB simonw 9599 2022-11-16T23:47:05Z 2022-11-16T23:47:05Z OWNER

OK, let's do it! Thanks so much for this.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317829214 https://github.com/simonw/datasette/pull/1893#issuecomment-1317829214 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OjHpe simonw 9599 2022-11-16T23:44:36Z 2022-11-16T23:44:36Z OWNER

Deployed that to https://datasette-pr-1893.vercel.app/fixtures - looks good to me!

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317797044 https://github.com/simonw/datasette/pull/1893#issuecomment-1317797044 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5Oi_y0 simonw 9599 2022-11-16T23:08:34Z 2022-11-16T23:08:34Z OWNER

I can push up a commit that uses the static fixtures schema for testing, but given that the query used to generate it is authed we would still need some work to make that work on live data, right?

Yeah, push that up. I'm happy to wire in the query right after we land this.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317757112 https://github.com/simonw/datasette/issues/1896#issuecomment-1317757112 https://api.github.com/repos/simonw/datasette/issues/1896 IC_kwDOBm6k_c5Oi2C4 simonw 9599 2022-11-16T22:26:52Z 2022-11-16T22:33:13Z OWNER

Some ideas from walking the dog:

Challenge: standard URL routing of request to database/table/row

Standardize on the named components of the URL patterns - database, table, pks

Async function that takes the request and the Datasette instance and returns a Resolved instance with: .level - database or table or row (better name?) .database - the name of the database .db - the database object .table - the name of the table (or view) .is_view perhaps? .pk_values if it's a row Should this attempt to resolve names queries too? ``` .where_sql - the where fragment you use .where_params - accompanying dictionary

await datasette.resolve_request(request) Or even better three methods:python datasette.resolve_database(request) datasette.resolve_table(request) datasette.resolve_row(request) ``` These can be typed correctly

Methods raise NotFound if not found

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Extract logic for resolving a URL to a database / table / row 1452364777  
1317755263 https://github.com/simonw/datasette/issues/1863#issuecomment-1317755263 https://api.github.com/repos/simonw/datasette/issues/1863 IC_kwDOBm6k_c5Oi1l_ simonw 9599 2022-11-16T22:24:59Z 2022-11-16T22:24:59Z OWNER

In trying to write this I realize that there's a lot of duplicated code with delete row, specifically around resolving the incoming URL into a row (or a database or a table).

Since this is so common, I think it's worth extracting the logic out first.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Update a single record in an existing table 1425029242  
1317746206 https://github.com/simonw/datasette/pull/1893#issuecomment-1317746206 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OizYe simonw 9599 2022-11-16T22:17:24Z 2022-11-16T22:17:24Z OWNER

Deployed 0a649e8f78c23e8db6869442eeb0dfe36a5443da: https://datasette-pr-1893.vercel.app/fixtures

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317744563 https://github.com/simonw/datasette/pull/1893#issuecomment-1317744563 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5Oiy-z simonw 9599 2022-11-16T22:16:03Z 2022-11-16T22:16:03Z OWNER

Honestly I'm not too bothered if table names with weird characters don't work correctly here - I care about those in the Datasette fixtures.db database because Datasette aims to support ANY valid SQLite database, so I need stuff in the test suite that includes weird edge cases like this. But I would hope very few people actually create tables with spaces in their names, so it's not a huge concern to me if autocompletion doesn't work properly for those.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317475720 https://github.com/simonw/datasette/pull/1893#issuecomment-1317475720 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OhxWI simonw 9599 2022-11-16T18:25:16Z 2022-11-16T18:25:16Z OWNER

Here's a query that returns the exact JSON we need to pass to the schema:

https://latest.datasette.io/_internal?sql=with+inner+as+%28%0D%0A++select%0D%0A++++table_name%2C%0D%0A++++json_group_array%28name%29+as+table_columns%0D%0A++from%0D%0A++++columns%0D%0A++where%0D%0A++++database_name+%3D+%3Adatabase%0D%0A++group+by%0D%0A++++table_name%0D%0A%29%0D%0Aselect%0D%0A++json_group_object%28table_name%2C+table_columns%29%0D%0Afrom%0D%0A++inner&database=fixtures

sql with inner as ( select table_name, json_group_array(name) as table_columns from columns where database_name = :database group by table_name ) select json_group_object(table_name, table_columns) from inner Returns (after pretty-printing): json { "123_starts_with_digits": [ "content" ], "Table With Space In Name": [ "content", "pk" ], "attraction_characteristic": [ "name", "pk" ], "binary_data": [ "data" ], "complex_foreign_keys": [ "f1", "f2", "f3", "pk" ], "compound_primary_key": [ "content", "pk1", "pk2" ], "compound_three_primary_keys": [ "content", "pk1", "pk2", "pk3" ], "custom_foreign_key_label": [ "foreign_key_with_custom_label", "pk" ], "facet_cities": [ "id", "name" ], "facetable": [ "_city_id", "_neighborhood", "complex_array", "created", "distinct_some_null", "n", "on_earth", "pk", "planet_int", "state", "tags" ], "foreign_key_references": [ "foreign_key_compound_pk1", "foreign_key_compound_pk2", "foreign_key_with_blank_label", "foreign_key_with_label", "foreign_key_with_no_label", "pk" ], "infinity": [ "value" ], "no_primary_key": [ "a", "b", "c", "content" ], "primary_key_multiple_columns": [ "content", "content2", "id" ], "primary_key_multiple_columns_explicit_label": [ "content", "content2", "id" ], "roadside_attraction_characteristics": [ "attraction_id", "characteristic_id" ], "roadside_attractions": [ "address", "latitude", "longitude", "name", "pk", "url" ], "searchable": [ "name with . and spaces", "pk", "text1", "text2" ], "searchable_fts": [ "__langid", "docid", "name with . and spaces", "searchable_fts", "text1", "text2" ], "searchable_fts_docsize": [ "docid", "size" ], "searchable_fts_segdir": [ "end_block", "idx", "leaves_end_block", "level", "root", "start_block" ], "searchable_fts_segments": [ "block", "blockid" ], "searchable_fts_stat": [ "id", "value" ], "searchable_tags": [ "searchable_id", "tag" ], "select": [ "and", "group", "having", "json" ], "simple_primary_key": [ "content", "id" ], "sortable": [ "content", "pk1", "pk2", "sortable", "sortable_with_nulls", "sortable_with_nulls_2", "text" ], "table/with/slashes.csv": [ "content", "pk" ], "tags": [ "tag" ], "units": [ "distance", "frequency", "pk" ] }

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317465874 https://github.com/simonw/datasette/pull/1893#issuecomment-1317465874 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5Ohu8S simonw 9599 2022-11-16T18:21:17Z 2022-11-16T18:21:54Z OWNER

I was worrying about the server-side overhead of collecting together all of the tables and column names for databases that might have hundreds of tables... but then I remember that I built the _internal table precisely for this kind of thing - so gathering all of that data should still only be a single SQL query against an in-memory database.

https://latest.datasette.io/login-as-root and then visit this page for an example query: https://latest.datasette.io/_internal?sql=select%0D%0A++database_name%2C%0D%0A++table_name%2C%0D%0A++json_group_array%28name%29%0D%0Afrom%0D%0A++columns%0D%0Awhere%0D%0A++database_name+%21%3D+%27_internal%27%0D%0Agroup+by%0D%0A++database_name%2C%0D%0A++table_name

sql select database_name, table_name, json_group_array(name) from columns where database_name != '_internal' group by database_name, table_name

database_name | table_name | json_group_array(name) -- | -- | -- extra_database | searchable | ["pk","text1","text2"] extra_database | searchable_fts | ["__langid","content","docid","searchable_fts","text1","text2"] extra_database | searchable_fts_content | ["c0text1","c1text2","c2content","docid"] extra_database | searchable_fts_segdir | ["end_block","idx","leaves_end_block","level","root","start_block"] extra_database | searchable_fts_segments | ["block","blockid"] fixtures | 123_starts_with_digits | ["content"] fixtures | Table With Space In Name | ["content","pk"] fixtures | attraction_characteristic | ["name","pk"] fixtures | binary_data | ["data"] fixtures | complex_foreign_keys | ["f1","f2","f3","pk"] fixtures | compound_primary_key | ["content","pk1","pk2"]

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317456909 https://github.com/simonw/datasette/pull/1893#issuecomment-1317456909 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OhswN simonw 9599 2022-11-16T18:17:39Z 2022-11-16T18:17:39Z OWNER

Tiny feature request (since you're in this code already) - I keep hitting Command+Enter on my macOS keyboard to submit the query, but the correct shortcut is Shift+Enter. Would be great if both worked!

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317452541 https://github.com/simonw/datasette/pull/1893#issuecomment-1317452541 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5Ohrr9 simonw 9599 2022-11-16T18:15:52Z 2022-11-16T18:15:52Z OWNER

Deployed latest copy with: datasette publish vercel fixtures.db \ --project datasette-pr-1893 \ --about 'PR 1893' \ --about_url https://github.com/simonw/datasette/pull/1893 \ --scope datasette \ --branch eccb1c6c781d69d8ec3c542ef65c78a4a0927a7c https://datasette-pr-1893.vercel.app/fixtures

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1317449610 https://github.com/simonw/datasette/pull/1893#issuecomment-1317449610 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5Ohq-K simonw 9599 2022-11-16T18:14:28Z 2022-11-16T18:14:28Z OWNER

I'm thinking of also adding count to the list since that's a common thing people would want to autocomplete. I notice BQ console highlights count in the same manner as other keywords like select as well.

Huh, yeah we should definitely have count - surprised it's not on the list on https://www.sqlite.org/lang_keywords.html which is why we didn't get it from the GPT-3 generated schema.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316530539 https://github.com/simonw/sqlite-utils/issues/512#issuecomment-1316530539 https://api.github.com/repos/simonw/sqlite-utils/issues/512 IC_kwDOCGYnMM5OeKlr simonw 9599 2022-11-16T07:49:50Z 2022-11-16T07:49:50Z OWNER

Tests passed.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
mypy failures in CI 1450952393  
1316447182 https://github.com/simonw/sqlite-utils/issues/512#issuecomment-1316447182 https://api.github.com/repos/simonw/sqlite-utils/issues/512 IC_kwDOCGYnMM5Od2PO simonw 9599 2022-11-16T06:32:31Z 2022-11-16T06:32:31Z OWNER

Test failed again: https://github.com/simonw/sqlite-utils/actions/runs/3476950474/jobs/5812663096

E: Failed to fetch http://azure.archive.ubuntu.com/ubuntu/pool/universe/s/spatialite/libsqlite3-mod-spatialite_4.3.0a-6build1_amd64.deb Unable to connect to azure.archive.ubuntu.com:http:

That looks like an intermittent error. I'll try running it again in the morning.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
mypy failures in CI 1450952393  
1316437748 https://github.com/simonw/sqlite-utils/issues/512#issuecomment-1316437748 https://api.github.com/repos/simonw/sqlite-utils/issues/512 IC_kwDOCGYnMM5Odz70 simonw 9599 2022-11-16T06:24:31Z 2022-11-16T06:24:31Z OWNER

sqlite-utils % pipx run no_implicit_optional . Calculating full-repo metadata... Executing codemod... 11.43s 98% complete, 0.24s estimated for 5 files to go... Then: Finished codemodding 239 files! - Transformed 239 files successfully. - Skipped 0 files. - Failed to codemod 0 files. - 0 warnings were generated. Here's the diff: ```diff diff --git a/sqlite_utils/db.py b/sqlite_utils/db.py index a06f4b7..e819d17 100644 --- a/sqlite_utils/db.py +++ b/sqlite_utils/db.py @@ -297,12 +297,12 @@ class Database:

 def __init__(
     self,
  • filename_or_conn: Union[str, pathlib.Path, sqlite3.Connection] = None,
  • filename_or_conn: Optional[Union[str, pathlib.Path, sqlite3.Connection]] = None, memory: bool = False,
  • memory_name: str = None,
  • memory_name: Optional[str] = None, recreate: bool = False, recursive_triggers: bool = True,
  • tracer: Callable = None,
  • tracer: Optional[Callable] = None, use_counts_table: bool = False, ): assert (filename_or_conn is not None and (not memory and not memory_name)) or ( @@ -341,7 +341,7 @@ class Database: self.conn.close()

    @contextlib.contextmanager - def tracer(self, tracer: Callable = None): + def tracer(self, tracer: Optional[Callable] = None): """ Context manager to temporarily set a tracer function - all executed SQL queries will be passed to this. @@ -378,7 +378,7 @@ class Database:

    def register_function( self, - fn: Callable = None, + fn: Optional[Callable] = None, deterministic: bool = False, replace: bool = False, name: Optional[str] = None, @@ -879,7 +879,7 @@ class Database: pk: Optional[Any] = None, foreign_keys: Optional[ForeignKeysType] = None, column_order: Optional[List[str]] = None, - not_null: Iterable[str] = None, + not_null: Optional[Iterable[str]] = None, defaults: Optional[Dict[str, Any]] = None, hash_id: Optional[str] = None, hash_id_columns: Optional[Iterable[str]] = None, @@ -1129,7 +1129,7 @@ class Database: sql += " [{}]".format(name) self.execute(sql)

  • def init_spatialite(self, path: str = None) -> bool:

  • def init_spatialite(self, path: Optional[str] = None) -> bool: """ The init_spatialite method will load and initialize the SpatiaLite extension. The path argument should be an absolute path to the compiled extension, which @@ -1182,7 +1182,7 @@ class Queryable:

    def count_where( self, - where: str = None, + where: Optional[str] = None, where_args: Optional[Union[Iterable, dict]] = None, ) -> int: """ @@ -1213,12 +1213,12 @@ class Queryable:

    def rows_where( self, - where: str = None, + where: Optional[str] = None, where_args: Optional[Union[Iterable, dict]] = None, - order_by: str = None, + order_by: Optional[str] = None, select: str = "*", - limit: int = None, - offset: int = None, + limit: Optional[int] = None, + offset: Optional[int] = None, ) -> Generator[dict, None, None]: """ Iterate over every row in this table or view that matches the specified where clause. @@ -1251,11 +1251,11 @@ class Queryable:

    def pks_and_rows_where( self, - where: str = None, + where: Optional[str] = None, where_args: Optional[Union[Iterable, dict]] = None, - order_by: str = None, - limit: int = None, - offset: int = None, + order_by: Optional[str] = None, + limit: Optional[int] = None, + offset: Optional[int] = None, ) -> Generator[Tuple[Any, Dict], None, None]: """ Like .rows_where() but returns (pk, row) pairs - pk can be a single value or tuple. @@ -1345,7 +1345,7 @@ class Table(Queryable): pk: Optional[Any] = None, foreign_keys: Optional[ForeignKeysType] = None, column_order: Optional[List[str]] = None, - not_null: Iterable[str] = None, + not_null: Optional[Iterable[str]] = None, defaults: Optional[Dict[str, Any]] = None, batch_size: int = 100, hash_id: Optional[str] = None, @@ -1545,7 +1545,7 @@ class Table(Queryable): pk: Optional[Any] = None, foreign_keys: Optional[ForeignKeysType] = None, column_order: Optional[List[str]] = None, - not_null: Iterable[str] = None, + not_null: Optional[Iterable[str]] = None, defaults: Optional[Dict[str, Any]] = None, hash_id: Optional[str] = None, hash_id_columns: Optional[Iterable[str]] = None, @@ -2464,7 +2464,7 @@ class Table(Queryable): columns: Optional[Iterable[str]] = None, limit: Optional[int] = None, offset: Optional[int] = None, - where: str = None, + where: Optional[str] = None, where_args: Optional[Union[Iterable, dict]] = None, quote: bool = False, ) -> Generator[dict, None, None]: @@ -2527,7 +2527,7 @@ class Table(Queryable):

    def delete_where( self, - where: str = None, + where: Optional[str] = None, where_args: Optional[Union[Iterable, dict]] = None, analyze: bool = False, ) -> "Table": ```

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
mypy failures in CI 1450952393  
1316412234 https://github.com/simonw/datasette/pull/1893#issuecomment-1316412234 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdttK simonw 9599 2022-11-16T06:00:39Z 2022-11-16T06:01:36Z OWNER

Should note though that this is a classic example of GPT-3 making stuff up in places.

current: Returns the current date, time, or timestamp

select current throws an error for me: https://latest.datasette.io/_memory?sql=select+current

select current_date, current_time, current_timestamp works though: https://latest.datasette.io/_memory?sql=select+current_date%2C+current_time%2C+current_timestamp

So let's drop current from the list. I'm OK with it though, I think it's likely good enough for the first attempt at this.

We should drop temp and temporary too.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316401895 https://github.com/simonw/datasette/pull/1893#issuecomment-1316401895 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdrLn simonw 9599 2022-11-16T05:50:40Z 2022-11-16T05:50:40Z OWNER

So I think our dialect (at least to start with) should be:

keywords: "and as asc between by case cast current current_date current_time current_timestamp desc distinct each else escape except exists explain filter first for from full generated group having if in index inner intersect into isnull join last left like limit not null or order outer over pragma primary query raise range regexp right rollback row select set table temp temporary then to union unique using values view virtual when where", // https://www.sqlite.org/datatype3.html types: "null integer real text blob", builtin: "" I left builtin blank here because I don't think we need any of those things at all.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316400688 https://github.com/simonw/datasette/pull/1893#issuecomment-1316400688 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5Odq4w simonw 9599 2022-11-16T05:49:31Z 2022-11-16T05:49:31Z OWNER

OK, I decided to play around with GPT-3 for this. https://beta.openai.com/playground

I prompted:

``` For each keyword say it it can be used in a SQLite select statement: and as asc between by case cast cross current current_date current_time current_timestamp desc detach distinct each else end escape except exclude exclusive exists explain fail filter first following for foreign from full generated glob group groups having if ignore immediate in index indexed initially inner insert instead intersect into is isnull join key last left like limit match materialized natural no not nothing notnull null nulls of offset on or order others outer over partition plan pragma preceding primary query raise range recursive references regexp reindex release rename replace restrict returning right rollback row rows savepoint select set table temp temporary then ties to transaction trigger unbounded union unique update using vacuum values view virtual when where window with without

  • and: yes
  • as: yes
  • asc: yes
  • between: yes
  • by: yes
  • case: yes
  • cast: yes
  • current: yes
  • current_date: yes
  • current_time: yes
  • current_timestamp: yes
  • desc: yes
  • detach: no
  • distinct: yes
  • each: yes
  • else: yes
  • end: yes
  • escape: yes
  • except: no
  • exclude: yes
  • exclusive: no Having given it these examples I ran it a few times:
  • exists: yes
  • explain: no
  • fail: no
  • filter: yes
  • first: yes
  • following: no
  • for: yes
  • foreign: no
  • from: yes
  • full: no
  • generated: no
  • glob: yes
  • group: yes
  • groups: no
  • having: yes
  • if: yes
  • ignore: no
  • immediate: no
  • in: yes
  • index: yes
  • indexed: no
  • initially: no
  • inner: no
  • insert: no
  • instead: no
  • intersect: no
  • into: yes
  • is: yes
  • isnull: yes
  • join: yes
  • key: no
  • last: yes
  • left: yes
  • like: yes
  • limit: yes
  • match: no
  • materialized: no -natural: yes
  • no: no
  • not: no
  • nothing: no
  • notnull: yes
  • null: yes
  • nulls: yes
  • of: no
  • offset: yes
  • on: yes
  • or: yes
  • order: yes
  • others: yes
  • outer: no
  • over: no
  • partition: no
  • pragma: no
  • preceding: no
  • primary: no
  • query: no
  • raise: no
  • range: no
  • recursive: no
  • references: no
  • regexp: yes
  • reindex: no
  • release: no
  • rename: no
  • replace: no
  • restrict: no
  • returning: yes
  • right: yes
  • rollback: no
  • row: yes
  • rows: no
  • savepoint: no
  • select: yes
  • set: no
  • table: yes
  • temp: yes
  • temporary: yes
  • then: yes
  • ties: no
  • to: yes
  • transaction: no
  • trigger: no
  • unbounded: no
  • union: yes
  • unique: yes
  • update: no
  • using: yes
  • vacuum: no
  • values: yes
  • view: yes
  • virtual: no
  • when: yes
  • where: yes
  • window: no
  • with: yes
  • without: no I added this: A space separated list of all of the keywords for which the answer was yes: It replied: and as asc between by case cast current current_date current_time current_timestamp desc distinct each else escape except exists explain filter first for from full generated group having if in index inner intersect into isnull join last left like limit not null or order outer over pragma primary query raise range regexp right rollback row select set table temp temporary then to union unique using values view virtual when where Then I tried doing this: Produce a short summary of how each of those are used:

  • and: ``` This kind of worked too! It ended up defining every keyword, not just the ones for which the "is it used in select" was "yes", but it gave me this list:

  • and: Used to combine multiple conditions in a WHERE clause
  • as: Rename a column or table in the output of a query
  • asc: Sort results in ascending order
  • between: Used in a WHERE clause to specify a range
  • by: Specifies how to sort the results of a query
  • case: Used to create different outputs based on conditions
  • cast: Converts a value from one data type to another
  • current: Returns the current date, time, or timestamp
  • current_date: Returns the current date
  • current_time: Returns the current time
  • current_timestamp: Returns the current timestamp
  • desc: Sort results in descending order
  • distinct: Selects only unique values
  • each: Used with aggregate functions
  • else: Used with the CASE statement
  • escape: Used to escape special characters in a string
  • except: Returns all rows from the first query that are not in the second query
  • exists: Used with subqueries
  • explain: Analyzes a query and returns information about it
  • fail: Used with the ON CONFLICT clause
  • filter: Used to specify conditions for aggregate functions
  • first: Used to specify conditions for aggregate functions
  • following: Used with window functions
  • for: Used to specify conditions for aggregate functions
  • foreign: Creates a foreign key
  • from: Specifies the table(s) to select data from
  • full: Used with outer joins
  • generated: Used with generated columns
  • glob: Used to match a string with a pattern
  • group: Groups together rows that have the same values
  • groups: Used with aggregate functions
  • having: Specifies conditions for groups
  • if: Used with the ON CONFLICT clause
  • ignore: Used with the ON CONFLICT clause
  • immediate: Used with the ON CONFLICT clause
  • in: Used to check if a value is in a list
  • index: Creates an index on a column or columns
  • indexed: Used with the ON CONFLICT clause
  • initially: Used with the ON CONFLICT clause
  • inner: Creates an inner join
  • insert: Inserts new data into a table
  • instead: Used with triggers
  • intersect: Returns all rows that are in both queries
  • into: Specifies the table to insert data into
  • is: Used to compare values
  • isnull: Checks if a value is null
  • join: Joins two or more tables together
  • key: Creates a primary key or unique key
  • last: Used to specify conditions for aggregate functions
  • left: Creates a left join
  • like: Checks if a value matches a pattern
  • limit: Specifies the maximum number of rows to return
  • not: Negates a condition
  • null: Specifies a null value
  • nulls: Used with the ORDER BY clause
  • of: Used with window functions
  • offset: Specifies the number of rows to skip
  • on: Specifies conditions for a join
  • or: Checks if either condition is true
  • order: Specifies how to sort the results of a query
  • others: Used with the CASE statement
  • outer: Creates an outer join
  • over: Used with window functions
  • partition: Used with window functions
  • pragma: Used to query or change various internal settings
  • preceding: Used with window functions
  • primary: Creates a primary key
  • query: Used with the ON CONFLICT clause
  • raise: Used with the ON CONFLICT clause
  • range: Used with window functions
  • recursive: Used with common table expressions
  • references: Creates a foreign key
  • regexp: Checks if a value matches a regular expression
  • reindex: Recreates an index
  • release: Used with savepoints
  • rename: Changes the name of a table or column
  • replace: Inserts new data into a table or updates existing data
  • restrict: Used with savepoints
  • returning: Returns data from inserted or updated rows
  • right: Creates a right join
  • rollback: Rolls back a transaction
  • row: Used with aggregate functions
  • select: Selects data from a table
  • set: Changes the value of a column
  • table: Specifies the table(s) to select data from
  • temp: Creates a temporary table
  • temporary: Creates a temporary table
  • then: Used with the CASE statement
  • ties: Used with the ORDER BY clause
  • to: Used with common table expressions
  • transaction: Starts a transaction
  • trigger: Creates a trigger
  • unbounded: Used with window functions
  • union: Returns all rows from both queries
  • unique: Creates a unique constraint
  • update: Updates existing data in a table
  • using: Specifies the table(s) to join
  • vacuum: Optimizes a database
  • values: Specifies the values to insert into a table
  • view: Creates a view
  • virtual: Creates a virtual table
  • when: Used with the CASE statement
  • where: Specifies conditions for a query
  • window: Used with window functions
  • with: Specifies common table expressions used in a query
  • without: Used with indexes
{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316340865 https://github.com/simonw/datasette/pull/1893#issuecomment-1316340865 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdcSB simonw 9599 2022-11-16T04:49:30Z 2022-11-16T04:49:43Z OWNER

The main issue is that we don't pass the relevant table data down to QueryView.

If you can come up with a static example JSON data structure example that does the right thing, I'm happy to refactor QueryView to make that available to the template - or even have a separate fetch() that grabs just the data needed for the autocomplete as a separate hit when the page loads (whichever has better performance implications). I'm working a fair amount in the view classes at the moment so adding this to that work would make sense.

{
    "total_count": 1,
    "+1": 1,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316294156 https://github.com/simonw/datasette/pull/1893#issuecomment-1316294156 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdQ4M simonw 9599 2022-11-16T04:00:12Z 2022-11-16T04:00:12Z OWNER

Have you ever seen CodeMirror correctly auto-completing columns? I'm not entirely sure I believe that the feature works anywhere else.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316293353 https://github.com/simonw/datasette/pull/1893#issuecomment-1316293353 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdQrp simonw 9599 2022-11-16T03:59:03Z 2022-11-16T03:59:03Z OWNER

Deployed a fresh copy: datasette publish vercel fixtures.db \ --branch b7b2942b13f9ea09cfa9f8c73e2869b9bd2349ae \ --project datasette-pr-1893 \ --about 'PR 1893' \ --about_url https://github.com/simonw/datasette/pull/1893 \ --scope datasette https://datasette-pr-1893.vercel.app/fixtures

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316262169 https://github.com/simonw/datasette/issues/1890#issuecomment-1316262169 https://api.github.com/repos/simonw/datasette/issues/1890 IC_kwDOBm6k_c5OdJEZ simonw 9599 2022-11-16T03:22:40Z 2022-11-16T03:22:40Z OWNER

Actually this works as it should in desktop Safari:

I'm going to just put up with the weird behaviour in Mobile Safari.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Autocomplete text entry for filter values that correspond to facets 1448143294  
1316253186 https://github.com/simonw/datasette/pull/1893#issuecomment-1316253186 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdG4C simonw 9599 2022-11-16T03:16:36Z 2022-11-16T03:16:36Z OWNER

Yeah I haven't written this down anywhere but Datasette definitely has an undocumented preference for lower-case SQL.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316242752 https://github.com/simonw/datasette/issues/1890#issuecomment-1316242752 https://api.github.com/repos/simonw/datasette/issues/1890 IC_kwDOBm6k_c5OdEVA simonw 9599 2022-11-16T03:10:52Z 2022-11-16T03:12:47Z OWNER

https://bugs.webkit.org/show_bug.cgi?id=201768 - " Datalist option's label not used" - marked as RESOLVED FIXED on March 31st 2020.

The commit: https://trac.webkit.org/changeset/259330/webkit

And here's the test mirrored on GitHub: https://cs.github.com/qtwebkit/webkit-mirror/blob/cc3fcd0b4bad1f7cf77c26e34aa01d16618d6d5e/LayoutTests/fast/forms/datalist/datalist-option-labels.html?q=datalist-option-labels.html

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Autocomplete text entry for filter values that correspond to facets 1448143294  
1316240839 https://github.com/simonw/datasette/issues/1890#issuecomment-1316240839 https://api.github.com/repos/simonw/datasette/issues/1890 IC_kwDOBm6k_c5OdD3H simonw 9599 2022-11-16T03:09:11Z 2022-11-16T03:09:11Z OWNER

Here's a polyfill for <datalist>: https://github.com/mfranzke/datalist-polyfill

It shouldn't be necessary now that Safari has shipped support (apparently added in https://developer.apple.com/documentation/safari-release-notes/safari-12_1-release-notes#3130314 Safari 12.1 in March 2019).

But it does look like Safari doesn't support differing label and value attributes, though documentation about this is hard to come by.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Autocomplete text entry for filter values that correspond to facets 1448143294  
1316236448 https://github.com/simonw/datasette/pull/1893#issuecomment-1316236448 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdCyg simonw 9599 2022-11-16T03:04:57Z 2022-11-16T03:04:57Z OWNER

If you rebase from main you should get the fix for that test failure.

{
    "total_count": 0,
    "+1": 0,
    "-1": 0,
    "laugh": 0,
    "hooray": 0,
    "confused": 0,
    "heart": 0,
    "rocket": 0,
    "eyes": 0
}
Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
1316233532 https://github.com/simonw/datasette/issues/1890#issuecomment-1316233532 https://api.github.com/repos/simonw/datasette/issues/1890 IC_kwDOBm6k_c5OdCE8 simonw 9599 2022-11-16T03:00:58Z 2022-11-16T03:00:58Z OWNER

Oops, introduced a test failure:

``` def test_table_html_foreign_key_facets(app_client): response = app_client.get( "/fixtures/foreign_key_references?_facet=foreign_key_with_blank_label" ) assert response.status == 200

  assert (
        '<li><a href="http://localhost/fixtures/foreign_key_references?_facet=foreign_key_with_blank_label&amp;foreign_key_with_blank_label=3">'
        "-</a> 1</li>"
    ) in response.text

E assert '

  • - 1
  • ' in '<!DOCTYPE html>\n<html>\n<head>\n <title>fixtures: foreign_key_references: 2 rows</title>\n <link rel="styleshe.../script>\n\n\n<!-- Templates considered: table-fixtures-foreign_key_references.html, *table.html -->\n</body>\n</html>' E + where '<!DOCTYPE html>\n<html>\n<head>\n <title>fixtures: foreign_key_references: 2 rows</title>\n <link rel="styleshe.../script>\n\n\n\n</body>\n</html>' = <datasette.utils.testing.TestResponse object at 0x7fd1b0080640>.text ``` Need to fix this test:

    https://github.com/simonw/datasette/blob/eac028d3f77aa5473a5fcf59240635a1bca80f7d/tests/test_table_html.py#L616-L624

    {
        "total_count": 0,
        "+1": 0,
        "-1": 0,
        "laugh": 0,
        "hooray": 0,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
    }
    Autocomplete text entry for filter values that correspond to facets 1448143294  
    1316232588 https://github.com/simonw/datasette/pull/1893#issuecomment-1316232588 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdB2M simonw 9599 2022-11-16T03:00:04Z 2022-11-16T03:00:04Z OWNER

    Oops, the tests are failing because of a test failure I introduced here: - #1890

    {
        "total_count": 0,
        "+1": 0,
        "-1": 0,
        "laugh": 0,
        "hooray": 0,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
    }
    Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
    1316231560 https://github.com/simonw/datasette/pull/1893#issuecomment-1316231560 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdBmI simonw 9599 2022-11-16T02:59:00Z 2022-11-16T02:59:00Z OWNER

    The resize handle doesn't appear on Mobile Safari on iPhone - I don't think that particularly matters though.

    The textarea does get a weird border around it when focused on iPhone though.

    Focused:

    Not focused:

    {
        "total_count": 0,
        "+1": 0,
        "-1": 0,
        "laugh": 0,
        "hooray": 0,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
    }
    Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
    1316227073 https://github.com/simonw/datasette/pull/1893#issuecomment-1316227073 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OdAgB simonw 9599 2022-11-16T02:54:22Z 2022-11-16T02:54:32Z OWNER

    If you can get a version of this working with table and column autocompletion just using a static JavaScript object in the source code with the right tables and columns, I'm happy to take on the work of turning that static object into something that Datasette includes in the page itself with all of the correct values.

    {
        "total_count": 0,
        "+1": 0,
        "-1": 0,
        "laugh": 0,
        "hooray": 0,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
    }
    Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
    1316141764 https://github.com/simonw/datasette/pull/1893#issuecomment-1316141764 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OcrrE simonw 9599 2022-11-16T01:26:59Z 2022-11-16T01:26:59Z OWNER

    Resizing works great for me - and the page automatically sizes the editor to fit an existing query, e.g. on https://datasette-pr-1893.vercel.app/fixtures?sql=select+id%2C+content%2C+content2%0D%0A++from+primary_key_multiple_columns_explicit_label%0D%0A++order+by+id%0D%0A++limit+101

    {
        "total_count": 0,
        "+1": 0,
        "-1": 0,
        "laugh": 0,
        "hooray": 0,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
    }
    Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
    1316137982 https://github.com/simonw/datasette/pull/1893#issuecomment-1316137982 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5Ocqv- simonw 9599 2022-11-16T01:23:47Z 2022-11-16T01:23:47Z OWNER

    Autocomplete here looks promising (I've wanted that to work for years!), but it does currently show a whole bunch of suggestions which aren't part of the SQLite SQL dialect:

    {
        "total_count": 0,
        "+1": 0,
        "-1": 0,
        "laugh": 0,
        "hooray": 0,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
    }
    Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  
    1316135244 https://github.com/simonw/datasette/pull/1893#issuecomment-1316135244 https://api.github.com/repos/simonw/datasette/issues/1893 IC_kwDOBm6k_c5OcqFM simonw 9599 2022-11-16T01:21:41Z 2022-11-16T01:21:41Z OWNER

    I just deployed a demo instance like this (using the commit hash from this PR):

    bash datasette publish vercel fixtures.db \ --branch 544f7025900b78f63c34b9985522271ba5fd9c0f \ --project datasette-pr-1893 \ --scope datasette \ --about 'PR 1893' \ --about_url https://github.com/simonw/datasette/pull/1893 Here's the result: https://datasette-pr-1893.vercel.app/fixtures

    {
        "total_count": 0,
        "+1": 0,
        "-1": 0,
        "laugh": 0,
        "hooray": 0,
        "confused": 0,
        "heart": 0,
        "rocket": 0,
        "eyes": 0
    }
    Upgrade to CodeMirror 6, add SQL autocomplete 1450363982  

    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 632.576ms · About: github-to-sqlite
    • Sort ascending
    • Sort descending
    • Facet by this
    • Hide this column
    • Show all columns
    • Show not-blank rows