aster.Web Data / Docs Aster UI ↗

Aster Web Data / Start here

Connect your own database

Generate DataSources from the tables you already have, review them, check them against the database and serve them.

If your tables already exist, you don't write the model from nothing. The scaffold command reads the database's catalog and writes one DataSource per table, with the types, keys, lengths and foreign keys filled in, and a configuration that serves them. You review the files, run check, and start the server. Scaffold reads no rows and changes nothing in the database.

It works on every SQL database Aster Web Data supports. TigerBeetle has a fixed catalog, so there is nothing to scaffold.

Scaffold from your schema

Put the connection URL in an environment variable, and give scaffold the database's kind, the variable's name and the schema to read. The URL itself never goes on the command line, where it would show in the process list and the shell history:

export SHOP_DATABASE_URL='postgres://reader@db.example.com:5432/shop'
aster-webdata-server scaffold --kind postgres --url-env SHOP_DATABASE_URL --database shop --schema sales

Suppose the sales schema holds customers and orders, orders.customer_id references customers(id), and orders.discount is a money column. Without --out, scaffold prints the files, each headed by its name:

$ aster-webdata-server scaffold --kind postgres --url-env SHOP_DATABASE_URL --database shop --schema sales
---
# customers.ds.yaml
# Written by `aster-webdata-server scaffold` from the database catalog.
# A starting point for the technical mapping layer: it records how the data is stored, not what it means.
# Schemas are often denormalised, or have missing or wrong foreign keys. Review it, edit it, then commit it.
ID: customers
database: shop
fields:
- canSave: false
  name: id
  primaryKey: true
  required: true
  type: integer
- collation: en_US.UTF-8
  length: 100
  name: name
  required: true
  type: text
- collation: en_US.UTF-8
  length: 200
  name: email
  required: false
  type: text
- collation: en_US.UTF-8
  defaultValue: EU
  length: 8
  name: region
  required: true
  type: text
schema: sales
tableName: customers
title: Customers of the shop

---
# orders.ds.yaml
# Written by `aster-webdata-server scaffold` from the database catalog.
# A starting point for the technical mapping layer: it records how the data is stored, not what it means.
# Schemas are often denormalised, or have missing or wrong foreign keys. Review it, edit it, then commit it.
# Unsupported column: native type money has no exact engine mapping
# length: null
# name: discount
# nativeName: discount
# nativeType: money
# precision: null
# required: false
# scale: null
ID: orders
database: shop
fields:
- canSave: false
  name: id
  primaryKey: true
  required: true
  type: long
- foreignKey: customers.id
  inverseName: orders
  name: customer_id
  required: true
  type: integer
- name: placed_at
  precision: 6
  required: true
  type: datetime
- name: total
  precision: 12
  required: true
  scale: 2
  type: decimal
- collation: en_US.UTF-8
  defaultValue: open
  name: status
  required: true
  type: text
schema: sales
tableName: orders

---
# service.yaml
# Written by `aster-webdata-server scaffold` from the database catalog.
# A starting point for the technical mapping layer: it records how the data is stored, not what it means.
# Schemas are often denormalised, or have missing or wrong foreign keys. Review it, edit it, then commit it.
databases:
  shop:
    kind: postgres
    setup: existing
    url_env: SHOP_DATABASE_URL
services:
  odata:
    datasources:
    - customers.ds.yaml
    - orders.ds.yaml

The foreign key has become a navigation: customer_id carries foreignKey: customers.id, so each order links to its customer and each customer gets an orders list. The discount column stays a comment that gives the reason, because no field type stores money exactly. service.yaml is a complete configuration: the database with setup: existing, and a service named odata that lists both files.

Add --out model to write the files into a folder. Scaffold will not overwrite a file there unless you add --force.

If your configuration already describes the database, name it instead of the kind: --config server.yaml --database shop. Repeat --schema to read several schemas, and choose tables with --include and --exclude, which take * and ? patterns. Quote the patterns so the shell leaves them alone:

aster-webdata-server scaffold --config server.yaml --database shop \
    --schema public --schema billing --include 'orders*' 'customers' 'invoice*' --out model

Review what it generated

The catalog records how the data is stored, not what it means, so read each file before you publish it:

Model your data describes every option you may want to change.

Check against the database

check compares every DataSource with its table, without serving:

aster-webdata-server check --config model/service.yaml

It lists each source as database.schema.table, and for each mismatch says what to declare to fix it, such as a precision or a collation. Run it again after you edit the files, and in your deployment pipeline:

Exit code Meaning
0 Every source matches its table
1 A mismatch, or a catalog that cannot be read
2 The configuration is invalid

Change the model shows what check reports and what the server does when a database fails it at start-up.

Serve it

Start the server with the generated configuration. Its service is served at /odata:

aster-webdata-server --config model/service.yaml

Or merge its databases and services entries into your own configuration, and rename the service. The database user needs the read and write privileges your sets use, which What runs on your database lists.