cldellow / datasette-ui-extras

Add editing UI and other power-user features to Datasette.
Apache License 2.0
12 stars 1 forks source link

explore: can the row page support views? #49

Closed cldellow closed 1 year ago

cldellow commented 1 year ago

As part of #48, it might be valuable to let users define a subset of a table as a view. For example, if you have:

CREATE TABLE data(
  id integer primary key,
  value text,
  approved integer,
  approved_at text,
  approved_by text
)

You might want to create a queue of records-to-be-reviewed, like:

CREATE VIEW needs_review AS
SELECT
  id,
  'Look closely at the value. Do you approve it?' AS instructions,
  value AS value_aliased_so_as_not_to_be_editable,
  approved
FROM data
WHERE approved IS NULL

That view declares that you should be able to edit the approved field. id isn't editable, as it's part of the pkey. The other two columns are aliased, and so aren't editable.

Then, you'd use SQLite's INSTEAD OF trigger to permit updates against the view. You'd probably want some jazz to create these triggers automatically, so users can get by with basic SQL understanding.

Questions:

cldellow commented 1 year ago

A horrendous idea: we could add a current_actor() function (see #50 ). When invoked, it runs Python code that uses an asgi local to output the current actor. This gets us the value needed by the approved_by field.

approved_at is just datetime().

How ought the schema signal that it wants those fields to be populated? A proposal:

CREATE VIEW needs_review AS
/* set approved_by=current_actor() */
/* set approved_at=datetime() */
SELECT
  id,
  'Look closely at the value. Do you approve it?' AS instructions,
  value AS value_aliased_so_as_not_to_be_editable,
  approved
FROM data
WHERE approved IS NULL

I think that's actually... not terrible? You could let them express other transformations in there, for example they could have access to old and do arbitrary SQL queries. We'd introspect the view and create the necessary trigger. May god have mercy on our souls.

cldellow commented 1 year ago

Validating that triggers work the way I expect:

CREATE TABLE data(id integer primary key, name text, age integer);
INSERT INTO data(name,age) VALUES ('colin', 37);
INSERT INTO data(name,age) VALUES ('jenn', 38);
CREATE VIEW view AS SELECT * FROM data;
CREATE TRIGGER update_underlying_fields INSTEAD OF UPDATE OF age, name ON view
BEGIN
   UPDATE data SET age = new.age, name = new.name WHERE id = old.id;
END;
UPDATE view SET age = 1, name = 'charlie' WHERE id = 1;
UPDATE view SET age = 10 WHERE id = 2;
SELECT * FROM view;

Yeah, that gives the expected result:

1|charlie|1
2|jenn|10
cldellow commented 1 year ago

I'm actually getting pretty jazzed about views being the initial foothold for editing data. They solve two common issues: