TotalBase
Concepts

Resources

Tables, views and functions as TotalBase resources: identity, exposure and what renaming or recreating them does.

A resource is a PostgreSQL object that TotalBase knows about and can make available through the Data API. There are three types:

TypePostgreSQL objectsData API actions
TABLEordinary and partitioned tablesread, create, update, delete
VIEWviews and materialized viewsread
FUNCTIONfunctionsexecute

Some objects never become resources: procedures, sequences, foreign tables, a partition (it belongs to its parent table), trigger functions, objects owned by an extension, and anything in pg_catalog, information_schema or the reserved totalbase schema. Types such as enums, domains, arrays and jsonb aren't resources either. They are column types that TotalBase understands.

Discovered, then exposed

TotalBase reads PostgreSQL's catalog at startup, after DDL it runs itself, and whenever the catalog changes. Each new table, view or function becomes a resource automatically. Nothing is exposed automatically. A new resource has no HTTP methods, so the API doesn't know it exists.

You expose a resource by choosing its methods, in the resource's Endpoints dialog in Database:

TypeMethods you can enable
TABLEGET, POST, PATCH, DELETE
VIEWGET
FUNCTIONPOST

Exposure is a ceiling, and permissions work below it. If DELETE is off for work_orders, no request can delete a work order through the API, whatever a role is granted. A method that is on still needs a permission. Exposure grants nothing by itself.

The Endpoints dialog of work_orders: GET, POST and PATCH on, DELETE off.
The Endpoints dialog of work_orders: GET, POST and PATCH on, DELETE off.

A resource that isn't exposed, or a method that is off, returns 404 RESOURCE_NOT_FOUND, the same answer as a table that doesn't exist. Callers can't find out which tables exist by probing the API.

Acme exposes:

  • work_orders, visits, customers, sites: GET, POST, PATCH (orders are cancelled, never deleted);
  • vehicle_positions: GET and POST only (positions are only ever added);
  • the views vehicles_latest_positions and work_orders_overview: GET;
  • the function create_invoice_from_work_order: POST.

Addresses

A resource is addressed by its schema and name, with its type spelled out:

/api/public/table/work_orders
/api/public/view/work_orders_overview
/api/public/function/create_invoice_from_work_order

Identity follows the OID

PostgreSQL gives every table, view and function an internal identifier, its OID, which doesn't change when the object is renamed. TotalBase ties each resource to that OID, not to its name:

You doPostgreSQLTotalBase
ALTER TABLE orders RENAME TO work_orderssame OIDthe same resource: exposure, permissions, presentation and DataViews follow it to the new name
ALTER TABLE ... SET SCHEMA fieldsame OIDthe same resource, in its new schema
DROP TABLE work_orders; CREATE TABLE work_orders (...)new OIDa new resource: hidden, no permissions

The last case is on purpose. A table that was dropped and created again may hold different data, so TotalBase never gives the new table the old one's permissions just because the name matches. You expose it and grant permissions on it again.

Columns work the same way: a renamed column keeps its label and its place in DataViews. A dropped and re-added column is a new column.

Status

A resource is ACTIVE while its object exists. When the object is dropped, the resource becomes MISSING and is then removed, along with its permissions. A resource that a DataView still uses stays MISSING until you fix that DataView, so the DataView can show what it lost.

What TotalBase keeps about a resource

Everything structural (columns, types, keys, constraints, indexes, relations, function signatures) is read from PostgreSQL every time. TotalBase stores only what PostgreSQL can't:

  • its exposed methods;
  • a description, kept in step with PostgreSQL's COMMENT ON;
  • the presentation of each column: its label, its format and the control that edits it. DataViews and dashboards use it, and every screen that shows the column inherits it.
  • the default sort a read uses when it doesn't ask for one;
  • auditing: whether reads are logged, and which columns are kept out of the log;
  • for a function, a classification (QUERY or ACTION) that helps describe it.

TotalBase's own tables

TotalBase's own tables (users, roles, files, the audit log and the rest) live in the totalbase schema. They are resources too, reachable at /api/totalbase/table/users and similar addresses, but their exposure is fixed by TotalBase, some columns (password hashes, token hashes) can never be read, and the tables that grant access can only be written by administrators. See Delegated administration.

Next steps