pgkiln 0.46.0 → 0.48.0

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.
Files changed (50) hide show
  1. package/db/migrations/108_sql_history.sql +25 -0
  2. package/db/migrations/109_builder_pins.sql +19 -0
  3. package/db/migrations/110_sql_charts.sql +23 -0
  4. package/db/migrations/111_sql_diagram.sql +24 -0
  5. package/db/migrations/113_rest_objects.sql +49 -0
  6. package/docs/apex-feature-parity.md +28 -2
  7. package/docs/guide/03-builder.md +178 -21
  8. package/docs/guide/08-security.md +19 -1
  9. package/docs/guide/10-tutorial.md +1 -1
  10. package/docs/guide/12-development.md +46 -2
  11. package/docs/guide/13-rest-api.md +74 -9
  12. package/docs/guide/16-files.md +2 -2
  13. package/package.json +1 -1
  14. package/public/builder.css +22 -0
  15. package/public/data-modeler.css +56 -0
  16. package/public/data-modeler.js +367 -0
  17. package/public/palette.js +133 -0
  18. package/public/worksheet.css +293 -0
  19. package/public/worksheet.js +669 -0
  20. package/src/app.ts +4 -0
  21. package/src/builder/ai-builder.ts +3 -3
  22. package/src/builder/autorest.ts +362 -0
  23. package/src/builder/data-modeler.ts +382 -0
  24. package/src/builder/db-users.ts +472 -0
  25. package/src/builder/launchpad.ts +140 -0
  26. package/src/builder/object-actions.ts +167 -0
  27. package/src/builder/object-browser.ts +47 -26
  28. package/src/builder/querybuilder.ts +1 -1
  29. package/src/builder/sampledata.ts +2 -2
  30. package/src/builder/scripts.ts +3 -3
  31. package/src/builder/sql-charts.ts +203 -0
  32. package/src/builder/sql-tools.ts +49 -0
  33. package/src/builder/sql.ts +28 -81
  34. package/src/builder/table-editor.ts +219 -0
  35. package/src/builder/ui.ts +21 -15
  36. package/src/builder/unload.ts +8 -4
  37. package/src/builder/worksheet.ts +592 -0
  38. package/src/builder/workspaces.ts +5 -3
  39. package/src/cli/replace.ts +3 -1
  40. package/src/datamodel.ts +324 -0
  41. package/src/dbroles.ts +215 -0
  42. package/src/runtime/autorest.ts +336 -0
  43. package/src/runtime/rest.ts +4 -4
  44. package/src/session.ts +2 -0
  45. package/src/sqlformat.ts +208 -0
  46. package/src/sqlplan.ts +133 -0
  47. package/src/sqlscript.ts +6 -2
  48. package/src/sqlworksheet.ts +278 -0
  49. package/src/tabledef.ts +226 -0
  50. package/src/unload.ts +14 -3
