OriginChainDB
Ask

Inspect how Ask answers

← Ask examples

The language tabs use earlier client interfaces. Check SDK versions and connection setup before running them.

Request show_plan to see the operations used to answer the question. Check the plan to confirm the intended table and filter.

Before you run it: Putting show_plan in the URL does not enable it. Plans may change with schemas and indexes.

A query plan is a list of database operations. In this example, IndexScan finds paid orders and Aggregate(count) counts them. Read those operations alongside the returned count before relying on the answer.

See how a question becomes a countRequest the plan in the body with show_plan: true.
  1. Ask about paid ordersThe question names the rows you want to count.
  2. Inspect the query planCheck the orders table, paid filter and counting step.
  3. Verify the countCompare the answer with the paid sample rows.

Follow the example

  1. Load the sample and confirm Ask is enabled.
  2. Set show_plan: true in the JSON body.
  3. Send the question.
  4. Compare the plan and rows with the intended filter.

Set up the table

Save this definition as orders.toml and send it to POST /v1/tenants/:t/schemas with Content-Type: text/plain before loading rows. The schema walkthrough shows how to register a file; use this page's definition for its sample.

namespace   = "shop"
table       = "orders"
primary_key = ["id"]

[[columns]]
name = "id"
ty   = "str"
required = true

[[columns]]
name = "customer_id"
ty   = "str"

[[columns]]
name = "amount"
ty   = "f64"

[[columns]]
name = "status"
ty   = "str"

[[indexes]]
name    = "by_status"
columns = ["status"]

Load sample rows

# Seed a handful of paid and pending orders so the plan has work to do.
curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/rows/shop.orders/_batch" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '[
    { "id": "o_1", "customer_id": "c_1", "amount": 19.00, "status": "paid"    },
    { "id": "o_2", "customer_id": "c_2", "amount": 42.00, "status": "paid"    },
    { "id": "o_3", "customer_id": "c_1", "amount": 11.50, "status": "pending" }
  ]'

Run the request

curl -X POST "https://$OC_HOST/v1/tenants/$OC_TENANT/ask" \
  -H "Authorization: Bearer $OC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "nl":        "count of paid orders",
    "schemas":   ["shop.orders"],
    "show_plan": true
  }'

Check the result

The response includes the plan alongside rows and cache information.

{
  "rows": [
    { "count": 2 }
  ],
  "cache": "miss",
  "plan": {
    "Aggregate": {
      "group": [],
      "aggs":  [ { "Count": { "alias": "count" } } ],
      "child": {
        "Filter": {
          "predicate": { "Eq": { "path": "status", "value": "paid" } },
          "child":     { "IndexScan": { "schema": "shop.orders", "index": "by_status" } }
        }
      }
    }
  }
}

The plan field is the same JSON the engine's /v1/query endpoint accepts as input. Lift it, store it, replay it - the planner is deterministic for a fixed schema set.

Understand the behavior

  • The compiler runs as usual. When show_plan is true, the resulting plan tree is serialised back into the response alongside the rows.
  • The plan here is Aggregate(count) → Filter(status = paid) → IndexScan(by_status). The presence of IndexScan instead of plain Scan tells you the planner picked up the by_status index.
  • If you see Scan where you expected IndexScan, the index probably doesn't cover the predicate - add an index or rephrase.

Important limits and checks

  • Putting show_plan in the URL. It's a body field. The query string is ignored.
  • Logging the plan tree on every request. It's a few KB and changes the response shape. Use it during development; turn it off in app code.
  • Assuming the plan is stable across schema changes. Adding or dropping an index re-plans. The previous plan tree is no longer the one the engine will run - re-fetch it.

Continue

Continue to make a question answerable.

© 2026 Silicoyn Technologies Pvt Ltd

On this page