Skip to main content

Extension Model

The provided languages are built on the same public extension points that are available to you, so you can add behavior at every level, from a single function to an entire language, without forking the engine.

You want to add...Do thisGuide
a function, operator, aggregate, or castbundle it as an extensionFunctions & Aggregates
a way to read a differently-shaped sourcewrite a data adapterData Adapters
a specialized access structurewrite an index typeCustom Index Types
a plan rewritewrite an optimizer ruleOptimizer Rules
a whole query languagewrite a language plug-inAuthoring a Language

Bundle it as an extension​

The lightest extension point is an Extension: a bundle of operators, functions, aggregates, and castables that you pass to the engine.

new DortDB({
mainLang: SQL(),
optimizer: { rules: defaultRules },
extensions: [datetime, myExtension],
});

Two optional fields shape what the bundle contributes: scope limits it to specific languages (for aggregates that only make sense in Cypher, say), and schema namespaces every member under a prefix. Note that only some languages support user-defined operators, SQL among them.

Adding to the algebra​

The deeper extension points, new index types, new optimizer rules, and new languages, often involve new plan operators. Because the core dispatches plan traversal through per-language visitors, a new operator can be introduced entirely inside your own package: you implement the visitor methods for it and the core stays untouched.

The catch is that every pass over the plan must know about your operator. Plan Visitors lists those passes and what each one needs from you; the formal description of the operators themselves is in the Formalism section.