Skip to content
This page View Markdown Open in ChatGPT Open in Claude

Get table meta

Describes a table : the name and the type of every column (or of every field found in a MongoDB collection), in the same format for every database. Migration scripts use it to check whether a column exists before adding it.

Method POST
URL /api/system-api/admin/get-table-meta : admin is the user path of your account
Body { instance, database, collection } or an array of them
Answer data : an array of fields, or an array of arrays
From code g.sys.system.getTableMeta

The call

Body
{ "instance": "mysql8", "database": "inventory", "collection": "customers" }
Answer
{
    "success": true,
    "statusCode": 200,
    "data": [
        { "name": "customer_id", "path": "customer_id", "count": 24, "total_count": 24, "type": "Number", "has_duplicates": false, "probability": 1 },
        { "name": "first_name", "path": "first_name", "count": 24, "total_count": 24, "type": [ "String", "Null" ], "has_duplicates": true, "probability": 1 }
    ]
}
Key Meaning
name, path The column, with its path for nested MongoDB fields.
type The type, or the list of types seen (MongoDB).
count, total_count, probability For MongoDB, in how many of the sampled documents the field appears.
has_duplicates Whether the same value appears twice in the sample.
  • table works in place of collection. An array of tables answers an array of arrays, in the same order.
  • A table of a tenant : "instance": "crm::acme", or the header x-am-tenant-username.

From code

A migration which adds a column once
const meta = await g.sys.system.getTableMeta({ instance: 'mysql8', database: 'inventory', table: 'order_transactions' });
if (!meta.find(c => c.name === 'description')) {
    await g.sys.system.executeQuery({ instance: 'mysql8', query: 'ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL' });
}
A migration which adds a column once
meta = await g.sys.system.get_table_meta(instance='mysql8', database='inventory', table='order_transactions')
if not any(column.name == 'description' for column in meta):
    await g.sys.system.execute_query('mysql8', 'ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL')
A migration which adds a column once
$meta = $g->sys->system->getTableMeta(instance: 'mysql8', database: 'inventory', table: 'order_transactions');
if (!array_filter($meta, fn ($column) => $column->name === 'description')) {
    $g->sys->system->executeQuery('mysql8', 'ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL');
}
A migration which adds a column once
var meta = await g.Sys.System.GetTableMeta(new GetTableMeta { Instance = "mysql8", Database = "inventory", Table = "order_transactions" });
if (!meta.Any(column => column.Name == "description"))
{
    await g.Sys.System.ExecuteQuery(new ExecuteQuery("mysql8", "ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL"));
}
A migration which adds a column once
meta, err := g.Sys.System.GetTableMeta(am.GetTableMeta{Instance: "mysql8", Database: "inventory", Table: "order_transactions"})
if err != nil {
    return nil, err
}
found := false
for _, column := range meta {
    found = found || column.Name == "description"
}
if !found {
    if _, err := g.Sys.System.ExecuteQuery(am.ExecuteQuery{Instance: "mysql8", Query: "ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL"}); err != nil {
        return nil, err
    }
}
A migration which adds a column once
let meta = g.sys.system.get_table_meta(GetTableMeta::default().instance("mysql8").database("inventory").table("order_transactions"))?;
if !meta.iter().any(|column| column.name == "description") {
    g.sys.system.execute_query(ExecuteQuery::new("mysql8", "ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL"))?;
}
A migration which adds a column once
List<TableMetaField> meta = g.sys.system.getTableMeta(new GetTableMeta().instance("mysql8").database("inventory").table("order_transactions"));
if (meta.stream().noneMatch(column -> "description".equals(column.getName()))) {
    g.sys.system.executeQuery(new ExecuteQuery("mysql8", "ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL"));
}
A migration which adds a column once
val meta = g.sys.system.getTableMeta(GetTableMeta().instance("mysql8").database("inventory").table("order_transactions"))
if (meta.none { it.name == "description" }) {
    g.sys.system.executeQuery(ExecuteQuery("mysql8", "ALTER TABLE `inventory`.`order_transactions` ADD COLUMN `description` varchar(255) NULL"))
}

A table of a tenant

  • instance: "crm::acme" reads the table in the database of the tenant acme of the multi-tenant instance crm. In a custom API called for a tenant, instance: "crm" reads it in the database of that tenant.
1
2
3
4
5
await g.sys.system.getTableMeta({
    instance: 'crm::acme',
    database: 'crm',
    collection: 'customers'
});
1
2
3
4
5
await g.sys.system.get_table_meta(
    'crm::acme',
    'crm',
    'customers',
)
1
2
3
4
5
$g->sys->system->getTableMeta(
    'crm::acme',
    'crm',
    'customers',
);
await g.Sys.System.GetTableMeta(new GetTableMeta("crm::acme", "crm", "customers"));
1
2
3
4
5
6
7
if _, err := g.Sys.System.GetTableMeta(am.GetTableMeta{
    Instance:   "crm::acme",
    Database:   "crm",
    Collection: "customers",
}); err != nil {
    return nil, err
}
g.sys.system.get_table_meta(GetTableMeta::new("crm::acme", "crm", "customers"))?;
g.sys.system.getTableMeta(new GetTableMeta("crm::acme", "crm", "customers"));
g.sys.system.getTableMeta(GetTableMeta("crm::acme", "crm", "customers"))

Access and settings

  • Over HTTP, a system API answers once its settings give it apiAccessType: TOKEN_ACCESS (the token of an API user whose group grants this system API, in x-am-authorization) or IS_PUBLIC. Without settings it is NO_ACCESS : your code calls it through g.sys, the admin panel tests it, and an HTTP call is refused.
  • The settings can also cache the answer or require person tokens (authProviders) ; pre and post hooks run around it like around any API.
  • The request headers apply : x-am-response-case, x-am-content-type-response, x-am-internationalization, x-am-tenant-username…

Errors

Code When
400 The body is wrong : the message names the missing or invalid key.
401 No valid API user token, or the API is NO_ACCESS : You are not authorized to access this API.
403 No group grants this system API.