@@ -0,0 +1,25 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 108: the SQL Worksheet's history (sprint 92, Database Actions DA-5:
3
+ -- SQL History). One row per statement a developer ran in the worksheet:
4
+ -- the text, how it ended (ok or error), the rows and the time. Running
5
+ -- the same statement again right after counts on the same row (runs,
6
+ -- at), so repeated runs don't flood the list. Kept per developer and
7
+ -- workspace, at most 500 rows each (the builder deletes older ones).
8
+ -- The builder reads and writes it as the owner; nobody else has grants.
9
+ -- The activity log keeps its own 'sql_command' entries (the SQL Workshop
10
+ -- home's Recent SQL Commands).
11
+ -- ---------------------------------------------------------------------
12
+ create table meta.sql_history (
13
+ id bigint generated always as identity primary key,
14
+ username text not null,
15
+ workspace_id int not null default 1 references meta.workspace on delete cascade,
16
+ sql text not null check (length(sql) <= 20000),
17
+ status text not null check (status in ('ok', 'error')),
18
+ rows bigint,
19
+ ms int,
20
+ error text,
21
+ runs int not null default 1,
22
+ at timestamptz not null default now()
23
+ );
24
+ create index sql_history_user_idx on meta.sql_history (username, workspace_id, id desc);
25
+ comment on table meta.sql_history is 'The SQL Worksheet''s history per developer and workspace (108); installation data, not exported';
@@ -0,0 +1,19 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 109: pins on the SQL Workshop's Launchpad (sprint 96, Database Actions
3
+ -- DA-15: Pinned & Recently Visited). A developer pins a tool, a database
4
+ -- object or a saved worksheet; the home page lists them first. Per
5
+ -- developer and workspace, at most 24 (the builder refuses more). Only
6
+ -- builder paths (/builder/…) are kept. The builder reads and writes it as
7
+ -- the owner; installation data, not exported.
8
+ -- ---------------------------------------------------------------------
9
+ create table meta.builder_pin (
10
+ id bigint generated always as identity primary key,
11
+ username text not null,
12
+ workspace_id int not null default 1 references meta.workspace on delete cascade,
13
+ href text not null check (href ~ '^/builder/' and length(href) <= 400),
14
+ label text not null check (length(label) between 1 and 120),
15
+ icon text not null default 'bookmark' check (icon ~ '^[a-z0-9-]{1,40}$'),
16
+ at timestamptz not null default now(),
17
+ unique (username, workspace_id, href)
18
+ );
19
+ comment on table meta.builder_pin is 'The SQL Workshop Launchpad''s pins per developer and workspace (109); installation data, not exported';
@@ -0,0 +1,23 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 110: SQL Workshop charts (sprint 97, Database Actions DA-6: Charts).
3
+ -- A chart is a SELECT with how to draw it: the chart type, the label
4
+ -- column and the value columns. The worksheet's Chart tab saves one; SQL
5
+ -- Workshop → Charts lists them and shows the ones on the dashboard. Shared
6
+ -- by the workspace's developers, like SQL Scripts. The builder runs the
7
+ -- SELECT read-only with the workshop's connection when it draws a chart.
8
+ -- Installation data, not exported.
9
+ -- ---------------------------------------------------------------------
10
+ create table meta.sql_chart (
11
+ id int generated always as identity primary key,
12
+ workspace_id int not null default 1 references meta.workspace on delete cascade,
13
+ name text not null check (length(name) between 1 and 120),
14
+ sql text not null check (length(sql) between 1 and 20000),
15
+ kind text not null default 'bar' check (kind in ('bar', 'column', 'line', 'area', 'donut', 'pie', 'scatter', 'stacked')),
16
+ label_col text not null default '',
17
+ value_cols text[] not null default '{}',
18
+ on_dashboard boolean not null default true,
19
+ created_by text,
20
+ updated_at timestamptz not null default now(),
21
+ unique (workspace_id, name)
22
+ );
23
+ comment on table meta.sql_chart is 'SQL Workshop charts: a SELECT drawn as a chart (110); installation data, not exported';
@@ -0,0 +1,24 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 111: the SQL Workshop's Data Modeler (sprint 98, Database Actions
3
+ -- DA-10: relational diagrams). A diagram is a named picture of some
4
+ -- tables and views of one schema: which objects it shows and where each
5
+ -- box stands. objects is a jsonb array of {"name", "x", "y"} (the
6
+ -- object's name in the schema, the box's position). The objects are only
7
+ -- names: the columns, keys and foreign keys are read from the catalog
8
+ -- whenever the diagram is shown, so a diagram never goes stale. Per
9
+ -- workspace, shared by its developers. The builder reads and writes it
10
+ -- as the owner; installation data, not exported.
11
+ -- ---------------------------------------------------------------------
12
+ create table meta.sql_diagram (
13
+ id bigint generated always as identity primary key,
14
+ workspace_id int not null default 1 references meta.workspace on delete cascade,
15
+ name text not null check (length(name) between 1 and 120),
16
+ schema_name text not null check (length(schema_name) between 1 and 63),
17
+ objects jsonb not null default '[]' check (jsonb_typeof(objects) = 'array' and jsonb_array_length(objects) <= 500),
18
+ created_by text not null,
19
+ created_at timestamptz not null default now(),
20
+ updated_by text,
21
+ updated_at timestamptz not null default now(),
22
+ unique (workspace_id, name)
23
+ );
24
+ comment on table meta.sql_diagram is 'The SQL Workshop Data Modeler''s diagrams per workspace (111); installation data, not exported';
@@ -0,0 +1,49 @@
1
+ -- ---------------------------------------------------------------------
2
+ -- 113: AutoREST (sprint 100, Database Actions DA-11 part 1; ORDS: REST ›
3
+ -- Enable on a table or view). SQL Workshop › RESTful Services publishes a
4
+ -- table or view through an application of the workspace:
5
+ --
6
+ -- /a/<alias>/autorest/<object>/ GET (paged, filters), POST
7
+ -- /a/<alias>/autorest/<object>/<key> GET, PUT, DELETE (tables with a primary key)
8
+ -- /a/<alias>/autorest/openapi.json the OpenAPI description of them all
9
+ --
10
+ -- The application decides how a request runs: its database role (never the
11
+ -- object's owner, a superuser or a role that bypasses row level security,
12
+ -- checked when the object is enabled and at every request), its tokens and
13
+ -- OAuth clients (App › REST API), its accounts' roles (meta.has_role) and
14
+ -- its availability. Without a bearer token an object answers 401 unless the
15
+ -- developer chose "public" for it explicitly.
16
+ --
17
+ -- The builder writes the rows as the owner; the runtime reads them.
18
+ -- Installation data like the application's OAuth clients: not exported (an
19
+ -- in-place import keeps them); the application's own REST modules are what
20
+ -- travels with an export.
21
+ -- ---------------------------------------------------------------------
22
+ create table meta.rest_object (
23
+ id int generated always as identity primary key,
24
+ app_id int not null references meta.app on delete cascade,
25
+ schema_name text not null check (length(schema_name) between 1 and 63),
26
+ object_name text not null check (length(object_name) between 1 and 63),
27
+ -- the URL segment: /a/<alias>/autorest/<alias>/
28
+ alias text not null check (alias ~ '^[a-z][a-z0-9_-]{0,62}$' and alias <> 'openapi.json'),
29
+ methods text[] not null default '{GET}' check (methods <@ '{GET,POST,PUT,DELETE}'::text[] and cardinality(methods) > 0),
30
+ -- token: a bearer token of the application (default); public: no token needed, meta.app_user() = nobody
31
+ auth text not null default 'token' check (auth in ('token', 'public')),
32
+ -- the caller needs one of these application roles (meta.has_role); empty: any caller the auth allows
33
+ roles text[] not null default '{}',
34
+ page_size int not null default 25 check (page_size between 1 and 500),
35
+ enabled boolean not null default true,
36
+ created_by text,
37
+ created_at timestamptz not null default now(),
38
+ updated_at timestamptz not null default now(),
39
+ unique (app_id, alias),
40
+ unique (app_id, schema_name, object_name)
41
+ );
42
+ revoke all on meta.rest_object from public;
43
+ grant select on meta.rest_object to pgkiln_runtime;
44
+ -- isolated workspaces (090): a workspace's logins see the rows of their own applications only
45
+ alter table meta.rest_object enable row level security;
46
+ create policy workspace on meta.rest_object
47
+ using ((select meta.isolation_off()) or app_id in (select meta.visible_apps()))
48
+ with check ((select meta.isolation_off()) or app_id in (select meta.visible_apps()));
49
+ comment on table meta.rest_object is 'AutoREST (113): tables and views published through an application at /a/<alias>/autorest/<alias>/; installation data, not exported';
@@ -7,7 +7,7 @@ open item and open an issue or pull request; see [CONTRIBUTING.md](../CONTRIBUTI
7
7
  Legend: ✅ available · 🟡 partial (see notes) · ❌ not yet · ➖ not planned (a deliberate choice,
8
8
  or better served by the PostgreSQL ecosystem; see the notes and [extensions](guide/15-extensions.md))
9
9
 
10
- Last reviewed: 2026-10-15 (sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
10
+ Last reviewed: 2026-10-16 (sprint 100: RESTful Services, tables and views published as REST endpoints with paging, filters, keys and OpenAPI; sprint 99: Administration → Database Users for PostgreSQL roles; sprint 98: the Data Modeler with relational diagrams, DDL and a data dictionary; sprint 97: charts of a query in the worksheet, saved charts and their dashboard; sprint 96: the SQL Workshop's Launchpad with pins and tool groups, the builder's search with Ctrl+K; sprint 95: Table Properties: create, edit or copy a table in a form with a DDL preview and Apply in one transaction; sprint 94: an object's menu with Open in a panel, Quick DDL, Add index / trigger / policy and Drop with dependents; sprint 93: worksheets saved as SQL Scripts with tabs and a Files list, Format, Convert case, find and replace, bind and substitution variables; sprint 92: the worksheet's Query Result with sort, value dialog, copy and downloads, plans as a tree with the slowest step and misestimates, SQL History with status, search and run again; sprint 91: the SQL Worksheet like Database Actions' SQL: navigator, Run Statement at the cursor and Run Script with a log per statement, Explain Plan, Autotrace, notices, history, Run as an application role; sprint 90: Comment Out in the page designer, gallery labels in title case; sprint 89: the Object Browser's schema, one row of tabs, blank NULLs, Modify column; sprint 88: home cards with colour bands and round icons, the hero on the page background, a page footer with the version and Back to top; sprint 87: the Create Application wizard reloads the page list for a schema, RLS badges, the alias from the name; sprint 86: the page designer by page number, HTML error pages in the builder; sprint 85: the Form Designer, beyond APEX; sprint 84: the date picker, facet menus; sprint 83: Component Settings and Component Groups; sprint 82: Report Queries; sprint 81: Application Computations and Shortcuts in Shared Components; sprint 80: the master grid's first row selected when the page opens and after a search; grid cells as text with their format mask until edited, with cell navigation by arrow keys, Enter, F2 and Escape; sprint 79: generated dashboards with sums, donuts and lines, leaving out charts that say nothing; applications open in their own light or dark mode until the user chooses, per application; a user menu with Appearance and Sign in when signed out; the developer toolbar's App and Page texts and debug state; the report search's column scope in the magnifier; sprint 78: generated faceted search reports with one column per foreign key, the faceted search's total row count, Show all and Yes/No values, one search field, friendly headings and number formats in generated grids and master-detail pages, friendly names in the Create Application wizard's page list; sprint 77: the Page Designer's layout and tree by display position, button positions, the tree's context menu with Duplicate and Copy to other page, Show Common / Show All, Go to group and the Template Options dialog; display positions, button positions and side-column page templates at runtime; sprint 76: the interactive report's menus and pagination, date items in the date format; sprint 75: the SQL Workshop's Object Browser and tabs; sprint 74: the builder's information architecture: Shared Components grid, Settings tabs, application home search and tasks; sprint 73: the Create Application wizard on one page with page types and features; sprint 72: the runtime chrome compared with APEX 26.2's: the developer toolbar, the Iris look, the navigation bar's Help menu and Install button; sprint 71: generated applications compared with APEX 26.2's: labels, foreign key names in reports, file columns, format masks, the Home page and the dashboard; sprint 70: treemap, sunburst and timeline charts; sprint 69: dragging tasks on a Gantt chart; sprint 68: the Data Reporter's welcome page, Find my workspace; sprint 67: REST source catalogs from OpenAPI documents, a workspace's export and import (two rows added); sprint 66: a blueprint from an existing application; sprint 65: facet charts; sprint 64: approval vacation rules and expiration policies; sprint 63: range, box plot and stock charts; sprint 62: workspace preferences (SQL Workshop and RESTful services per workspace), extension links, Manage backups across applications, SQL Workshop utilities with object reports, About Database and a database monitor; sprint 61: the builder's screens compared with APEX 26.1: the workspace sign-in page, the Administration menu with workspace message, environment banner and utilization, the SQL Workshop home, the App Gallery, application groups and cross application reports (four rows added); sprint 60: isolated workspaces with their own database logins, row-level security on pgkiln's tables and workspace database roles, workspace administrators; sprint 59: the Page Designer's help pane, Quick edit from the developer toolbar; sprint 58: page groups; sprint 57: region templates hero, title bar, buttons container, inline dialog and drawer, wizard with wizard progress, the carousel; sprint 56: Generate DDL and Schema Comparison in the SQL Workshop, `pgkiln ddl` and `pgkiln compare`; sprint 55: an editable login page with a Login region and the Minimal page template, Forgot password through the application's mail service; sprint 54: interactive grid views, the single row view, group by and chart; sprint 53: application settings, user preferences and items kept per user, dynamic translations, `meta.data_export` and data export downloads, display image and geocoded address items; sprint 52: every dynamic action event and action, Ajax callbacks, an error handling function, the session timeout warning; sprint 51: checked imports, application backups, availability and Run only, feedback, type-specific attribute help; sprint 50: lost update detection, warn on unsaved changes, the URL and search regions with search configurations, the developer toolbar with a session state viewer, and e-mail through SMTP with OAuth2, Microsoft Graph, Amazon SES and HTTP APIs; import checks, application availability, property help and e-mail compared again; 2026-10-06: pgkiln 0.31.0, in progress: static application files and the Execute JavaScript dynamic action; region, item, dynamic action and process plug-ins; conditional and dynamic theme styles; XML and Excel in `meta.parse_data`, zips in SQL, `meta.v_boolean`; file items in S3-compatible object storage; map layers by the visible area and as vector tiles; a graphical query builder; tenants for workflows and tasks; application files as YAML and region static IDs; Lucide icons and icon modifiers; PWA push notifications; 0.30.0: 136 icons and an icon picker; an axe-core accessibility audit; cropping pictures; session sharing between applications; twenty-two built-in languages; 0.29.0: workspaces; the Iris base style; drawers; built-in template components including the metric card; Theme Roller dark-mode colours, live preview and template options on items and report columns; report selection across pages; instance settings; fourteen built-in languages; 0.28.0: AI with Claude and OpenAI; 0.27.0: Data Reporter; sample data generator; create application from several sheets, pasted data or existing tables; 0.26.0: working copies with a three-way merge; theme, library and boilerplate applications with subscriptions; 0.25.0: Gantt, pyramid and polar charts; map layers, clustering and server-side spatial filters; REST data sources that write back from forms and grids and synchronise into tables, OAuth2 password and refresh-token grants; debug messages per request and an install/upgrade log; `meta.web_request()` and `meta.parse_data()`; Theme Roller style variants and template options; 0.24.0: automations with several actions, error handling per row and runs from SQL; invoke-API workflow steps; Unload Data in the Data Workshop; create page wizards for cards, calendar, chart, map, faceted search, form and master-detail; create an application from a file; 0.23.0: interactive grid aggregates, frozen/moved/resized columns, layouts and saved grid reports, master-detail, row actions and copy/paste; download processes, execution chains in the background, workflow processes, branches to a function's URL or another app, the Dialog Closed event; number format masks, automatic time zone, runtime messages in German, French and Spanish; SQL scripts, Quick SQL, a query builder, XML loading and data load definitions; custom authentication, lists, page and application locks with developer comments, supporting objects; 0.22.0: keyset paging, report PDFs and REST collections streamed from a cursor, database-account authentication; 0.21.0: HTTP-header authentication behind a reverse proxy; 0.20.0: a popup list of values with server-side search; 0.19.0: row-range pagination, maximum row counts and row limits, lazy loading and caching of regions, streamed CSV/Excel downloads; 0.18.0: calendar week/day/list views with drag and drop, bubble/gauge/funnel/radar charts and drill-down, smart filters, a region display selector and more facet types, computations, conditional branches, build options, menu buttons, REST data sources and web credentials, rich text/Markdown, rating, combobox, date range and QR code items; 0.17.0: an App Builder home, workspace dashboard and utilities like APEX's; 0.16.0: a Page Designer with drag-and-drop layout, a code editor with autocomplete, template components and plug-ins, parallel branches and versions of workflows, the `pgkiln` command line with one file per component; 0.15.0: drop and paste files, heat maps, filtering a report by the map area; 0.14.0: stacked, combo, scatter and pie charts, several files per upload item; 0.13.0: map and tree regions; 0.12.0: REST modules in the builder; 0.11.0: workflows and Progressive Web Apps; 0.10.0: LDAP, SAML, "Keep me signed in", document templates, JSON loading, approvals and the task list; pgkiln installs no application, HR is an example).
11
11
 
12
12
  ## At a glance
13
13
 
@@ -184,7 +184,7 @@ two, REST source catalogs and the workspace export, with their features.)
184
184
 
185
185
  | APEX | pgkiln | Notes |
186
186
  |---|---|---|
187
- | SQL Workshop: SQL commands, object browser | ✅ | (sprint 61) A **home page** like APEX's: tiles, recently created tables, your recent SQL commands and the workspace's recent scripts, and the session's **default schema** (first in the search path of SQL Commands and Scripts). (sprint 75) The **Object Browser** like APEX's: a schema in the header, a tree by object type (tables, views, materialized views, indexes, sequences, types, functions, procedures, triggers) with a filter and a Create menu, system and extension objects hidden unless asked, and a table in tabs (columns with Add/Rename/Drop column writing the ALTER TABLE to review, data in pages, indexes, constraints, triggers, grants, row level security, dependencies, statistics, DDL); the tools as main tabs and a More menu. (sprint 62) **Utilities** like APEX's: the tools on one page, **Object Reports** (tables without a primary key, unindexed foreign keys, row-level security without policies or not enabled, PUBLIC grants, unused indexes, largest tables, missing comments), **About Database** and a **Database Monitor** of sessions and blocked queries for administrators. **Missing:** a recycle bin (PostgreSQL has none), user interface defaults (pgkiln's wizards read the catalog and comments) |
187
+ | SQL Workshop: SQL commands, object browser | ✅ | (sprint 61) A **home page** like APEX's: tiles, recently created tables, your recent SQL commands and the workspace's recent scripts, and the session's **default schema** (first in the search path of the SQL Worksheet and Scripts). (sprint 91) **SQL Commands is the SQL Worksheet** like Database Actions' SQL: a navigator, the statement at the cursor or a script with a log per statement, Explain Plan and Autotrace, notices and history (see the Database Actions section below). (sprint 75) The **Object Browser** like APEX's: a schema in the header, a tree by object type (tables, views, materialized views, indexes, sequences, types, functions, procedures, triggers) with a filter and a Create menu, system and extension objects hidden unless asked, and a table in tabs (columns with Add/Rename/Drop column writing the ALTER TABLE to review, data in pages, indexes, constraints, triggers, grants, row level security, dependencies, statistics, DDL); the tools as main tabs and a More menu. (sprint 62) **Utilities** like APEX's: the tools on one page, **Object Reports** (tables without a primary key, unindexed foreign keys, row-level security without policies or not enabled, PUBLIC grants, unused indexes, largest tables, missing comments), **About Database** and a **Database Monitor** of sessions and blocked queries for administrators. **Missing:** a recycle bin (PostgreSQL has none), user interface defaults (pgkiln's wizards read the catalog and comments) |
188
188
  | RESTful services (ORDS) | ✅ | [PostgREST](https://postgrest.org) next to pgkiln: `api` schema, the same RLS as the UI, per-app API role, tokens in the builder, a pre-request check, and **OAuth clients** (client credentials, like ORDS `oauth.create_client`) so tokens renew themselves |
189
189
  | REST handler editor, REST-enabled SQL | ✅ | **REST modules** in the builder: handlers (method, path with parameters, SQL as collection, item or statements, roles, public) served by pgkiln with bearer tokens and an OpenAPI description; plus PostgREST for schema-wide APIs. **Missing:** REST-enabled SQL (rarely desirable) |
190
190
  | SQL scripts, query builder, Quick SQL | ✅ | **SQL Scripts**: saved, upload/download, a result per statement, stop or continue on errors, optionally one transaction, run history. **Quick SQL** (a subset: tables, child tables, types, the main column directives, `/auditcols`, settings, views). A graphical **query builder**: tables as boxes on a canvas (dragged, placed where left), joins along foreign keys or drawn from column to column (inner or left), column functions with automatic `group by`, conditions, sort, open in SQL Commands; without JavaScript the same as forms ([chapter 3](guide/03-builder.md#sql-workshop)) |
@@ -334,3 +334,29 @@ Sources: [APEX 26.1 new features](https://docs.oracle.com/en/database/oracle/ape
334
334
  | Map Backgrounds | ➖ Not planned per application: the installation's map tile server (`MAP_TILE_URL`) is every map's background |
335
335
  | AI Attributes, AI Services, AI Agents | AI Services; AI agents ➖ not planned |
336
336
 
337
+ ## Database Actions (SQL Developer Web) and the SQL Workshop
338
+
339
+ (sprint 91) Oracle's Database Actions, the ORDS tool next to APEX, is the standard for pgkiln's SQL Workshop, mapped
340
+ to PostgreSQL. pgkiln's own extras stay: Quick SQL, the Query Builder, Sample Data, Schema Comparison, Object Reports,
341
+ AI and row level security badges.
342
+
343
+ | Database Actions | pgkiln | |
344
+ |---|---|---|
345
+ | SQL worksheet: navigator, editor, output tabs, status bar | SQL Workshop → SQL Worksheet (sprint 91): navigator by schema and object type with columns, drag and drop and SELECT / INSERT / UPDATE / DELETE; Query Result, Script Output, Notices (DBMS Output), Explain Plan, Autotrace, SQL History; resizable panes, fullscreen | ✅ |
346
+ | Run Statement (Ctrl+Enter), Run Script (F5) | The statement at the cursor or the selection; a script with a log per statement (psql command tags, error line and column), stop or continue on error; Run as an application's role | ✅ |
347
+ | Explain Plan (F10), Autotrace (F6) | A tree of steps (sprint 92): cost, rows, conditions; with Autotrace (`EXPLAIN ANALYZE, BUFFERS`, rolled back) actual time, rows, loops, buffers, each step's own time, the slowest step and 10× misestimates; the text plan too | ✅ |
348
+ | Query Result grid (paging, download, sharing) | 500 rows (All rows: 10,000) with row numbers, numbers right-aligned, sort, a value dialog, copy, Download as CSV, JSON, XML, Excel or SQL inserts (sprint 92); no sharing links | ✅ |
349
+ | SQL History, DBMS Output | SQL History per developer with status, rows, time, search and run again; Notices with their time (sprint 92) | ✅ |
350
+ | Worksheets saved as files, tabs | Save, Save as, Rename, Download as SQL Scripts, a Files tab, worksheet tabs that survive a reload (sprint 93) | ✅ |
351
+ | Create Chart from a query, Charts | The worksheet's Chart tab (Ctrl+F11) and SQL Workshop → Charts with a dashboard (sprint 97); no page made from a chart yet | ✅ |
352
+ | Object context menu, table properties dialog, Quick DDL | An object's menu (sprint 94): Open in a panel, Quick DDL to the worksheet or a file, Load data, Add index / trigger / policy, Drop with its dependents; **Table Properties** (sprint 95): columns, keys, foreign keys, checks, indexes, comment, RLS, partitioning, DDL preview, Apply in one transaction, use as template | ✅ |
353
+ | Format, Convert Case, Find and replace, bind variables | Format (Ctrl+F7), Convert case, find and replace, Go to line, comment lines, `:NAME` and `&NAME.` asked for before a run (sprint 93); no guided tour | ✅ |
354
+ | Data Modeler (relational diagrams) | SQL Workshop → Data Modeler (sprint 98): diagrams per schema, boxes with columns and keys, foreign key lines with crow's feet, positions saved, zoom, fit, auto layout, mini-map, SVG / PNG export, DDL of the shown objects, a data dictionary | ✅ |
355
+ | REST (modules, AutoREST) | SQL Workshop → RESTful Services (sprint 100): a table or view published through an application with GET (paging, filters, search, order), item GET, POST, PUT, DELETE as the app role with its tokens and RLS, OpenAPI; custom modules, templates and handlers are application REST modules (Shared Components), not yet managed from the SQL Workshop | 🟡 |
356
+ | Scheduling | pgkiln's own jobs and automations | ❌ |
357
+ | Database Users | Administration → Database users (sprint 99): roles with sign-in, attributes, expiry, memberships and owned objects; create and edit with the SQL reviewed (password masked, a SCRAM verifier) and applied in one transaction; drop with reassign or drop owned; pgkiln's roles protected. PostgreSQL has no created date or quota | ✅ |
358
+ | Real Time SQL Monitor | Database Monitor (sessions) and Top SQL per application role | 🟡 |
359
+ | Launchpad, Search Database (Ctrl+K) | The SQL Workshop home as a Launchpad (sprint 96): pinned and recently visited, Development / Administration / Monitoring tabs; Search (Ctrl+K) for tools, applications, pages and database objects; no guided walk-through | ✅ |
360
+ | Data Pump | Application backups and Unload Data | 🟡 |
361
+ | Liquibase | Schema Comparison | 🟡 |
362
+ | JavaScript (MLE) | ➖ Not planned: PostgreSQL has plv8 as an extension | ➖ |
@@ -84,7 +84,7 @@ builder page while the workspace is current.
84
84
  Administrators and the workspace's administrators set them on the workspace's page (Administration menu →
85
85
  *Workspace preferences*; APEX: Set Workspace Preferences):
86
86
 
87
- - **Enable the SQL Workshop**: off, every SQL Workshop page (SQL Commands, the Object Browser, SQL scripts, Load and
87
+ - **Enable the SQL Workshop**: off, every SQL Workshop page (the SQL Worksheet, the Object Browser, SQL scripts, Load and
88
88
  Unload Data, Quick SQL, the query builder, Sample Data, DDL, Compare, AI) answers *403* while the workspace is
89
89
  current, for every developer including administrators; the rail and Workspace utilities no longer show it. A
90
90
  developer who belongs to another workspace can still use it there. Turn it off for a workspace whose developers
@@ -143,7 +143,7 @@ workspace → *Isolation*). It needs `RUNTIME_DATABASE_URL` (applications don't
143
143
 
144
144
  - **Two PostgreSQL logins of its own**: `pgkiln_ws<id>_run_<suffix>` runs its applications (pages, processes, REST
145
145
  handlers, automations, workflows, background processes, REST synchronisation); `pgkiln_ws<id>_dev_<suffix>` runs its
146
- developers' SQL: SQL Commands, SQL Scripts, Quick SQL, Load and Unload Data, Sample Data, DDL and Compare, the
146
+ developers' SQL: the SQL Worksheet, SQL Scripts, Quick SQL, Load and Unload Data, Sample Data, DDL and Compare, the
147
147
  Advisor, code checks and document previews. SQL that runs `RESET ROLE` (or `set_config('role', …)`) only gets back to
148
148
  that login, which can use the workspace's database roles and nothing else.
149
149
  - **The workspace's database roles** (APEX: workspace schemas): isolating gives the workspace the roles its
@@ -183,7 +183,7 @@ Every builder page has the same frame, modelled on an IDE:
183
183
  pages of an application); at the bottom the **Administration** menu (Workspace utilities; for administrators of the
184
184
  current workspace *Manage service*: [workspace message and environment banner](#workspace-message-and-environment-banner),
185
185
  [workspace utilization](#workspace-utilization) and the workspace's page; Manage users and groups, Developers,
186
- Monitor activity, Change my password), Help, and your account menu (the circle with your initials) with the
186
+ Monitor activity, [Database users](#database-users) for administrators, Change my password), Help, and your account menu (the circle with your initials) with the
187
187
  **builder theme** (*Dark*, the default; *Light*; or *System*, which follows the operating system),
188
188
  Change password and Sign out. The theme is remembered on this device, also after signing out;
189
189
  it only changes the builder, not your applications.
@@ -1191,8 +1191,8 @@ administrator chooses it under **SQL Workshop → AI** (any enabled [AI service]
1191
1191
  switches the builder's AI off). What it is used for:
1192
1192
 
1193
1193
  - **SQL from a question** (SQL Workshop → AI): pick a schema and ask; the answer is a statement and
1194
- a short explanation. It is **shown, never run**: check it, change it and run it in SQL Commands
1195
- yourself (*Run in SQL Commands*).
1194
+ a short explanation. It is **shown, never run**: check it, change it and run it in the SQL Worksheet
1195
+ yourself (*Run in the SQL Worksheet*).
1196
1196
  - **Explain a query or an error** (SQL Workshop → AI): paste a query, an error message or both
1197
1197
  (optionally with a schema for context); the explanation is shown with simple formatting.
1198
1198
  - **Describe tables for AI** (SQL Workshop → AI → *Describe tables*): per table or view, a
@@ -1246,34 +1246,124 @@ may use), a form to **issue a token** for an account, and `curl` examples. See
1246
1246
 
1247
1247
  ## SQL Workshop
1248
1248
 
1249
- The SQL Workshop opens on its **home** (`/builder/sql`; APEX: the SQL Workshop home): tiles for the Object Browser,
1250
- SQL Commands, SQL Scripts, the utilities and Quick SQL; **Recently created tables** (the newest tables you can read:
1251
- PostgreSQL keeps no creation time, so object ids decide), your **recent SQL commands** (click one to open it in SQL
1252
- Commands; other developers' are never shown) and the workspace's **recent SQL scripts**. The side column sets the
1253
- session's **schema** (APEX: the default schema): it goes first in the search path of SQL Commands and SQL Scripts until
1249
+ The SQL Workshop opens on its **home** (`/builder/sql`; APEX: the SQL Workshop home): tiles for the SQL Worksheet,
1250
+ the Object Browser, SQL Scripts, the utilities and Quick SQL; **Recently created tables** (the newest tables you can read:
1251
+ PostgreSQL keeps no creation time, so object ids decide), your **recent SQL commands** (click one to open it in the SQL
1252
+ Worksheet; other developers' are never shown) and the workspace's **recent SQL scripts**. The side column sets the
1253
+ session's **schema** (APEX: the default schema): it goes first in the search path of the SQL Worksheet and SQL Scripts until
1254
1254
  you sign out. Tasks link to Quick SQL, blueprints, table descriptions, sample data and Generate DDL.
1255
1255
 
1256
- (sprint 75) The tools are tabs: Home, Object Browser, SQL Commands, SQL Scripts and Utilities; **More** opens the
1257
- others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compare, AI), and the open one is a tab too.
1258
-
1259
- - **SQL Commands** (`/builder/sql/commands`): run any SQL as the **owner connection**, not as an application role. Multiple
1260
- statements are allowed; the result of the last one is shown (up to 500 rows). Press
1261
- **Ctrl/Cmd + Enter** to run. The [code editor](#the-code-editor) suggests every schema, table,
1262
- column and function the owner sees.
1256
+ (sprint 75) The tools are tabs: Home, SQL Worksheet, Object Browser, SQL Scripts and Utilities; **More** opens the
1257
+ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compare, Data Modeler, AI), and the open one is a tab too.
1258
+
1259
+ (sprint 96; Database Actions: the Launchpad) The home page starts with **Pinned & recently visited**: the pages you
1260
+ pinned (a tool, a database object from the Object Browser, a saved worksheet from its file menu; at most 24, per
1261
+ workspace) and the SQL Workshop pages you opened last in this browser. Below, the tools are in three tabs,
1262
+ **Development**, **Administration** and **Monitoring**, each with a line about what it does and a pin; the **More**
1263
+ menu uses the same headings.
1264
+
1265
+ **Search** (**Ctrl/Cmd + K** on any builder page, or the field in the header) finds tools, applications, pages
1266
+ (by name or number) and database objects (tables, views, materialized views, functions and procedures) by name;
1267
+ the arrow keys and Enter open one. Applications and pages come from your workspace only; objects from the schemas
1268
+ the SQL Workshop's connection may use. Without JavaScript the header's field opens a page of results.
1269
+
1270
+ - **SQL Worksheet** (`/builder/sql/worksheet`, sprint 91; Database Actions: SQL; was SQL Commands, whose address
1271
+ `/builder/sql/commands` opens the same page): one screen with a **navigator** on the left, the **editor** with a
1272
+ toolbar, **output tabs** below and a **status bar**.
1273
+ - The navigator has a schema (the same one as the Object Browser), an object type (*All Objects*, tables, views,
1274
+ materialized views, indexes, sequences, types, functions, procedures, triggers, policies) and a search field.
1275
+ A table or view opens to its columns with their types (a key marks the primary key); drag it into the editor
1276
+ for a `SELECT` of all its columns, or use its **SELECT**, **INSERT**, **UPDATE** and **DELETE** buttons, which
1277
+ insert the statement at the cursor. Columns are listed for the first 400 tables and views of a schema.
1278
+ - (sprint 94) Each object has a **⋯ menu** (or right-click it; Shift+right-click keeps the browser's menu), in
1279
+ the Object Browser's tree too: **Open** shows the Object Browser's tabs in a panel at the side, without leaving
1280
+ the worksheet; **Quick DDL** puts the object's DDL into a new worksheet tab (with the search path set to its
1281
+ schema) or downloads it as a `.sql` file; for a table **Load data**, **Add index**, **Add trigger** (a trigger
1282
+ function and the trigger) and **Add policy** (row level security on, a policy to fill in); **Drop…** writes the
1283
+ DROP statement with a comment that lists what depends on the object (views, foreign keys…). Nothing runs: you
1284
+ review the statement and run it.
1285
+ (sprint 100) Tables and views also have **REST › Enable / Disable**: it opens the object's page in **RESTful
1286
+ Services** when it is published, or the Enable form for it (below).
1287
+ - (sprint 95) **Table Properties** (a table's **Edit…**, **Use as template**, the Object Browser's *Edit table* and
1288
+ its *Table (form)* tile): a form with **Columns** (name, type, primary key, not null, default, identity,
1289
+ comment; move them up or down for a new table, remove them), **Unique keys**, **Foreign keys** (the table it refers
1290
+ to, its columns, on delete), **Checks**, **Indexes** (columns or expressions, unique; indexes with another method or
1291
+ a condition are kept as they are), the table's **comment**, **row level security** (and forcing it for the owner)
1292
+ and, for a new table, **partitioning** (range, list or hash and its key). **Preview DDL** shows the exact CREATE
1293
+ TABLE, or for an existing table the ALTER statements from what the catalog says now; **Apply** runs them in one
1294
+ transaction (nothing changes when one fails, and the error shows under *Output*); **Open in the worksheet** puts
1295
+ them there instead. *Use as template* starts a new table with the same columns and keys (names with `_copy`).
1296
+ Defaults, checks and index expressions are single expressions (no `;` or comments).
1297
+ - **Run Statement** (**Ctrl/Cmd + Enter**) runs the statement at the cursor: the one the cursor is in, else the
1298
+ nearest one before it. A selection runs as it is, even when it holds several statements. The rows of the last
1299
+ query show in **Query Result**, up to 500, with row numbers, numbers right-aligned and NULL as *(null)*. The
1300
+ statement that ran is selected again afterwards. (sprint 92) Click a column heading to sort the rows, a cell to
1301
+ see its whole value (JSON indented), **Copy** for the rows as tab-separated text, and **All rows** to run the
1302
+ statement again for up to 10,000 rows. **Download** saves a SELECT as CSV, JSON, XML, Excel or SQL inserts
1303
+ through Unload Data (a read-only transaction, so the query runs once more).
1304
+ - **Run Script** (**F5**) runs every statement in order and writes **Script Output**: for each statement its line,
1305
+ the rows as text (up to 50), its notices, and its command tag like psql's (`CREATE TABLE`, `INSERT 0 2`,
1306
+ `SELECT 14`) with its time. An error says its line and column in the worksheet; the cursor goes to that line.
1307
+ The script stops at the first error unless **Continue on error** is on. psql meta-commands and `COPY … FROM
1308
+ STDIN` / `TO STDOUT` are skipped (use Load Data and Unload Data).
1309
+ - **Explain Plan** (**F10**) shows the plan of the statement at the cursor; nothing runs. **Autotrace** (**F6**) runs
1310
+ it with `EXPLAIN (ANALYZE, BUFFERS)` in a transaction that is rolled back, so an UPDATE or DELETE changes
1311
+ nothing. (sprint 92) The plan is a tree of steps: the operation, the table or index, cost, estimated rows and
1312
+ width, and the step's conditions (filter, index and join conditions, sort keys). Autotrace adds the actual time,
1313
+ rows, loops and buffers, the time spent in the step itself, marks the **slowest step**, and flags estimates that
1314
+ are 10 times too high or too low (run `ANALYZE` on the table). **Text plan** shows it like psql.
1315
+ - (sprint 97) **Chart** (**Ctrl + F11**, or *Chart* above the Query Result) draws the last query with pgkiln's
1316
+ own charts: the first text or date column gives the labels, the number columns the values; change the type (bar,
1317
+ column, stacked bar, line, area, donut, pie, scatter), the label column or the values and it draws again. Name it
1318
+ and **Save chart**: SQL Workshop → **Charts** lists the saved charts (shared by the workspace) and draws the ones
1319
+ on its dashboard; a chart's page changes its settings, opens its query in the worksheet or deletes it. A saved
1320
+ chart's SELECT runs read-only with a 10 second timeout and at most 500 rows.
1321
+ - **Notices** lists the `RAISE NOTICE`, `INFO` and `WARNING` messages of the last run with their time.
1322
+ **SQL History** (sprint 92) lists your last 200 statements in this workspace with how they ended, their rows and
1323
+ time; running the same statement again counts on its row (*3×*). Search it, show only the ones that failed or
1324
+ succeeded, click one to insert it at the cursor, **Run** to run it again, or copy it. Other developers' history
1325
+ never shows; 500 statements are kept per developer. The home page's *Recent SQL commands* opens it.
1326
+ - The status bar counts errors and warnings and shows the last message and its time.
1327
+ - (sprint 93) **Worksheets and files**: the worksheet's name is a menu with **Save** (**Ctrl/Cmd + S**), *Save as
1328
+ new*, *Rename*, **Download** (a `.sql` file), **New** and *Open…*. A worksheet is saved as a script of SQL Scripts
1329
+ (shared by the workspace's developers); the navigator's **Files** tab lists them, and SQL Scripts opens one in the
1330
+ worksheet. Several worksheets stay open as **tabs** above the editor (at most 20); a `*` marks text not saved yet.
1331
+ The tabs and their unsaved text are kept in the browser, so they survive a reload.
1332
+ - **Bind variables** (`:NAME`) and **substitution variables** (`&NAME.`) are asked for in a dialog before the run.
1333
+ A bind variable's value is a quoted literal (empty is NULL), so it can never change the statement; a substitution
1334
+ variable's text goes into the statement as it is (a table or column name, for instance). The values are
1335
+ remembered for the session; the history and the log keep the statement as written.
1336
+ - **Format** (**Ctrl + F7**) lays out the selection or the whole worksheet: a clause per line, the columns of a select
1337
+ list and the conditions of a WHERE one per line, joins and subqueries indented, keywords in lower or UPPER case
1338
+ (chosen in the **?** menu). Strings, comments and `$$` bodies stay as they are. **Convert case** (**Ctrl + B**)
1339
+ cycles the selection (or the word at the cursor) through UPPER, lower and Initial caps. **Find and replace**
1340
+ (**Ctrl + F**, **Ctrl + H**) with a regular expression or exact case, **Go to line** (**Ctrl + G**), and
1341
+ **Ctrl + /** comments the selected lines out or in. The **?** menu lists every key; **F1** opens this help. The
1342
+ upload button opens Load Data for the navigator's schema.
1343
+ - Each statement commits on its own. Statements run as the **owner connection** (an isolated workspace's
1344
+ developer login for its developers), on a connection of their own that is closed afterwards, so `SET ROLE` or
1345
+ `SET search_path` doesn't leak. **Run as** picks an application of your workspace instead: the statements then
1346
+ run as its database role, with `pgkiln.app_id` set, so its grants and row level security policies apply. Use
1347
+ it to test policies; it is no security boundary, since the SQL could `RESET ROLE`.
1348
+ - With script, the panes fill the window. Drag the splitters (or focus one and use the arrow keys) to resize
1349
+ them, hide the navigator, or use **Fullscreen** to see only the editor (**Escape** leaves). Sizes are
1350
+ remembered in the browser. Without script, the buttons post the form and the panes stack; Run Statement then
1351
+ runs every statement. The [code editor](#the-code-editor) suggests every schema, table, column and function
1352
+ you can use.
1263
1353
  - **Object Browser** (APEX's): the **schema** in the header and a tree with a
1264
1354
  folder per object type (tables, views, materialized views, indexes, sequences, types, functions, procedures,
1265
1355
  triggers) and a **filter** by name. pgkiln's own schemas (`meta`, `pgkiln_plugins`) and objects that belong to an
1266
1356
  extension show only with **Show system objects**. **Create** (and the tiles shown when nothing is selected) opens
1267
- SQL Commands with a CREATE TABLE, VIEW, FUNCTION, SEQUENCE or INDEX statement to fill in. A table opens in tabs:
1357
+ the SQL Worksheet with a CREATE TABLE, VIEW, FUNCTION, SEQUENCE or INDEX statement to fill in. A table opens in tabs:
1268
1358
  **Columns** (with comments; the toolbar's *Add*, *Modify* (type, nulls, default), *Rename* and *Drop column* write
1269
- the ALTER TABLE statement into SQL Commands to review and run: nothing changes until you press Run), **Data** (25
1359
+ the ALTER TABLE statement into the SQL Worksheet to review and run: nothing changes until you press Run), **Data** (25
1270
1360
  rows a page; NULL is a blank cell), **Indexes**, **Constraints**
1271
1361
  (primary key, foreign keys with the table they refer to, unique, check), **Triggers**, **Grants**, **Row level
1272
1362
  security** (on or off, the policies), **Dependencies** (views and foreign keys that use it, and what it uses),
1273
1363
  **Statistics** (rows, sizes, analyze and vacuum times) and **DDL**. A view has the same tabs where they apply; a
1274
1364
  function or procedure shows its source, a trigger, index, sequence or type its definition. (sprint 89) The tabs stay
1275
1365
  on one row: Columns, Data, Indexes, Constraints and DDL (and the current one), the others under **More**. The
1276
- schema shown is the one you chose last (remembered for the session), else the session's schema of SQL Commands,
1366
+ schema shown is the one you chose last (remembered for the session), else the session's schema of the SQL Worksheet,
1277
1367
  else the **parsing schema** of the application changed last in your workspace (the schema its database role
1278
1368
  uses).
1279
1369
  - **SQL Scripts**: saved scripts, shared by the developers of the workspace. Create one in the editor, upload a
@@ -1308,10 +1398,31 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1308
1398
  note. Each join can be inner or left. Drag a table by its handle, or focus the handle and use
1309
1399
  the arrow keys (Shift for bigger steps); it stays where it was left. On phones the tables are
1310
1400
  stacked. Then pick conditions (`=`, `<>`, `<`, `like`, `in (a, b)`, `is null` …, combined with
1311
- AND or OR), the sort, `distinct` and a row limit. The SELECT is shown and opens in SQL Commands.
1401
+ AND or OR), the sort, `distinct` and a row limit. The SELECT is shown and opens in the SQL Worksheet.
1312
1402
  The state is in the URL (tables in the order chosen, joins, functions and the tables' places), so
1313
1403
  a query can be bookmarked; everything except dragging works without JavaScript. Only names from
1314
1404
  the catalog and the fixed functions are used, and condition values are string literals.
1405
+ - **Data Modeler** (SQL Workshop → More → Data Modeler, `/builder/sql/modeler`): named relational
1406
+ **diagrams** of a schema's tables and views, kept per workspace and shared by its developers. Create
1407
+ one with a name, a schema and, optionally, the objects (`orders, customers`, `ord*`, or `*` for all);
1408
+ **Add objects to diagram** searches the schema (part of a name, a pattern with `*`, or `*`) and adds
1409
+ the ticked ones. Each object is a box with its columns, their types, `P` (primary key), `F` (foreign
1410
+ key), `U` (unique) and `*` for not null; a foreign key between two shown tables is a line from the
1411
+ referencing table (a crow's foot: many) to the referenced one (a bar: one), dashed with a circle
1412
+ when the foreign key may be empty. A box's name opens **Table Properties** (a view: the Object
1413
+ Browser). The toolbar: **Save** (Ctrl+S), **Undo** / **Redo** (Ctrl+Z, Ctrl+Y), **Zoom out** / **Zoom
1414
+ in** (or Ctrl+wheel), **Fit**, **Auto layout** (referenced tables to the left of the tables that
1415
+ reference them; undoable), a **Mini-map** (click or drag in it to move around), **SVG** and **PNG**
1416
+ exports of the diagram as shown, **Print**, **Generate DDL** (the CREATE statements of the shown
1417
+ objects with their keys, indexes, triggers, row level security, policies, comments and grants: to
1418
+ download or open in the SQL Worksheet) and **Data dictionary** (each object's columns with type,
1419
+ nullability, default, keys and comments, its constraints and what references it; to print, save as
1420
+ PDF from the print dialog, or download as an HTML file). Drag a box to move it, or focus it and use
1421
+ the arrow keys (Shift for bigger steps). The diagram keeps only the objects' names and positions
1422
+ (`meta.sql_diagram`): columns and keys are read from the catalog each time, so it never goes stale;
1423
+ an object dropped from the schema is reported and left out on the next save. Without JavaScript the
1424
+ diagram shows at its saved positions, and adding, removing, auto layout, Export SVG, DDL and the
1425
+ dictionary all work. Diagrams are installation data, not exported with applications.
1315
1426
  - **Load Data**: load a CSV, TSV, Excel, JSON or XML file into a new table (with inferred column
1316
1427
  types) or an existing one (append, merge by primary key, or replace), with a per-row error
1317
1428
  report, or with a saved **data load definition**; a mapping can be saved as one
@@ -1345,6 +1456,15 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1345
1456
  has (commented out), columns whose identity or generation differs, and types, domains and
1346
1457
  sequences that differ. The same from the command line (`pgkiln ddl`, `pgkiln compare`,
1347
1458
  [chapter 18](18-cli.md)) and for AI agents (`generate_ddl`, `compare_schemas`).
1459
+ - **RESTful Services** (`/builder/sql/rest`, sprint 100; Database Actions: REST › AutoREST): publish a table or
1460
+ view as REST endpoints. Choose the object (of a schema the SQL Workshop may use), the **application** it is
1461
+ published through, a URL name, the **methods** (GET: rows and one row; POST; PUT; DELETE; single rows need a primary
1462
+ key), **who may call it** (a bearer token of the application, or explicitly *public*), optional application
1463
+ **roles** and the page size. The application decides the rest: the statements run as its database role (never the
1464
+ object's owner, a superuser or a role that bypasses row level security), with its tokens and OAuth clients and its
1465
+ accounts' roles. The object's page checks the role's grants per method, row level security and (for a view)
1466
+ `security_invoker`, lists the endpoints with their URLs, and shows cURL and `fetch` examples and the OpenAPI link.
1467
+ Details in [chapter 13](13-rest-api.md#autorest-tables-and-views-from-the-sql-workshop).
1348
1468
  - **Utilities** (`/builder/sql/utilities`; APEX: SQL Workshop → Utilities): tiles for Load and Unload Data, Sample
1349
1469
  Data, the Query Builder, DDL and Compare, and three pages of their own. Each runs in a read-only transaction with a
1350
1470
  15-second statement timeout, on the SQL Workshop's connection (an isolated workspace's developers see only the
@@ -1358,9 +1478,46 @@ others (Quick SQL, Query Builder, Load and Unload Data, Sample Data, DDL, Compar
1358
1478
  - **Database Monitor** (administrators only): the client sessions of this database from `pg_stat_activity`, active
1359
1479
  first, with their state, wait event, running time, the sessions that block them and the query (as far as the
1360
1480
  owner may read other roles' statistics). Read only: it cancels nothing.
1481
+ - **Database Users** (administrators only; Administration menu → *Database users*, `/builder/db-users`; sprint 99,
1482
+ Database Actions: Database Users): see [Database users](#database-users).
1361
1483
 
1362
1484
  Because the SQL Workshop runs as the owner, restrict who gets a developer account.
1363
1485
 
1486
+ ### Database users
1487
+
1488
+ (sprint 99; Database Actions: Database Users) **Administration → Database users** (administrators only; also on the
1489
+ SQL Workshop's Launchpad under *Administration*) lists the PostgreSQL roles of the server (`pg_roles`; the predefined
1490
+ `pg_` roles are left out): whether they can sign in, superuser / create DB / create role / bypass RLS / replication,
1491
+ the connection limit, **valid until** (with *in N days* or *expired*), the roles they are a member of and what they own
1492
+ (schemas, objects in this database, objects elsewhere). PostgreSQL doesn't record when a role was created.
1493
+ The tiles on top filter the list: roles that can sign in, **passwords that expire within 30 days**, roles with
1494
+ **BYPASSRLS**, roles **without sign-in that own objects**, and pgkiln's own roles; a search field filters by name.
1495
+
1496
+ **Create database user** (or a role's page) is a form: name, *Can sign in* (LOGIN), the password (*No password* /
1497
+ *Set a password*; for an existing role *Keep*, *Set a new password* or *Remove*), **valid until** (a date; empty: no
1498
+ expiry), the connection limit, the roles it is a **member of** (group roles and the predefined roles; not pgkiln's own,
1499
+ superusers, login roles or the roles that reach the server's files), its **default schema** (the search path in this
1500
+ database: `ALTER ROLE … IN DATABASE … SET search_path`), a comment, and per schema **Usage** and **Create**,
1501
+ **Future tables** (default privileges, *read* or *read and write*, on what pgkiln's owner connection creates there) and
1502
+ **Existing tables** (a one-off grant or revoke on the tables there now). pgkiln's own schemas aren't offered.
1503
+
1504
+ **Review SQL** shows the statements (only what differs from what the catalog says now), with the password as
1505
+ `'********'`; the password itself is typed on that page (twice) and **Apply** runs the statements in one
1506
+ transaction: all or none, and the error with the statement that failed. Apply runs only what the review showed:
1507
+ when the form or the role changed in between, the review comes again. The masked statements go to the activity log
1508
+ (event `db_role`).
1509
+
1510
+ **Drop role…** lists what the role owns and warns about objects in other databases; it reassigns them to another role
1511
+ (`REASSIGN OWNED`) or, with a tick, drops them (`DROP OWNED`), revokes its privileges in this database and drops the
1512
+ role, again after showing the SQL.
1513
+
1514
+ pgkiln's **own roles** are marked *pgkiln* and are read only here: the owner and runtime connections (`DATABASE_URL`,
1515
+ `RUNTIME_DATABASE_URL`), every `pgkiln…` role (`pgkiln_runtime`, `pgkiln_app_code`, `pgkiln_authenticator`,
1516
+ `pgkiln_anon`, isolated workspaces' logins) and the bootstrap superuser. Roles **in use** by an application (parsing
1517
+ schema, REST API role) or an isolated workspace can be changed but not dropped. New names can't start with `pg_` or
1518
+ `pgkiln`. The owner connection needs `CREATEROLE` (and, on PostgreSQL 16 and later, ADMIN on roles it didn't create)
1519
+ for these changes; PostgreSQL's own error says so otherwise.
1520
+
1364
1521
  ## Export and import
1365
1522
 
1366
1523
  **Export** downloads the application as JSON: pages, all components, shared components and
@@ -507,10 +507,28 @@ matures. Privileges show up in **SQL Workshop → Object Browser**.
507
507
  A `data_load` process loads files as the app role too, also with a data load definition: a
508
508
  definition naming a table the role can't write fails like any other insert, and a process only
509
509
  finds the definitions of its own application. XML files with a document type declaration are
510
- refused ([chapter 16](16-files.md#data-loading)). The SQL Workshop (SQL Commands, SQL Scripts,
510
+ refused ([chapter 16](16-files.md#data-loading)). The SQL Workshop (the SQL Worksheet, SQL Scripts,
511
511
  Quick SQL, Load Data, Unload Data, Sample Data) runs as the owner instead, so every developer can change any table: keep
512
512
  developer accounts to people you trust with the database.
513
513
 
514
+ The REST endpoints pgkiln serves (an application's REST modules and the tables and views published with **SQL
515
+ Workshop → RESTful Services**, AutoREST) run as the app role too, never as the owner: these grants, column grants
516
+ and the row level security below decide what an API caller may read and change. AutoREST refuses a role that owns
517
+ the published object or bypasses row level security, and an object answers only to a bearer token of its application
518
+ unless the developer chose *public* for it ([chapter 13](13-rest-api.md#autorest-tables-and-views-from-the-sql-workshop)).
519
+
520
+ ### Database users and their passwords
521
+
522
+ (sprint 99) Administrators create and change PostgreSQL roles in the builder (**Administration → Database users**,
523
+ [chapter 3](03-builder.md#database-users)). Passwords never reach PostgreSQL or a page in plain text: pgkiln hashes
524
+ a new password itself into a **SCRAM-SHA-256 verifier** (random salt, 4096 iterations, SASLprep, like psql's
525
+ `\password`) and the statement carries only that verifier, as a literal built with pg's `escapeLiteral`. The review
526
+ and the activity log show `PASSWORD '********'`; the password is typed on the review page, posted once with Apply and
527
+ not stored, echoed or logged. A server with `log_statement = ddl` logs the verifier, not the password. Every name is
528
+ quoted with `escapeIdentifier`, every value is checked (dates, numbers, schema names, grantable roles) and quoted.
529
+ The page is for administrators only (others get 403), every change needs the CSRF token, and pgkiln's own roles can't
530
+ be changed, dropped or granted from it, so the page can't take pgkiln's own connections away.
531
+
514
532
  ## Session state protection
515
533
 
516
534
  - **URL items**: on pages with protection *Arguments must have checksum* (the default), item
@@ -20,7 +20,7 @@ Then open http://127.0.0.1:3100/a/tasks and sign in as `ann` / `ann-password` or
20
20
 
21
21
  ## Step 1: the table and the business logic
22
22
 
23
- Open **SQL Workshop → SQL Commands** and run:
23
+ Open **SQL Workshop → SQL Worksheet**, paste this and press **Run Script** (F5):
24
24
 
25
25
  ```sql
26
26
  create schema tasks;