<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.memcp.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wikiservice</id>
	<title>MemCP - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.memcp.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wikiservice"/>
	<link rel="alternate" type="text/html" href="https://www.memcp.org/wiki/Special:Contributions/Wikiservice"/>
	<updated>2026-08-29T06:55:08Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.1</generator>
	<entry>
		<id>https://www.memcp.org/index.php?title=Main_Page&amp;diff=408</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Main_Page&amp;diff=408"/>
		<updated>2026-08-28T10:14:06Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MemCP Database – Fast, Compressed SQL for OLTP and OLAP =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:2.5rem 2rem; margin:0 0 1.5rem; border-radius:14px; background:linear-gradient(135deg,#3d6208 0%,#64910c 52%,#76b512 100%); color:#fff; text-align:center;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:2.6rem; line-height:1.1; font-weight:700; margin-bottom:.7rem;&amp;quot;&amp;gt;MemCP&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.45rem; line-height:1.35; font-weight:600; margin:0 auto .9rem; max-width:56rem;&amp;quot;&amp;gt;A fast, compressed, MySQL-protocol-compatible columnar database for modern OLTP and OLAP workloads&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.05rem; line-height:1.6; margin:0 auto 1.4rem; max-width:54rem;&amp;quot;&amp;gt;MemCP is an open-source SQL database written in Go. It combines persistent in-memory operation, adaptive column compression, parallel query execution and direct application APIs so operational data can be queried and analyzed without maintaining a separate analytical copy.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-bottom:1.5rem;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block; padding:.2rem .65rem; margin:.15rem; border:1px solid #ffffff88; border-radius:1rem;&amp;quot;&amp;gt;Beta&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; padding:.2rem .65rem; margin:.15rem; border:1px solid #ffffff88; border-radius:1rem;&amp;quot;&amp;gt;Open Source&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; padding:.2rem .65rem; margin:.15rem; border:1px solid #ffffff88; border-radius:1rem;&amp;quot;&amp;gt;MySQL Protocol + HTTP APIs&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;plainlinks&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block; margin:.25rem;&amp;quot;&amp;gt;[[Install MemCP with Docker|&amp;lt;span style=&amp;quot;display:inline-block; padding:.65rem 1rem; border-radius:6px; background:#fff; color:#496f0c; font-weight:700;&amp;quot;&amp;gt;Get started with Docker&amp;lt;/span&amp;gt;]]&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; margin:.25rem;&amp;quot;&amp;gt;[[Supported SQL|&amp;lt;span style=&amp;quot;display:inline-block; padding:.65rem 1rem; border:1px solid #fff; border-radius:6px; color:#fff; font-weight:700;&amp;quot;&amp;gt;Explore SQL support&amp;lt;/span&amp;gt;]]&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; margin:.25rem;&amp;quot;&amp;gt;[https://github.com/launix-de/memcp &amp;lt;span style=&amp;quot;display:inline-block; padding:.65rem 1rem; border:1px solid #fff; border-radius:6px; color:#fff; font-weight:700;&amp;quot;&amp;gt;View on GitHub&amp;lt;/span&amp;gt;]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Memcp-Load.png|center|frameless|1000px|alt=MemCP database dashboard and workload overview]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.85rem 1rem; margin:1rem 0 2rem; border-left:5px solid #d99b00; background:#fff7d6; color:#332600;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Development status: Beta.&#039;&#039;&#039; MemCP is under active development. Check [[Supported SQL]], [[Current Status and Open Issues]] and the durability requirements of your workload before migrating production data.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.15rem; margin:1rem 0 2rem; border-left:5px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Your MySQL queries are too slow?&#039;&#039;&#039; Run the same representative workload on MemCP instead of assuming another index or a larger MySQL server is the only answer. Compare results, durability and authenticated end-to-end latency; if the migration gates pass, move the performance-critical workload to MemCP. [[MySQL is too slow|Start the MemCP performance evaluation →]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.15rem; margin:1rem 0 2rem; border:1px solid #b7c99a; border-radius:9px; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Observed performance profile:&#039;&#039;&#039; MemCP has achieved &#039;&#039;&#039;speedups of 10× and more over MariaDB/PostgreSQL&#039;&#039;&#039; in measured OLAP and search-oriented workflows, where RecSets and compressed column scans avoid wide row materialization. In one filtered-list workflow over roughly one million documents, the same query took around &#039;&#039;&#039;30 seconds on PostgreSQL&#039;&#039;&#039; and &#039;&#039;&#039;1.6 seconds on MemCP&#039;&#039;&#039;. Isolated OLTP paths currently take about &#039;&#039;&#039;1.3–2.0× as long&#039;&#039;&#039;, but in complete WordPress- and wiki-style page builds this has made &#039;&#039;&#039;no significant difference to overall page-loading time&#039;&#039;&#039; in the measured application workflows. These are workload observations, not universal guarantees; [[Performance Measurement|reproduce them on your data]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is MemCP? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MemCP Database&#039;&#039;&#039; is a persistent, compressed, column-oriented SQL database for mixed OLTP and OLAP workloads. It speaks the MySQL client protocol, also exposes SQL over HTTP, and executes supported queries through a functional compiler and a parallel column-storage engine.&lt;br /&gt;
&lt;br /&gt;
The name on this site refers to the database project. MemCP Database is &#039;&#039;&#039;not&#039;&#039;&#039; a Model Context Protocol (MCP) memory server and is unrelated to the C/C++ &amp;lt;code&amp;gt;memcpy()&amp;lt;/code&amp;gt; memory-copy function. When writing about or linking to the project, the unambiguous name is &#039;&#039;&#039;MemCP Database&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Problems MemCP solves ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:1rem; margin:1rem 0 2rem;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Slow filtered lists on millions of rows&amp;lt;/div&amp;gt;&lt;br /&gt;
Complex &amp;lt;code&amp;gt;WHERE&amp;lt;/code&amp;gt;, joins, membership tests, &amp;lt;code&amp;gt;ORDER BY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LIMIT&amp;lt;/code&amp;gt; can make a row store inspect or materialize far more data than the page returns. MemCP uses RecSets, late materialization, adaptive indexes and ordered braking to keep the working domain compact.&amp;lt;br /&amp;gt;[[MySQL is too slow|Evaluate the query]] · [[RecSets|How RecSets work]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Slow GROUP BY, COUNT and dashboards&amp;lt;/div&amp;gt;&lt;br /&gt;
Column scans read only referenced compressed values. Parallel shard-local aggregation, group caches and computed structures target repeated analytical queries over fresh operational data.&amp;lt;br /&amp;gt;[[Columnar Storage]] · [[Temporary Computed Columns]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Slow database writes caused by fsync&amp;lt;/div&amp;gt;&lt;br /&gt;
Durability is selectable per table. &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; protects commits through power loss; &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; has measured about 10× its write throughput when process-crash recovery is sufficient.&amp;lt;br /&amp;gt;[[Persistency and Performance Guarantees|Choose a write strategy]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Database writes wear out an SD card&amp;lt;/div&amp;gt;&lt;br /&gt;
For reconstructible edge data, &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; avoids a continuous WAL and normally publishes one compressed generation every 15 minutes, reducing constant flash writes while making the loss window explicit.&amp;lt;br /&amp;gt;[[Hardware Requirements]] · [[Persistency and Performance Guarantees]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Choose your path ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:1rem; margin:1rem 0 2rem;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Evaluate MemCP&amp;lt;/div&amp;gt;&lt;br /&gt;
Understand the workload model, current status, hardware needs and differences from MySQL.&lt;br /&gt;
&lt;br /&gt;
[[What is OLTP and OLAP|OLTP and OLAP]] · [[Comparison: MemCP vs. MySQL|Compare with MySQL]] · [[Hardware Requirements|Hardware requirements]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Build an application&amp;lt;/div&amp;gt;&lt;br /&gt;
Use the MySQL protocol, SQL over HTTP, RDF or application-specific endpoints inside MemCP.&lt;br /&gt;
&lt;br /&gt;
[[Advanced SQL Tutorial|SQL tutorial]] · [[SQL over REST|SQL over HTTP]] · [[Database Tools compatibility with MemCP|Client tooling]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Operate MemCP&amp;lt;/div&amp;gt;&lt;br /&gt;
Plan deployment, migration, persistence, storage backends, settings and performance measurement.&lt;br /&gt;
&lt;br /&gt;
[[Deployment]] · [[Persistency and Performance Guarantees|Durability]] · [[Migration from MySQL and PostgreSQL|Migration]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Understand and contribute&amp;lt;/div&amp;gt;&lt;br /&gt;
Explore the storage engine, optimizer, embedded Scheme runtime and project internals.&lt;br /&gt;
&lt;br /&gt;
[[Query Planner and Physical Lowering|Query planner]] · [[RecSets]] · [[Columnar Storage]] · [[Contributing]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Quickstart ==&lt;br /&gt;
&lt;br /&gt;
=== Run with Docker ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
docker run --name memcp \&lt;br /&gt;
  -e ROOT_PASSWORD=&#039;choose-a-password&#039; \&lt;br /&gt;
  -p 4321:4321 -p 3307:3307 \&lt;br /&gt;
  -v memcp-data:/data \&lt;br /&gt;
  carli2/memcp:latest&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then open &amp;lt;code&amp;gt;http://localhost:4321&amp;lt;/code&amp;gt; and connect a MySQL application to &amp;lt;code&amp;gt;127.0.0.1&amp;lt;/code&amp;gt; on port &#039;&#039;&#039;3307&#039;&#039;&#039;. The volume mounted at &amp;lt;code&amp;gt;/data&amp;lt;/code&amp;gt; retains persistent table data across container replacement. See [[Install MemCP with Docker|the complete Docker guide]] before deploying it as a service.&lt;br /&gt;
&lt;br /&gt;
=== Build from source ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/launix-de/memcp&lt;br /&gt;
cd memcp&lt;br /&gt;
go mod download&lt;br /&gt;
make&lt;br /&gt;
./memcp --api-port=4321 --mysql-port=3307 lib/main.scm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connect with MySQL tooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mysql -h 127.0.0.1 -u root -p -P 3307&lt;br /&gt;
# Enter the password selected for this data directory.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The development default for a fresh data directory is &amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;. Change it before exposing MemCP to another machine. MemCP can also be supervised with PM2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
pm2 start ./memcp --name memcp -- \&lt;br /&gt;
  --no-repl -data ./data --api-port=4321 --mysql-port=3307 lib/main.scm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Background deployments must use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt; so that closing standard input does not terminate the interactive console and stop the server. See [[Compile MemCP from Source|Build from Source]], [[Deployment]] and [[MemCP Console]].&lt;br /&gt;
&lt;br /&gt;
== Key features ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:.8rem; margin:1rem 0;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;High performance&#039;&#039;&#039;&amp;lt;br /&amp;gt;Parallel, batch-oriented query execution is designed for multicore CPUs, compact working sets and fast persistent storage, serving both OLTP and OLAP workloads.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Columnar storage&#039;&#039;&#039;&amp;lt;br /&amp;gt;Data is stored by column for improved compression, a smaller memory footprint and fast analytical access.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Persistent in-memory operation&#039;&#039;&#039;&amp;lt;br /&amp;gt;MemCP is designed to keep active data in memory while offering configurable per-table durability and persistence backends.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Fast configurable writes&#039;&#039;&#039;&amp;lt;br /&amp;gt;Choose durability per table: &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; protects committed data through power loss, while measured &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; paths have reached about 10× its write throughput; &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; batches reconstructible data into the normal 15-minute rebuild cycle.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Built-in APIs&#039;&#039;&#039;&amp;lt;br /&amp;gt;SQL over HTTP and in-database services can remove an extra middleware hop for suitable applications.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Adaptive compression&#039;&#039;&#039;&amp;lt;br /&amp;gt;Bit-packing, dictionary encoding and sequence compression reduce the bytes read for suitable data. Historical imports have reached reductions around 80% versus their MySQL/MariaDB representation; measure your own schema.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Simple deployment&#039;&#039;&#039;&amp;lt;br /&amp;gt;Start with Docker, PM2 or the native binary. The compact application has historically had an installation footprint of approximately 10 MB.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Extensible frontends&#039;&#039;&#039;&amp;lt;br /&amp;gt;The Go storage engine and embedded Scheme environment support SQL, RDF, REST and custom application interfaces.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #9ad32d; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Cost-based query execution&#039;&#039;&#039;&amp;lt;br /&amp;gt;Logical decorrelation and join optimization are separated from cost-based physical selection of scans, indexes, RecSets, reusable caches and execution pipelines.&amp;lt;br /&amp;gt;[[Query Planner and Physical Lowering|How MemCP plans and lowers queries →]] · [[RecSets|How compact record sets process large domains →]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Why MemCP? ==&lt;br /&gt;
&lt;br /&gt;
Traditional relational databases were designed around spinning disks and comparatively small numbers of CPU cores. MemCP rethinks storage and query execution for modern multicore systems, large caches, fast storage and mixed workloads.&lt;br /&gt;
&lt;br /&gt;
Typical use cases include:&lt;br /&gt;
&lt;br /&gt;
* real-time dashboards and analytics;&lt;br /&gt;
* data-heavy SaaS platforms;&lt;br /&gt;
* embedded systems with limited resources;&lt;br /&gt;
* high-throughput OLTP/OLAP hybrids.&lt;br /&gt;
&lt;br /&gt;
Whether MemCP is a good fit depends on the required SQL compatibility, durability, query mix, data size and operational environment. Review [[Supported SQL]], [[Persistency and Performance Guarantees]] and [[Performance Measurement]] rather than treating benchmark figures as universal guarantees.&lt;br /&gt;
&lt;br /&gt;
== MemCP vs. MySQL ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
! Feature&lt;br /&gt;
! MySQL&lt;br /&gt;
! MemCP&lt;br /&gt;
|-&lt;br /&gt;
| Storage model&lt;br /&gt;
| Primarily row-based&lt;br /&gt;
| Column-based and compressed&lt;br /&gt;
|-&lt;br /&gt;
| Performance focus&lt;br /&gt;
| General-purpose relational workloads&lt;br /&gt;
| Parallel, in-memory-oriented execution for mixed operational and analytical workloads&lt;br /&gt;
|-&lt;br /&gt;
| In-memory capability&lt;br /&gt;
| Available through selected engines and caching&lt;br /&gt;
| Central design goal and default operating model&lt;br /&gt;
|-&lt;br /&gt;
| REST API integration&lt;br /&gt;
| Normally external&lt;br /&gt;
| Built in&lt;br /&gt;
|-&lt;br /&gt;
| Installation footprint&lt;br /&gt;
| Common server installations are approximately 150 MB or larger&lt;br /&gt;
| The native application has historically been approximately 10 MB&lt;br /&gt;
|-&lt;br /&gt;
| Open source&lt;br /&gt;
| ✅&lt;br /&gt;
| ✅&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MemCP provides MySQL protocol compatibility but does not claim to implement every MySQL feature. See [[Comparison: MemCP vs. MySQL]] for a detailed comparison and [[Database Tools compatibility with MemCP]] for client compatibility.&lt;br /&gt;
&lt;br /&gt;
== Architecture overview ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Tables, schemas and columns&#039;&#039;&#039;: Familiar SQL structures use a compressed columnar physical layout. See [[Databases, Tables and Columns]] and [[Columnar Storage]].&lt;br /&gt;
* &#039;&#039;&#039;Transaction model&#039;&#039;&#039;: Delta and main storage support mixed OLTP and OLAP semantics. See [[Transactions and Isolation]] and [[Shards, RecordIDs, Main Storage, Delta Storage]].&lt;br /&gt;
* &#039;&#039;&#039;Query planning&#039;&#039;&#039;: Logical optimization is separated from physical execution decisions. See [[Query Planner and Physical Lowering]].&lt;br /&gt;
* &#039;&#039;&#039;Persistence&#039;&#039;&#039;: Per-table durability can use filesystem, S3 or Ceph/RADOS storage. See [[Persistency and Performance Guarantees]] and [[Storage Backends]].&lt;br /&gt;
* &#039;&#039;&#039;Operations&#039;&#039;&#039;: The dashboard, metrics, process inspection and memory controls support day-to-day operation. See [[Dashboard and Operations]] and [[Memory Management and Eviction]].&lt;br /&gt;
* &#039;&#039;&#039;Scale-out roadmap&#039;&#039;&#039;: MemCP is single-node today. A leaderless CRUSH/RADOS and MOESI-inspired cluster design is planned, but must not be treated as an available production feature. See [[Cluster Monitor]].&lt;br /&gt;
* &#039;&#039;&#039;Frontends&#039;&#039;&#039;: MemCP provides multiple query and application interfaces:&lt;br /&gt;
** SQL through the MySQL wire protocol and SQL over HTTP;&lt;br /&gt;
** an RDF/graph query frontend;&lt;br /&gt;
** custom APIs through in-database web applications.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
The following navigation remains on the start page so users and search engines can reach every major documentation area directly.&lt;br /&gt;
&lt;br /&gt;
=== Introduction and evaluation ===&lt;br /&gt;
&lt;br /&gt;
* [[What is OLTP and OLAP]]&lt;br /&gt;
* [[History of the MemCP project]]&lt;br /&gt;
* [[Hardware Requirements]]&lt;br /&gt;
* [[Persistency and Performance Guarantees]]&lt;br /&gt;
* [[Current Status and Open Issues]]&lt;br /&gt;
* [[MySQL is too slow|SQL performance problems MemCP solves]]&lt;br /&gt;
* [[Comparison: MemCP vs. MySQL]]&lt;br /&gt;
&lt;br /&gt;
=== Getting started ===&lt;br /&gt;
&lt;br /&gt;
* [[Install MemCP with Docker|Install with Docker]]&lt;br /&gt;
* [[With Singularity|Install with Singularity/Apptainer]]&lt;br /&gt;
* [[Compile MemCP from Source|Build from Source]]&lt;br /&gt;
* [[Contributing]]&lt;br /&gt;
* [[Introduction to Scheme]]&lt;br /&gt;
* [[Full SCM API documentation]]&lt;br /&gt;
&lt;br /&gt;
=== Administration ===&lt;br /&gt;
&lt;br /&gt;
* [[Deployment]]&lt;br /&gt;
* [[Migration from MySQL and PostgreSQL]]&lt;br /&gt;
* [[Settings]]&lt;br /&gt;
* [[Security and Authentication]]&lt;br /&gt;
* [[Dashboard and Operations]]&lt;br /&gt;
* [[Memory Management and Eviction]]&lt;br /&gt;
* [[Process Hibernation]]&lt;br /&gt;
* [[Performance Measurement]]&lt;br /&gt;
* [[MemCP Console]]&lt;br /&gt;
&lt;br /&gt;
=== Frontends ===&lt;br /&gt;
&lt;br /&gt;
==== SQL frontend ====&lt;br /&gt;
&lt;br /&gt;
* [[Supported SQL]]&lt;br /&gt;
* [[Advanced SQL Tutorial]]&lt;br /&gt;
* [[JSON|JSON and SQL/JSON]]&lt;br /&gt;
* [[Triggers]]&lt;br /&gt;
* [[SQL over REST]]&lt;br /&gt;
* [[Database Tools compatibility with MemCP|Supported Tooling]]&lt;br /&gt;
* [[Query Planner and Physical Lowering|How SQL operators are implemented]]&lt;br /&gt;
* [[Add custom SQL operators to MemCP]]&lt;br /&gt;
&lt;br /&gt;
==== RDF frontend ====&lt;br /&gt;
&lt;br /&gt;
* [[Introduction to RDF]]&lt;br /&gt;
* [[Advanced Graph Querying]]&lt;br /&gt;
* [https://github.com/launix-de/rdfop RDF browser and templating example]&lt;br /&gt;
&lt;br /&gt;
==== Custom frontends ====&lt;br /&gt;
&lt;br /&gt;
* [[In-Database WebApps and REST Services]]&lt;br /&gt;
* [[MemCP for Microservices]]&lt;br /&gt;
* [[Websockets in MemCP]]&lt;br /&gt;
&lt;br /&gt;
=== Persistence backends and storage ===&lt;br /&gt;
&lt;br /&gt;
* [[File System]]&lt;br /&gt;
* [[Storage Backends|S3-compatible and Ceph/RADOS storage]]&lt;br /&gt;
* [[Cluster Monitor]]&lt;br /&gt;
&lt;br /&gt;
=== Internals ===&lt;br /&gt;
&lt;br /&gt;
==== How MemCP works ====&lt;br /&gt;
&lt;br /&gt;
* [[Databases, Tables and Columns]]&lt;br /&gt;
* [[Shards, RecordIDs, Main Storage, Delta Storage]]&lt;br /&gt;
* [[Columnar Storage]]&lt;br /&gt;
* [[Transactions and Isolation]]&lt;br /&gt;
* [[Query Planner and Physical Lowering]]&lt;br /&gt;
* [[Full SCM API documentation]]&lt;br /&gt;
&lt;br /&gt;
==== Scheme documentation ====&lt;br /&gt;
&lt;br /&gt;
* [[SCM Builtins]]&lt;br /&gt;
* [[Arithmetic / Logic]]&lt;br /&gt;
* [[Strings]]&lt;br /&gt;
* [[Streams]]&lt;br /&gt;
* [[Lists]]&lt;br /&gt;
* [[Associative Lists / Dictionaries]]&lt;br /&gt;
* [[Date]]&lt;br /&gt;
* [[Vectors]]&lt;br /&gt;
* [[Parsers]]&lt;br /&gt;
* [[Sync]]&lt;br /&gt;
* [[IO]]&lt;br /&gt;
* [[Storage]]&lt;br /&gt;
&lt;br /&gt;
==== Optimizations ====&lt;br /&gt;
&lt;br /&gt;
* [[Query Planner and Physical Lowering]]&lt;br /&gt;
* [[In-Memory Compression, Columnar Compression Techniques]]&lt;br /&gt;
* [[Temporary Computed Columns]]&lt;br /&gt;
* [[Data Auto Sharding and Auto Indexing]]&lt;br /&gt;
* [[Parallel Computing]]&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/launix-de/memcp MemCP on GitHub]&lt;br /&gt;
* [https://www.vldb.org/pvldb/vol13/p2649-boncz.pdf VLDB Research Paper]&lt;br /&gt;
* [https://cs.emis.de/LNI/Proceedings/Proceedings241/383.pdf LNI Proceedings Paper]&lt;br /&gt;
* [https://www.dcs.bbk.ac.uk/~dell/teaching/cc/paper/sigmod10/p135-malewicz.pdf Large Graph Algorithms]&lt;br /&gt;
&lt;br /&gt;
Additional blog posts on design decisions, compression techniques and performance optimization are available on the [https://launix.de/launix/ Launix blog].&lt;br /&gt;
&lt;br /&gt;
== Community ==&lt;br /&gt;
&lt;br /&gt;
MemCP is an open-source project maintained by developers for developers. Contributions are welcome in the form of bug reports, feature requests and pull requests.&lt;br /&gt;
&lt;br /&gt;
See [[Contributing]] and the [https://github.com/launix-de/memcp GitHub repository].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=With_Singularity&amp;diff=407</id>
		<title>With Singularity</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=With_Singularity&amp;diff=407"/>
		<updated>2026-08-28T10:14:06Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Run MemCP with Singularity/Apptainer =&lt;br /&gt;
&lt;br /&gt;
Build the repository-provided image target:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/launix-de/memcp&lt;br /&gt;
cd memcp&lt;br /&gt;
make memcp.sif&lt;br /&gt;
apptainer run memcp.sif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bind a persistent host directory to the container data path and expose or forward the HTTP/MySQL ports according to the local Apptainer installation. Set a strong initial root password for a fresh data directory and keep the image, application modules, and data directory versions together during upgrades.&lt;br /&gt;
&lt;br /&gt;
Singularity installations can use the corresponding &amp;lt;code&amp;gt;singularity&amp;lt;/code&amp;gt; command. See [[Deployment]], [[Persistency and Performance Guarantees]], and [[Security and Authentication]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Websockets_in_MemCP&amp;diff=406</id>
		<title>Websockets in MemCP</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Websockets_in_MemCP&amp;diff=406"/>
		<updated>2026-08-28T10:14:05Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Websockets in MemCP =&lt;br /&gt;
&lt;br /&gt;
An embedded HTTP handler can upgrade a request through the response object&#039;s WebSocket facility and receive messages through a callback. The &amp;lt;code&amp;gt;apps/minigame.scm&amp;lt;/code&amp;gt; example in the repository demonstrates the current API and routing pattern.&lt;br /&gt;
&lt;br /&gt;
WebSockets keep one bidirectional connection open for live dashboards, notifications, collaborative state, games, or change feeds. They are a delivery channel, not a durable message queue: reconnect, replay, acknowledgement, ordering, and missed-message semantics belong to the application.&lt;br /&gt;
&lt;br /&gt;
== Server-side upgrade ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(set send ((res &amp;quot;websocket&amp;quot;)&lt;br /&gt;
	(lambda (message) (print &amp;quot;message: &amp;quot; message))&lt;br /&gt;
	(lambda () (print &amp;quot;connection closed&amp;quot;))))&lt;br /&gt;
(send 1 &amp;quot;Hello from MemCP&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The numeric first argument is the WebSocket frame opcode used by the current response API. Keep the sending function only for the connection lifetime.&lt;br /&gt;
&lt;br /&gt;
A browser client can connect to the routed endpoint with the standard API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
const socket = new WebSocket(&amp;quot;wss://example.test/minigame/ws&amp;quot;);&lt;br /&gt;
socket.addEventListener(&amp;quot;open&amp;quot;, () =&amp;gt; socket.send(JSON.stringify({type: &amp;quot;hello&amp;quot;})));&lt;br /&gt;
socket.addEventListener(&amp;quot;message&amp;quot;, event =&amp;gt; console.log(JSON.parse(event.data)));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Complete routed example ==&lt;br /&gt;
&lt;br /&gt;
The repository&#039;s &amp;lt;code&amp;gt;apps/minigame.scm&amp;lt;/code&amp;gt; shows the complete routing pattern: preserve the previous handler, serve an HTML/JavaScript client below one prefix, and upgrade only the WebSocket path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(define http_handler (begin&lt;br /&gt;
	(set old_handler http_handler)&lt;br /&gt;
	(lambda (req res) (begin&lt;br /&gt;
		(match (req &amp;quot;path&amp;quot;)&lt;br /&gt;
			&amp;quot;/minigame/ws&amp;quot; (begin&lt;br /&gt;
				(set send ((res &amp;quot;websocket&amp;quot;)&lt;br /&gt;
					(lambda (message) (begin&lt;br /&gt;
						(print &amp;quot;message: &amp;quot; message)&lt;br /&gt;
						(send 1 (concat &amp;quot;echo: &amp;quot; message))))))&lt;br /&gt;
				(send 1 &amp;quot;Hello from MemCP&amp;quot;))&lt;br /&gt;
			(regex &amp;quot;^/minigame/(.*)$&amp;quot; path asset) (begin&lt;br /&gt;
				((res &amp;quot;header&amp;quot;) &amp;quot;Content-Type&amp;quot; &amp;quot;text/plain&amp;quot;)&lt;br /&gt;
				((res &amp;quot;status&amp;quot;) 200)&lt;br /&gt;
				((res &amp;quot;print&amp;quot;) &amp;quot;WebSocket client assets belong here&amp;quot;))&lt;br /&gt;
			(old_handler req res))))))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this module is imported by &amp;lt;code&amp;gt;lib/main.scm&amp;lt;/code&amp;gt;, the existing server uses the wrapped handler. A standalone application can call &amp;lt;code&amp;gt;serve&amp;lt;/code&amp;gt; explicitly. Keep the receive callback and its connection-local &amp;lt;code&amp;gt;send&amp;lt;/code&amp;gt; closure together; never store that closure after close.&lt;br /&gt;
&lt;br /&gt;
Prefer JSON messages with an explicit type and version. Validate the decoded shape before reading fields, cap message size, and define how the client resubscribes or resumes after reconnect.&lt;br /&gt;
&lt;br /&gt;
== Database-backed publish/subscribe ==&lt;br /&gt;
&lt;br /&gt;
Prepare fixed queries during module startup, create a session per connection, and bind authenticated identity and subscription state there. A receive callback can update state atomically; query results can be emitted through &amp;lt;code&amp;gt;send&amp;lt;/code&amp;gt;. On close, release subscriptions and other references so they do not keep sessions or sending functions alive.&lt;br /&gt;
&lt;br /&gt;
For fan-out, use bounded per-client queues and a policy for slow consumers (drop/coalesce messages or disconnect). A database table can persist events for replay, but a &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; table cannot provide durable delivery after restart.&lt;br /&gt;
&lt;br /&gt;
The earlier hardlife.io example used this structure at larger scale: prepare position-update, listener-membership and dirty-list queries once; authenticate a player handle with a message authentication code; keep the connection&#039;s player/location state in a session; mark affected listeners dirty after a position change; send only changed avatars; and remove listener state on disconnect. The complete historical listing coupled credentials, global &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; defaults and application-specific tables, so reproducing it as a copy-and-paste server would be unsafe. The pipeline remains a useful design example.&lt;br /&gt;
&lt;br /&gt;
Hosting the handler beside the database removes an application/database socket hop and repeated parsing for prepared shapes. That is a performance opportunity, not proof that every embedded WebSocket service is faster than a separate Node.js or Go service; benchmark the authenticated end-to-end path and account for the shared failure domain.&lt;br /&gt;
&lt;br /&gt;
== Production considerations ==&lt;br /&gt;
&lt;br /&gt;
Authenticate the upgrade, validate browser Origin, limit message and queue sizes, apply backpressure, and remove subscriptions when the connection closes. A slow client must not create an unbounded in-memory backlog. Long database operations should observe cancellation. Use TLS at a trusted proxy or transport layer and do not expose default credentials.&lt;br /&gt;
&lt;br /&gt;
Storage ENGINE choice is independent of WebSocket delivery: &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; can lose recent writes, and &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; are not durable. See [[In-Database WebApps and REST Services]] and [[Persistency and Performance Guarantees]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Temporary_Computed_Columns&amp;diff=405</id>
		<title>Temporary Computed Columns</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Temporary_Computed_Columns&amp;diff=405"/>
		<updated>2026-08-28T10:14:05Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;computed-columns-group-caches-and-orc&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Computed Columns, Group Caches, and ORC =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Verified against commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 28 August 2026.&#039;&#039;&#039; These are optimizer-managed physical structures. Applications normally write SQL; MemCP analyzes the plan, creates suitable caches, and maintains their validity automatically.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MemCP reuses expensive expressions and relational stages without copying complete result rows into a generic temporary table. It can attach one computed value to an existing base row, keep a narrow table of grouping keys and aggregates, or maintain an order-dependent column. The surrounding base columns remain where they already are.&lt;br /&gt;
&lt;br /&gt;
This matters for queries that join or filter a million rows, sort by one derived value, and finally return only 100 rows. A conventional wide temporary result may copy every projected column before &amp;lt;code&amp;gt;ORDER BY ... LIMIT&amp;lt;/code&amp;gt;. MemCP instead tries to materialize only the value, key domain, [[RecSets|record set]], or ordering dependency needed by the next physical stage.&lt;br /&gt;
&lt;br /&gt;
== The three reusable structures ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Structure !! Logical meaning !! Stored shape !! Typical use&lt;br /&gt;
|-&lt;br /&gt;
| Ordinary computed column || One derived value per live row of an existing table || A lazy &amp;lt;code&amp;gt;StorageComputeProxy&amp;lt;/code&amp;gt; backed by compressed main values, sparse repaired values, and a validity mask || Repeated scalar expressions, lookup results, JSON paths, correlated scalar probes, computed ordering&lt;br /&gt;
|-&lt;br /&gt;
| Group cache/keytable || One row per distinct grouping/domain key plus computed aggregate columns || A narrow internal &amp;lt;code&amp;gt;ENGINE=cache&amp;lt;/code&amp;gt; table with a unique key || Reused &amp;lt;code&amp;gt;GROUP BY&amp;lt;/code&amp;gt;, correlated aggregates, prepared membership/group domains&lt;br /&gt;
|-&lt;br /&gt;
| ORC (ordered-reduce column) || One value whose computation depends on partition/order predecessors || An ordered computed proxy with per-row validity and dependency-range repair || Running totals, rank/row-number-like work, reusable window/order calculations&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SQL plan cache is different: it stores compiled plan formulas, not computed rows. A query may reuse a compiled formula without having a warm group cache, or reuse a computed cache after a newly compiled query recognizes the same canonical definition.&lt;br /&gt;
&lt;br /&gt;
== From SQL expression to canonical cache ==&lt;br /&gt;
&lt;br /&gt;
MemCP does not name reusable structures after a query&#039;s disposable aliases. During logical planning and physical lowering it analyzes the expression and constructs a canonical identity from the data the structure represents:&lt;br /&gt;
&lt;br /&gt;
* table aliases are rewritten to stable source roles, while two roles in a self-join remain distinct;&lt;br /&gt;
* column references include physical schema, relation, and column identity;&lt;br /&gt;
* grouping keys, source graph, filters, aggregate recipe, partition/order definition, and relevant bounds become part of the identity;&lt;br /&gt;
* SELECT aliases, formatting, and unrelated output columns do not create a second cache;&lt;br /&gt;
* stable structural hashes produce names such as internal &amp;lt;code&amp;gt;.grp:...&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;agg_...&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;__orc_...&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
Consequently, two queries can share a computed aggregate even when their SQL aliases or final projections differ. A second aggregate over the same group domain can add another narrow computed column to the existing keytable instead of cloning the entire intermediate relation. Conversely, a different filter, join role, ordering recipe, or semantic dependency receives a different identity rather than incorrectly sharing values.&lt;br /&gt;
&lt;br /&gt;
Preparation filters are deliberately absent from a computed column&#039;s logical identity. They only say which values are likely to be consumed soon and should be warmed eagerly. Every other live row still has a well-defined value that can be computed later.&lt;br /&gt;
&lt;br /&gt;
== Automatic analysis of the generated Scheme code ==&lt;br /&gt;
&lt;br /&gt;
The planner emits a &amp;lt;code&amp;gt;createcolumn&amp;lt;/code&amp;gt; call containing the computation lambda and its direct input columns. This is not the end of dependency discovery. The storage engine walks the resulting Scheme AST/procedure to determine what the computation reads and how source changes can reach the cached value.&lt;br /&gt;
&lt;br /&gt;
The analyzer:&lt;br /&gt;
&lt;br /&gt;
# removes source-location wrappers and accepts both unresolved symbols and already-resolved builtin procedures;&lt;br /&gt;
# descends through lambdas and nested physical expressions;&lt;br /&gt;
# recognizes &amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scalar_scan&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;scalar_scan_order&amp;lt;/code&amp;gt; calls;&lt;br /&gt;
# also examines a scan&#039;s table expression, because a dynamic physical source can itself contain dependency-producing scans;&lt;br /&gt;
# resolves literal table handles or canonical table expressions to schema and relation;&lt;br /&gt;
# reads filter and map column lists from both quoted and constructed-list forms;&lt;br /&gt;
# records every source column used by the filter or mapper;&lt;br /&gt;
# inspects conjunctions of equality predicates and maps a source scan parameter back to the outer computed-column input it equals;&lt;br /&gt;
# follows source columns that are themselves computed and expands them transitively to their physical input, map, partition, and sort columns;&lt;br /&gt;
# extracts session-variable dependencies and creates session-specific cache variants where a value must not leak between users or sessions.&lt;br /&gt;
&lt;br /&gt;
For example, a generated lookup conceptually shaped like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(lambda (customer_id)&lt;br /&gt;
	(scan tx (table &amp;quot;shop&amp;quot; &amp;quot;payments&amp;quot;)&lt;br /&gt;
		&#039;(&amp;quot;customer_id&amp;quot;)&lt;br /&gt;
		(lambda (payment_customer)&lt;br /&gt;
			(equal? payment_customer (outer customer_id)))&lt;br /&gt;
		&#039;(&amp;quot;amount&amp;quot;)&lt;br /&gt;
		(lambda (amount) amount)&lt;br /&gt;
		+&lt;br /&gt;
		0))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
tells the storage analyzer that &amp;lt;code&amp;gt;payments.customer_id&amp;lt;/code&amp;gt; is the reverse lookup key for the target row&#039;s &amp;lt;code&amp;gt;customer_id&amp;lt;/code&amp;gt;, and that &amp;lt;code&amp;gt;payments.amount&amp;lt;/code&amp;gt; is relevant to the value. An UPDATE of an unrelated &amp;lt;code&amp;gt;payments.note&amp;lt;/code&amp;gt; column therefore need not invalidate the cache.&lt;br /&gt;
&lt;br /&gt;
The analysis is deliberately conservative. If a scan or reverse key relationship cannot be proven from the generated code, MemCP does not guess. It generates complete-column invalidation so the next read recomputes correct values. More analyzable code improves maintenance precision; opaque code must remain correct.&lt;br /&gt;
&lt;br /&gt;
== Automatic generation of maintenance triggers ==&lt;br /&gt;
&lt;br /&gt;
When the computed-column signature is installed or changes, &amp;lt;code&amp;gt;createcolumn&amp;lt;/code&amp;gt; calls the storage engine&#039;s trigger generator. It registers hidden system triggers on every discovered source table. Registration is idempotent, so preparing the same canonical cache again updates/reuses its metadata instead of accumulating duplicate triggers.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Analyzed shape !! Generated reaction to source INSERT/UPDATE/DELETE&lt;br /&gt;
|-&lt;br /&gt;
| Direct row-local inputs || The corresponding row value is marked stale or repaired through the computed proxy.&lt;br /&gt;
|-&lt;br /&gt;
| Lookup with proven equality key || Scan only target cache rows whose key equals the source row&#039;s &amp;lt;code&amp;gt;OLD&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;NEW&amp;lt;/code&amp;gt; key, then invalidate that exact subset.&lt;br /&gt;
|-&lt;br /&gt;
| Additive aggregate (&amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt;, neutral zero, analyzable map without nested scans) || Apply the mapped delta with &amp;lt;code&amp;gt;$increment:&amp;amp;lt;column&amp;amp;gt;&amp;lt;/code&amp;gt;; UPDATE subtracts OLD and adds NEW when the group key stays stable.&lt;br /&gt;
|-&lt;br /&gt;
| Additive UPDATE whose group key changes || Invalidate safely because old and new keytable membership may differ.&lt;br /&gt;
|-&lt;br /&gt;
| COUNT-style constant-one helper || Prefer robust invalidation, because the value also controls empty/non-empty group visibility.&lt;br /&gt;
|-&lt;br /&gt;
| ORC with known partition and sort key || Invalidate the affected partition from the OLD/NEW sort position onward.&lt;br /&gt;
|-&lt;br /&gt;
| Opaque or unsupported dependency || Invalidate the complete computed column.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The generated triggers run after INSERT, UPDATE, and DELETE. UPDATE triggers compare only columns proven relevant by the analysis and skip maintenance if none changed. They use the trigger row dictionaries &amp;lt;code&amp;gt;OLD&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NEW&amp;lt;/code&amp;gt; to find both sides of a key-changing update.&lt;br /&gt;
&lt;br /&gt;
Selective invalidation is itself batched. The internal &amp;lt;code&amp;gt;$invalidate:&amp;amp;lt;column&amp;amp;gt;&amp;lt;/code&amp;gt; callback collects matching record IDs during the maintenance scan; invalidation is applied after scan locks are released. Incremental changes are similarly accumulated per proxy and record ID before &amp;lt;code&amp;gt;$increment:&amp;amp;lt;column&amp;amp;gt;&amp;lt;/code&amp;gt; updates cached values. This avoids nested lock acquisition in the inner scan loop.&lt;br /&gt;
&lt;br /&gt;
System maintenance triggers are hidden from ordinary &amp;lt;code&amp;gt;SHOW TRIGGERS&amp;lt;/code&amp;gt;; they are implementation-owned rather than user DDL. User triggers and the computed-cache trigger graph still share the storage engine&#039;s defined timing and locking machinery.&lt;br /&gt;
&lt;br /&gt;
=== Dependency chains and invalidation waves ===&lt;br /&gt;
&lt;br /&gt;
A cached column can depend on another computed cache. The storage engine registers &amp;lt;code&amp;gt;AfterInvalidate&amp;lt;/code&amp;gt; edges in addition to source DML triggers. Invalidating the lower cache synchronously propagates to its dependants.&lt;br /&gt;
&lt;br /&gt;
One invalidation wave carries a query/goroutine-local visited set keyed by target table and column. This makes repeated edges idempotent and prevents a malformed cycle from recursing forever without introducing a global invalidation lock. Selective invalidation is currently propagated conservatively at column level when a downstream reverse mapping cannot be preserved safely.&lt;br /&gt;
&lt;br /&gt;
=== Lifecycle cleanup ===&lt;br /&gt;
&lt;br /&gt;
The generator also owns cleanup:&lt;br /&gt;
&lt;br /&gt;
* dropping an internal target cache removes the triggers it installed on source tables;&lt;br /&gt;
* dropping a source table can drop dependent dot-prefixed helper tables so a later table with the same name cannot inherit stale data;&lt;br /&gt;
* group-key maintenance reacts to source INSERT, UPDATE, and DELETE;&lt;br /&gt;
* dropping the base table or a grouping column removes its dependent keytable;&lt;br /&gt;
* trigger target leases pin a cache while maintenance is using it, preventing concurrent eviction from invalidating a live pointer.&lt;br /&gt;
&lt;br /&gt;
These lifecycle triggers must only remove the helper objects they explicitly own. They are not general garbage collection and must never delete unrelated user data.&lt;br /&gt;
&lt;br /&gt;
== Race-free initial construction ==&lt;br /&gt;
&lt;br /&gt;
Installing triggers after filling a cache would leave a lost-update window: a source write between the snapshot and trigger registration would never invalidate the new value. &amp;lt;code&amp;gt;initialize_cache_table&amp;lt;/code&amp;gt; closes that race.&lt;br /&gt;
&lt;br /&gt;
It resolves and sorts all source tables into a deterministic lock order, blocks source mutations, registers maintenance, fills the canonical cache from a consistent source view, optionally finalizes/rebuilds it, and only then releases the locks. Concurrent attempts to initialize the same generation wait for the shared result rather than performing duplicate fills.&lt;br /&gt;
&lt;br /&gt;
Internal keytables use &amp;lt;code&amp;gt;ENGINE=cache&amp;lt;/code&amp;gt; and can store this initializer as a closed &amp;lt;code&amp;gt;oninit&amp;lt;/code&amp;gt; procedure. After restart or eviction, the first idempotent creation guard rebuilds the empty generation before exposing it to consumers. See [[Persistency and Performance Guarantees]] for why cache data is reconstructible rather than durable.&lt;br /&gt;
&lt;br /&gt;
== Lazy values, eager warming, and repair ==&lt;br /&gt;
&lt;br /&gt;
An ordinary computed column is a complete logical column even when few physical values exist:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Compress&amp;lt;/code&amp;gt; can eagerly calculate all rows when the plan expects broad consumption;&lt;br /&gt;
* &amp;lt;code&amp;gt;CompressFiltered&amp;lt;/code&amp;gt; warms only rows selected by a preparation filter;&lt;br /&gt;
* reading a missing or invalid ordinary value calculates that row from its current inputs and stores the result;&lt;br /&gt;
* valid compressed main values use the normal bulk column-reader fast path;&lt;br /&gt;
* repeated &amp;lt;code&amp;gt;createcolumn&amp;lt;/code&amp;gt; calls for the same signature preserve valid cached values and repair only missing/dirty state;&lt;br /&gt;
* a materially different semantic formula receives a different canonical identity; reissuing the same signature preserves its valid cache. ORC metadata changes explicitly invalidate the affected ordered proxies.&lt;br /&gt;
&lt;br /&gt;
For broad selective invalidations, each proxy compares a short measured repair sample with its last full recomputation cost. If point repair is predicted to cost more, it marks the whole column dirty and lets the next consumer perform one coherent rebuild. This adapts to the actual computor rather than relying on one global row-count threshold.&lt;br /&gt;
&lt;br /&gt;
The historical documentation said computations become parallel above 60,000 rows. That threshold is no longer the public execution contract. Current preparation fans work out over active shards, while planner cost, shard count, input size, and the maintenance/recompute path determine useful parallelism. Large independent shards can compute concurrently; a tiny table or a single ordered dependency cannot gain speed merely from crossing a fixed row number.&lt;br /&gt;
&lt;br /&gt;
== GROUP BY through narrow computed relations ==&lt;br /&gt;
&lt;br /&gt;
A reusable group cache conceptually follows four steps:&lt;br /&gt;
&lt;br /&gt;
# create a canonical internal table containing a UNIQUE key over all grouping columns;&lt;br /&gt;
# populate the distinct grouping keys;&lt;br /&gt;
# add one computed column for each aggregate or derived ordering value;&lt;br /&gt;
# scan the narrow group relation and join/project base values only where the final result needs them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE t (a TEXT, b INT);&lt;br /&gt;
INSERT INTO t VALUES (&#039;foo&#039;, 1), (&#039;bar&#039;, 2), (&#039;foo&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT a, SUM(b) AS total&lt;br /&gt;
FROM t&lt;br /&gt;
GROUP BY a;&lt;br /&gt;
-- bar | 2&lt;br /&gt;
-- foo | 4&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The keytable cleanup trigger inserts a missing key idempotently, removes a key after the last source row leaves the group, and handles OLD and NEW keys on UPDATE. It runs at priority 90, before aggregate invalidation at priority 100, so key membership is current when a value is repaired.&lt;br /&gt;
&lt;br /&gt;
GROUP BY syntax does not force a cache. The physical lowerer compares a one-pass fused aggregation with keytable construction, expected probes/reuse, maintenance cost, memory, and available alternative carriers. Query-local or UNION-shaped groups may instead be filled in one batch, while reusable base-table groups can use storage-managed computed columns.&lt;br /&gt;
&lt;br /&gt;
Different surrounding WHERE ranges can reuse the same row-local computed expression because the preparation predicate does not define the column. A group cache, however, includes the grouping domain and semantic source filter in its canonical identity: two genuinely different group populations must not share one aggregate value.&lt;br /&gt;
&lt;br /&gt;
== Order-dependent computed columns (ORC) ==&lt;br /&gt;
&lt;br /&gt;
An ORC is not pointwise. A running total at row 500 depends on preceding rows in its partition, so changing row 100 may invalidate a suffix rather than just row 100.&lt;br /&gt;
&lt;br /&gt;
The ORC definition records sort columns/directions, the number of leading partition columns, map columns/function, reducer, and neutral value. Generated triggers:&lt;br /&gt;
&lt;br /&gt;
* use equality bounds for the partition prefix;&lt;br /&gt;
* invalidate a range beginning at the changed OLD or NEW sort key;&lt;br /&gt;
* leave unrelated partitions valid;&lt;br /&gt;
* fall back to complete invalidation when a cross-table dependency cannot be mapped selectively;&lt;br /&gt;
* compare cumulative selective-invalidation cost with the last suffix/full recomputation and choose complete invalidation when that is cheaper.&lt;br /&gt;
&lt;br /&gt;
On the next read, the ordered proxy repairs the dependency range under the table&#039;s ORC recomputation guard. Concurrent readers do not observe the internal “invalid” sentinel used by the reducer. If one ordered scan can compute a window directly, the planner may fuse it instead of creating an ORC at all.&lt;br /&gt;
&lt;br /&gt;
== Cost, eviction, and observability ==&lt;br /&gt;
&lt;br /&gt;
The physical lowerer compares:&lt;br /&gt;
&lt;br /&gt;
* direct scalar/index probes;&lt;br /&gt;
* a fused one-pass scan or aggregate;&lt;br /&gt;
* a [[RecSets|RecSet]] carrier;&lt;br /&gt;
* a canonical computed column;&lt;br /&gt;
* an FK-backed/group cache;&lt;br /&gt;
* an ORC;&lt;br /&gt;
* a narrow temporary relation.&lt;br /&gt;
&lt;br /&gt;
Inputs include build work, expected reuse, source and target cardinality, maintenance/invalidation work, memory, ordering, LIMIT, and available indexes. &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt; shows the selected physical family for supported decisions; it is better evidence than assuming repeated SQL text always builds a cache.&lt;br /&gt;
&lt;br /&gt;
Temporary computed columns and keytables are accounted by the global memory manager. Access refreshes their lease/last-used state. Because they are reconstructible, the manager can evict them under pressure; a later query recreates or lazily repairs them. Base data remains authoritative throughout.&lt;br /&gt;
&lt;br /&gt;
== Correctness boundaries ==&lt;br /&gt;
&lt;br /&gt;
* A preparation filter changes warming, never the logical domain or NULL value of a computed column.&lt;br /&gt;
* A cached value must never outlive a source change without an invalidation/maintenance edge.&lt;br /&gt;
* Opaque code requires conservative invalidation; absence of a recognized equality is not evidence of independence.&lt;br /&gt;
* Session-dependent formulas require isolated variants and must not reuse one user&#039;s value for another session.&lt;br /&gt;
* ORC invalidation follows ordering dependencies and cannot be replaced by unrelated point repair.&lt;br /&gt;
* Internal trigger generation must be complete before source mutations are unblocked.&lt;br /&gt;
* Cache eviction and source-table DDL must remove their owned trigger graph without touching user data.&lt;br /&gt;
&lt;br /&gt;
For exact low-level signatures see [[Storage]]. Related architecture is documented in [[Query Planner and Physical Lowering]], [[Triggers]], [[Columnar Storage]], [[Memory Management and Eviction]], [[RecSets]], and [[Parallel Computing]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Supported_SQL&amp;diff=404</id>
		<title>Supported SQL</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Supported_SQL&amp;diff=404"/>
		<updated>2026-08-28T10:14:04Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;supported-sql&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Supported SQL =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Verified against development commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. MemCP is Beta and does not claim complete MySQL or PostgreSQL compatibility. Unsupported shapes should fail explicitly; test a required workload before migration.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
This page is a capability map for application evaluation. MemCP accepts a broad MySQL-oriented dialect through its MySQL protocol and HTTP endpoint, plus PostgreSQL-oriented syntax through a separate HTTP endpoint. Both compile into the same logical planner and storage runtime, but accepted surface syntax and returned metadata can differ by frontend.&lt;br /&gt;
&lt;br /&gt;
Support is defined by tested semantics, not merely by whether the parser accepts a statement. Compatibility-only clauses may intentionally be no-ops, and uncommon combinations can remain unsupported even when their individual operators are available. Use this overview to select candidates, then verify every required query, constraint, transaction, prepared statement, and client behavior against the deployed release.&lt;br /&gt;
&amp;lt;span id=&amp;quot;query-language&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Query language ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt;, aliases, &amp;lt;code&amp;gt;WHERE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DISTINCT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;GROUP BY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HAVING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ORDER BY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LIMIT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;OFFSET&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;INNER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LEFT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RIGHT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;CROSS JOIN&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UNION ALL&amp;lt;/code&amp;gt;, including ordered/limited set results;&lt;br /&gt;
* derived tables and logical SQL views;&lt;br /&gt;
* scalar, &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; subqueries, including many correlated and grouped forms;&lt;br /&gt;
* aggregates &amp;lt;code&amp;gt;COUNT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SUM&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AVG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MAX&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;GROUP_CONCAT&amp;lt;/code&amp;gt;;&lt;br /&gt;
* window functions including &amp;lt;code&amp;gt;ROW_NUMBER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RANK&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DENSE_RANK&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LEAD&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LAG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FIRST_VALUE&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LAST_VALUE&amp;lt;/code&amp;gt; with partition/order clauses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;data-modification-and-schema&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Data modification and schema ==&lt;br /&gt;
&lt;br /&gt;
* single- and multi-row &amp;lt;code&amp;gt;INSERT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INSERT IGNORE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INSERT … SELECT&amp;lt;/code&amp;gt;, and MySQL or PostgreSQL upsert syntax;&lt;br /&gt;
* &amp;lt;code&amp;gt;UPDATE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DELETE&amp;lt;/code&amp;gt;, including qualified and supported multi-table forms;&lt;br /&gt;
* &amp;lt;code&amp;gt;CREATE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ALTER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RENAME&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TRUNCATE&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DROP&amp;lt;/code&amp;gt; for databases and tables;&lt;br /&gt;
* &amp;lt;code&amp;gt;CREATE VIEW&amp;lt;/code&amp;gt;, indexes, primary/unique keys, foreign keys, defaults, &amp;lt;code&amp;gt;AUTO_INCREMENT&amp;lt;/code&amp;gt;, computed expressions, types, collations, and per-table ENGINE;&lt;br /&gt;
* persistent BEFORE/AFTER triggers for INSERT, UPDATE, and DELETE.&lt;br /&gt;
&lt;br /&gt;
Foreign keys are enforced for the tested RESTRICT, CASCADE, and SET NULL paths. Some compatibility DDL is intentionally accepted as a no-op; for example, a client accepting &amp;lt;code&amp;gt;ADD FULLTEXT&amp;lt;/code&amp;gt; does not imply a MySQL-compatible full-text index implementation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;transactions-security-and-metadata&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Transactions, security, and metadata ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;BEGIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;COMMIT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;ROLLBACK&amp;lt;/code&amp;gt;;&lt;br /&gt;
* users, passwords, grants, revokes, and database access policies;&lt;br /&gt;
* &amp;lt;code&amp;gt;SHOW DATABASES&amp;lt;/code&amp;gt;, tables, columns, indexes, create-table metadata, variables, engines, processlist, and selected &amp;lt;code&amp;gt;INFORMATION_SCHEMA&amp;lt;/code&amp;gt; relations;&lt;br /&gt;
* prepared statements over the MySQL protocol;&lt;br /&gt;
* &amp;lt;code&amp;gt;KILL QUERY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;KILL CONNECTION&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
See [[Transactions_and_Isolation|Transactions and Isolation]] and [[Security_and_Authentication|Security and Authentication]] for the operational contract.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;expressions&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Expressions ==&lt;br /&gt;
&lt;br /&gt;
MemCP implements SQL NULL/three-valued logic, CASE, COALESCE/NULLIF/IFNULL, arithmetic and bitwise operators, comparisons, BETWEEN, IN lists, LIKE/ILIKE, REGEXP/RLIKE, MATCH…AGAINST compatibility, casts, string functions, mathematical functions, hashes, date/time functions, intervals, and timezone conversion.&lt;br /&gt;
&lt;br /&gt;
The exact parser and function catalog changes more often than this overview. Use the generated API reference and the SQL test taxonomy for detailed coverage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;json&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== JSON ==&lt;br /&gt;
&lt;br /&gt;
MemCP stores declared &amp;lt;code&amp;gt;JSON&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;JSONB&amp;lt;/code&amp;gt; values in a native tagged BSON representation. The MySQL dialect implements JSON validation, type inspection, path extraction, constructors, aggregates, mutation functions, containment/search operations, &amp;lt;code&amp;gt;JSON_TABLE&amp;lt;/code&amp;gt;, and the &amp;lt;code&amp;gt;-&amp;gt;&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;-&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; operators. The PostgreSQL dialect provides its corresponding &amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;jsonb&amp;lt;/code&amp;gt; operators, constructors, aggregates, path functions, and set-returning expansion forms. Deterministic path expressions can be materialized and indexed through the ordinary computed-column/index machinery. See [[JSON]] for the detailed compatibility contract and deviations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;planner-inspection&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Planner inspection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;EXPLAIN SELECT ...;&lt;br /&gt;
EXPLAIN IR SELECT ...;&lt;br /&gt;
EXPLAIN REORDER SELECT ...;&lt;br /&gt;
EXPLAIN PHYSICAL SELECT ...;&lt;br /&gt;
EXPLAIN COMPILE SELECT ...;&amp;lt;/pre&amp;gt;&lt;br /&gt;
See [[Query Planner and Physical Lowering]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;known-limitations&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Known limitations ==&lt;br /&gt;
&lt;br /&gt;
MemCP is not a byte-for-byte MySQL server implementation. Metadata details, administrative commands, uncommon syntax, advanced locking modes, XA, stored procedures, and untested SQL-standard edge cases may be absent. Consult the [https://github.com/launix-de/memcp/issues current issue tracker] and add a must-pass and must-fail test for every application-critical construct.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Storage&amp;diff=403</id>
		<title>Storage</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Storage&amp;diff=403"/>
		<updated>2026-08-28T10:14:04Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;storage&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Storage =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Generated from MemCP c42e19eba on 2026-08-27; do not edit manually. --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&amp;gt;Generated from MemCP commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. See [[Full SCM API documentation]].&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Storage&#039;&#039;&#039; module is the low-level data interface used by generated SQL plans. It manages databases, tables, columns, constraints, scans, indexes, RecSets, computed data, persistence, and schema lifecycle operations.&lt;br /&gt;
&lt;br /&gt;
Most application code should use SQL instead of calling these functions directly. Planner-generated calls rely on exact transaction, locking, callback, ownership, and quoting contracts. Functions that accept table handles or transaction contexts must not be replaced with direct access to shard internals.&lt;br /&gt;
&lt;br /&gt;
For the physical model see [[Columnar Storage]], [[Shards, RecordIDs, Main Storage, Delta Storage]], and [[Persistency and Performance Guarantees]].&lt;br /&gt;
&lt;br /&gt;
== table ==&lt;br /&gt;
&lt;br /&gt;
resolves a schema+table name pair into a table handle&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_estimate ==&lt;br /&gt;
&lt;br /&gt;
estimate output row count for a table scan&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== table_planner_statistics ==&lt;br /&gt;
&lt;br /&gt;
return the immutable O(1) planner-statistics snapshot for a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_selectivity_estimate ==&lt;br /&gt;
&lt;br /&gt;
bounded estimate of visible rows matching a table filter; stops at max_rows and does not log scan telemetry&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;condition_cols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to the selectivity predicate&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;condition&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): predicate sampled to estimate matching rows&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the sampled row matches&lt;br /&gt;
* &#039;&#039;&#039;max_rows&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;table_empty&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== table_empty? ==&lt;br /&gt;
&lt;br /&gt;
returns true if a table currently has no rows&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_recset ==&lt;br /&gt;
&lt;br /&gt;
builds a query-local record-set handle from one table scan, or -- when given an existing recset instead of a table -- narrows that recset to the members which also satisfy filter, re-evaluating filter only over its existing membership. The latter is the cheap way to AND a further (possibly subscan-heavy) condition onto an already-narrowed recset without re-touching rows outside it (e.g. evaluating an expensive correlated check only over the rows a cheap selective filter already narrowed a table down to). The returned value is not persisted and can be scanned like a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): a table, or an existing recset to narrow further&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a row enters the recset&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row belongs in the recset&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_count ==&lt;br /&gt;
&lt;br /&gt;
returns the number of currently stored recids in a query-local recset&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_project_join ==&lt;br /&gt;
&lt;br /&gt;
projects a source recset through key columns into a query-local target-table recset&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;source_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;source_key_columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;target_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;target_key_columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_key_index ==&lt;br /&gt;
&lt;br /&gt;
builds an immutable lookup function for key columns of the rows contained in a query-local recset&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context used while reading source keys&lt;br /&gt;
* &#039;&#039;&#039;source_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;source_key_columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;lookup&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): tests whether the recset contains a row with the supplied composite key&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each source key column, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;present&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether the composite key occurs in the recset&lt;br /&gt;
&lt;br /&gt;
== recset_union ==&lt;br /&gt;
&lt;br /&gt;
combines query-local recsets from the same table and removes duplicate record IDs&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recsets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_intersect ==&lt;br /&gt;
&lt;br /&gt;
intersects query-local recsets from the same table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recsets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_difference ==&lt;br /&gt;
&lt;br /&gt;
returns the records from the first query-local recset which occur in none of the following same-table recsets&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-11&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recsets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-11&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_not ==&lt;br /&gt;
&lt;br /&gt;
returns the complement of a query-local recset relative to the currently visible rows of its base table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-12&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-12&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_exists ==&lt;br /&gt;
&lt;br /&gt;
returns true if a table contains at least one visible row matching the given filter; uses scan boundary analysis without map/reduce setup&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-13&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a row exists&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row satisfies the existence test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-13&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan ==&lt;br /&gt;
&lt;br /&gt;
does an unordered parallel filter-map-reduce pass on a single table and returns the reduced result&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 6–10&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-14&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility and mutations; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;): table handle, query-local recset, or a list for temporary data&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a dataset is passed to the map phase. Equality and range comparisons may be translated into indexed scans&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row proceeds to map&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to map after filtering; pseudo columns are $update (update/delete current row), $recset_contains (row-bound RecSet membership), $set:&amp;amp;lt;column&amp;amp;gt;, $increment:&amp;amp;lt;column&amp;amp;gt;, and $invalidate:&amp;amp;lt;column&amp;amp;gt; (computed-column maintenance), plus NEW.&amp;amp;lt;column&amp;amp;gt; in trigger plans&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that extracts or produces one value from the row; it may also use documented pseudo columns for mutations or result output&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce, or returned directly when no reducer is supplied&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional aggregation function used first within shards and then to combine shard results &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for the reduce phase, otherwise nil is assumed &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;reduce2&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional final reducer that combines the neutral value with the result produced by reduce &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, in case of no hits, call map once anyway with NULL values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-14&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_batch ==&lt;br /&gt;
&lt;br /&gt;
does an unordered parallel filter-map-reduce pass on a single table using batchdata-backed #N pseudo columns and returns the reduced result&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 8–12&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-15&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility and mutations; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;): table handle, query-local recset, or a list for temporary data&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to filter; #0, #1, ... address batchdata slots&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a dataset is passed to the map phase&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when this table row and batch row proceed to map&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to map; #0, #1, ... address batchdata slots&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that extracts data from the table row and batch row&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce or returned directly&lt;br /&gt;
* &#039;&#039;&#039;stride&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): number of batchdata entries per batch row&lt;br /&gt;
* &#039;&#039;&#039;batchdata&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;any&amp;amp;gt;&amp;lt;/code&amp;gt;): flat batch buffer accessed via #N pseudo columns&lt;br /&gt;
** &#039;&#039;&#039;slot&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one batch value; every stride consecutive slots form a batch row&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional lambda function that aggregates mapped values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for the reduce phase, otherwise nil is assumed &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;reduce2&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional final reducer that combines the neutral value with the result produced by reduce &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, in case of no hits, call map once anyway with NULL values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-15&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_order_batch_accept ==&lt;br /&gt;
&lt;br /&gt;
incrementally scans a table or existing RecSet in scan_order order and applies a RecSet batch filter before OFFSET/LIMIT and map/reduce. The first candidate RecSet contains offset+limit rows; if too few rows are accepted, subsequent disjoint batches contain twice as many candidates until the accepted limit is satisfied or the input is exhausted. batchFilter is called as (batchFilter input_recset) and must return an exact subset RecSet of the same base table and transaction. A simple batchFilter may call (scan_recset tx input_recset filterColumns realFilter); complex filters may project input_recset to another table, apply search/ACL scans and project the result back to the input table. The returned RecSet is used only as a membership mask against the already ordered candidate vector, so output order is preserved without scanning the unordered RecSet again. For non-unique ORDER BY values, include an explicit unique tie-breaker. sortcols/sortdirs may both be empty; that path greedily collects candidates without sorting. limitPartitionCols is present for scan_order signature compatibility and currently must be 0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 10–14&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-16&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context used consistently by the candidate scan and every batch filter operation; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table_or_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|recset&amp;lt;/code&amp;gt;): base table or complete existing query-local RecSet from which ordered candidate batches are drawn&lt;br /&gt;
* &#039;&#039;&#039;batchFilter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): function (lambda (input_recset) accepted_recset). It may naively narrow input_recset with scan_recset, or run arbitrary RecSet projections/search/ACL operations and project back. It must return a same-table, same-transaction subset of input_recset&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;input_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): same as scan_order: columns or computed sort functions. Include a unique tie-breaker for a total repeatable order; use an empty list for greedy unsorted collection&lt;br /&gt;
** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
* &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): same as scan_order: one relation per sort column; must also be empty when sortcols is empty&lt;br /&gt;
** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
**** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
* &#039;&#039;&#039;limitPartitionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): reserved for scan_order signature compatibility; currently must be 0&lt;br /&gt;
* &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of batch-filter-accepted rows to skip; it is not the number of driver candidates already examined&lt;br /&gt;
* &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): finite maximum number of accepted rows passed to map; the initial candidate batch size is offset+limit and doubles for every subsequent batch&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to map after filtering; pseudo columns are $update (update/delete current row), $recset_contains (row-bound RecSet membership), $set:&amp;amp;lt;column&amp;amp;gt;, $increment:&amp;amp;lt;column&amp;amp;gt;, and $invalidate:&amp;amp;lt;column&amp;amp;gt; (computed-column maintenance), plus NEW.&amp;amp;lt;column&amp;amp;gt; in trigger plans; $break is reserved for internal ORC convergence and must not implement SQL OFFSET/LIMIT, which belong in the native offset and limit arguments&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): same map callback contract as scan_order; accepted record IDs are passed to its shard mapper in batches&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce or returned directly&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional serial reducer over mapped accepted rows, with the same accumulator contract as scan_order &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): optional neutral element for reduce; defaults to nil &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): optional scan_order-compatible outer behavior: map one NULL row when no accepted row reaches map &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;notFoundValue&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): optional result when no accepted row reaches map and isOuter is false; defaults to neutral &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-16&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_order ==&lt;br /&gt;
&lt;br /&gt;
does an ordered parallel filter and serial map-reduce pass on a single table and returns the reduced result&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 11–17&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-17&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility and mutations; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;): table handle, query-local RecSet, or a list for temporary data&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a dataset is passed to the map phase. Equality and range comparisons may be translated into indexed scans&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row proceeds to ordering and map&lt;br /&gt;
* &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): columns used for ordering; each entry corresponds to one relation in sortdirs&lt;br /&gt;
** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
* &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): one ordering relation per entry in sortcols; &amp;amp;lt; is ascending and &amp;amp;gt; is descending&lt;br /&gt;
** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
**** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
* &#039;&#039;&#039;limitPartitionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of leading sort columns that form the partition key for per-partition offset/limit. 0 (default) means global offset/limit.&lt;br /&gt;
* &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of globally ordered, filter-accepted items to skip before map; apply SQL OFFSET here rather than in map&lt;br /&gt;
* &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): maximum globally ordered, filter-accepted items passed to map; -1 means unlimited; apply SQL LIMIT here so shard-local Top-K and the global merge can brake early&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to map after filtering; pseudo columns are $update (update/delete current row), $recset_contains (row-bound RecSet membership), $set:&amp;amp;lt;column&amp;amp;gt;, $increment:&amp;amp;lt;column&amp;amp;gt;, and $invalidate:&amp;amp;lt;column&amp;amp;gt; (computed-column maintenance), plus NEW.&amp;amp;lt;column&amp;amp;gt; in trigger plans; $break is reserved for internal ORC convergence and must not implement SQL OFFSET/LIMIT, which belong in the native offset and limit arguments&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that extracts or produces one value from each accepted row&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce or returned directly&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional serial aggregation function over mapped values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for the reduce phase, otherwise nil is assumed &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, in case of no hits, call map once anyway with NULL values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;notFoundValue&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) result for no hits when isOuter is false; defaults to neutral &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;postOrderFilterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): optional columns for a predicate evaluated in global order before OFFSET/LIMIT are counted; use for expensive acceptance checks that cannot participate in index boundaries &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;postOrderFilter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional late acceptance predicate. Rejected rows do not count toward OFFSET/LIMIT and never reach map &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the ordered row counts toward OFFSET/LIMIT and reaches map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-17&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_order_multi ==&lt;br /&gt;
&lt;br /&gt;
does an ordered parallel filter and serial map-reduce pass across multiple tables simultaneously, merging results into a single sorted stream&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 13–17&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-18&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context&lt;br /&gt;
* &#039;&#039;&#039;tables&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;table|recset&amp;amp;gt;&amp;lt;/code&amp;gt;): scan sources; all per-table lists must have this length&lt;br /&gt;
** &#039;&#039;&#039;source&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|recset&amp;lt;/code&amp;gt;): base table or query-local record set for one input stream&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;lt;string&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;): filter column lists, one per table&lt;br /&gt;
** &#039;&#039;&#039;table filter columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to the matching filterFns entry&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name in the corresponding table&lt;br /&gt;
* &#039;&#039;&#039;filterFns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(columns:any...) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): filter lambdas, one per table&lt;br /&gt;
** &#039;&#039;&#039;table filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): predicate for the corresponding table and filterColumns entry&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row enters that table&#039;s ordered stream&lt;br /&gt;
* &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;): sort column lists, one per table; every inner list must match sortdirs in length and result domains&lt;br /&gt;
** &#039;&#039;&#039;table sort columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): sort expressions for the corresponding table&lt;br /&gt;
*** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
**** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
* &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): shared ordering relations used for every table stream and for the outer merge&lt;br /&gt;
** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
**** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
* &#039;&#039;&#039;perTableOffset&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;int&amp;amp;gt;|nil&amp;lt;/code&amp;gt;): optional per-table offsets; nil disables all per-table offsets&lt;br /&gt;
** &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): rows skipped in the corresponding table before the outer merge; -1 disables the offset&lt;br /&gt;
* &#039;&#039;&#039;perTableLimit&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;int&amp;amp;gt;|nil&amp;lt;/code&amp;gt;): optional per-table limits; nil disables all per-table limits&lt;br /&gt;
** &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): maximum rows retained from the corresponding table before the outer merge; -1 disables the limit&lt;br /&gt;
* &#039;&#039;&#039;limitPartitionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of leading sort columns forming partition key&lt;br /&gt;
* &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of items to skip (global)&lt;br /&gt;
* &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): max number of items to read (global; -1 = unlimited)&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;lt;string&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;): map column lists, one per table&lt;br /&gt;
** &#039;&#039;&#039;table map columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to the matching mapFns entry&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name in the corresponding table&lt;br /&gt;
* &#039;&#039;&#039;mapFns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): map lambdas, one per table&lt;br /&gt;
** &#039;&#039;&#039;table map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): mapper for the corresponding table and mapColumns entry&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value inserted into the merged stream and passed to reduce&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional aggregation function over mapped values from the merged stream &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for reduce &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, emit null row when no hits &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;notFoundValue&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) result for no hits when isOuter is false; defaults to neutral &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-18&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createdatabase ==&lt;br /&gt;
&lt;br /&gt;
creates a new database&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-19&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new database&lt;br /&gt;
* &#039;&#039;&#039;ignoreexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, return false instead of throwing an error &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-19&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropdatabase ==&lt;br /&gt;
&lt;br /&gt;
drops a database&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-20&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, don&#039;t throw an error if it doesn&#039;t exist &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-20&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== checktablemaintenance ==&lt;br /&gt;
&lt;br /&gt;
checks whether a user-initiated maintenance operation is allowed for a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-21&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-21&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== maintenance_capabilities ==&lt;br /&gt;
&lt;br /&gt;
returns the server-side maintenance capabilities for a database or table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-22&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-22&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createtable ==&lt;br /&gt;
&lt;br /&gt;
creates a table, runs its oninit option and registered after-create-table lifecycle triggers synchronously, and returns only after initialization completes; concurrent if-not-exists callers wait for that same completion&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-23&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the existing database that will contain the table&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table to create&lt;br /&gt;
* &#039;&#039;&#039;cols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;gt;&amp;lt;/code&amp;gt;): column and constraint definitions&lt;br /&gt;
** &#039;&#039;&#039;definition&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): one of (&amp;amp;quot;column&amp;amp;quot; name type dimensions typeparams), (&amp;amp;quot;unique&amp;amp;quot; name columns), or (&amp;amp;quot;foreign&amp;amp;quot; name local_columns referenced_table referenced_columns update_mode delete_mode). Column lists contain strings; foreign-key modes are restrict, cascade, or set null. A column definition&#039;s dimensions contains integers and its typeparams uses the same fields documented by createcolumn options&lt;br /&gt;
* &#039;&#039;&#039;options&#039;&#039;&#039; (&amp;lt;code&amp;gt;list|assoc&amp;lt;/code&amp;gt;): table options as an alternating key/value list&lt;br /&gt;
** &#039;&#039;&#039;auto_increment&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): first automatically assigned value; must be non-negative&lt;br /&gt;
** &#039;&#039;&#039;charset&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): default character set name&lt;br /&gt;
** &#039;&#039;&#039;collation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): default collation name&lt;br /&gt;
** &#039;&#039;&#039;comment&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): user-visible table comment&lt;br /&gt;
** &#039;&#039;&#039;engine&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): storage engine: safe, logged, sloppy, memory, or cache&lt;br /&gt;
** &#039;&#039;&#039;oninit&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): closed zero-argument initializer run synchronously once per data generation; concurrent if-not-exists callers wait for completion&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): ignored initializer result&lt;br /&gt;
* &#039;&#039;&#039;ifnotexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): when true, return false instead of failing if the table exists; if another caller is still creating it, wait for that caller&#039;s after-create-table initialization before returning false &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-23&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when this call created and initialized the table, false when ifnotexists reused an initialized table&lt;br /&gt;
&lt;br /&gt;
== createcolumn ==&lt;br /&gt;
&lt;br /&gt;
creates a new column in table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–7&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-24&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;colname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new column&lt;br /&gt;
* &#039;&#039;&#039;type&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the basetype&lt;br /&gt;
* &#039;&#039;&#039;dimensions&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;int&amp;amp;gt;&amp;lt;/code&amp;gt;): dimensions of the type, for example precision and scale for decimal&lt;br /&gt;
** &#039;&#039;&#039;dimension&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): one type-specific dimension&lt;br /&gt;
* &#039;&#039;&#039;options&#039;&#039;&#039; (&amp;lt;code&amp;gt;list|assoc&amp;lt;/code&amp;gt;): column properties and computed-column configuration as an alternating key/value list&lt;br /&gt;
** &#039;&#039;&#039;auto_increment&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): assign increasing values automatically&lt;br /&gt;
** &#039;&#039;&#039;collate&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): collation used for this column&lt;br /&gt;
** &#039;&#039;&#039;comment&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): user-visible column comment&lt;br /&gt;
** &#039;&#039;&#039;default&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): literal value used when an insert omits the column&lt;br /&gt;
** &#039;&#039;&#039;default_expression&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): expression evaluated when an insert omits the column&lt;br /&gt;
** &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): predicate limiting which rows are computed&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row should be computed&lt;br /&gt;
** &#039;&#039;&#039;filtercols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to filter before computing a value&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
** &#039;&#039;&#039;mapcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to mapfn for ordered-reduce computation&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
** &#039;&#039;&#039;mapfn&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): maps one source row into a value for reducefn&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reducefn&lt;br /&gt;
** &#039;&#039;&#039;null&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether the column accepts nil values&lt;br /&gt;
** &#039;&#039;&#039;partitioncount&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): number of leading sort columns that define independent reducer partitions&lt;br /&gt;
** &#039;&#039;&#039;primary&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether this column belongs to the primary key&lt;br /&gt;
** &#039;&#039;&#039;reducefn&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): combines ordered mapped values into the computed-column aggregate &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
**** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
** &#039;&#039;&#039;reduceinit&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): initial accumulator supplied to reducefn&lt;br /&gt;
** &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): columns or expressions defining ordered-reduce input order&lt;br /&gt;
*** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
**** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
** &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): one ordering relation for every sortcols entry&lt;br /&gt;
*** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
**** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
***** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
** &#039;&#039;&#039;temp&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether this is a query-local temporary computed column&lt;br /&gt;
** &#039;&#039;&#039;unique&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether values must be unique&lt;br /&gt;
** &#039;&#039;&#039;update&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): expression evaluated when a row is updated&lt;br /&gt;
* &#039;&#039;&#039;computorCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to computor in this order &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;computor&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda expression that computes this column from the values selected by computorCols &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): computed column value&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-24&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createkey ==&lt;br /&gt;
&lt;br /&gt;
creates a new key on a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-25&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;keyname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new key&lt;br /&gt;
* &#039;&#039;&#039;unique&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether the key is unique&lt;br /&gt;
* &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns to include&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-25&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropkey ==&lt;br /&gt;
&lt;br /&gt;
drops a named unique key from a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-26&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;keyname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the unique key&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-26&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createforeignkey ==&lt;br /&gt;
&lt;br /&gt;
creates a new foreign key on a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 7–7&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-27&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table1&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;keyname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new key&lt;br /&gt;
* &#039;&#039;&#039;columns1&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns to include&lt;br /&gt;
* &#039;&#039;&#039;table2&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;columns2&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns to include&lt;br /&gt;
* &#039;&#039;&#039;updatemode&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): restrict|cascade|set null&lt;br /&gt;
* &#039;&#039;&#039;deletemode&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): restrict|cascade|set null&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-27&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== shardcolumn ==&lt;br /&gt;
&lt;br /&gt;
tells us how it would partition a column according to their values. Returns a list of pivot elements.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-28&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;colname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the column&lt;br /&gt;
* &#039;&#039;&#039;numpartitions&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of partitions; optional. leave 0 if you want to detect the partiton number automatically or copy the partition schema of the table &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-28&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== partitiontable ==&lt;br /&gt;
&lt;br /&gt;
suggests a partition scheme for a table. If the table has no partition scheme yet, it will immediately apply that scheme and return true. If the table already has a partition scheme, it will alter the partitioning score such that the partitioning scheme is considered in the next repartitioning and return false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-29&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): associative list of string -&amp;amp;gt; list representing column name -&amp;amp;gt; pivots. You can compute pivots by (shardcolumn ...)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-29&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== altertable ==&lt;br /&gt;
&lt;br /&gt;
alters a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-30&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): one of owner|drop|engine|collation|auto_increment&lt;br /&gt;
* &#039;&#039;&#039;parameter&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): name of the column to drop or value of the parameter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-30&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== altercolumn ==&lt;br /&gt;
&lt;br /&gt;
alters a column&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-31&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the column&lt;br /&gt;
* &#039;&#039;&#039;operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): one of drop|type|collation|auto_increment|comment&lt;br /&gt;
* &#039;&#039;&#039;parameter&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): name of the column to drop or value of the parameter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-31&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== droptable ==&lt;br /&gt;
&lt;br /&gt;
removes a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-32&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, don&#039;t throw an error if it already exists &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-32&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropcolumn ==&lt;br /&gt;
&lt;br /&gt;
drops a column from a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-33&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the column to drop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-33&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== migratedropcolumn ==&lt;br /&gt;
&lt;br /&gt;
drops a legacy system column during startup migration&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-34&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): legacy column name&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-34&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== invalidatecolumn ==&lt;br /&gt;
&lt;br /&gt;
marks all values of a computed column as stale&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-35&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the computed column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-35&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== invalidateorc ==&lt;br /&gt;
&lt;br /&gt;
invalidates ORC column rows from a sort key onwards via validMask scan&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-36&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the ORC column&lt;br /&gt;
* &#039;&#039;&#039;sortkeys&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): composite sort key values from which to invalidate&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-36&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== register_keytable_cleanup ==&lt;br /&gt;
&lt;br /&gt;
registers triggers on a base table to maintain keytable entries (insert/delete group keys)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-37&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;base_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;kt_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;tblvar&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): table alias used in scan column prefixes&lt;br /&gt;
* &#039;&#039;&#039;key_pairs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of (base_col kt_col) pairs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-37&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== initialize_cache_table ==&lt;br /&gt;
&lt;br /&gt;
registers maintenance, locks source tables for a consistent snapshot, and runs a canonical planner-cache initializer exactly once&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–6&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-38&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;transaction&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): explicit transaction context carrying query-session ownership&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;source_tables&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;register_maintenance&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;initializer&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;finalizer&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional zero-argument finalizer run under the same source-table locks after initialization &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-38&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== touch_keytable ==&lt;br /&gt;
&lt;br /&gt;
extends the lease on a keytable so CacheManager defers eviction&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-39&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-39&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== locktables ==&lt;br /&gt;
&lt;br /&gt;
acquires WRITE or READ user-level locks on a list of tables (LOCK TABLES); implicitly releases any previously held locks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-40&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;locks&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): flat list of schema, table, write? triples&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-40&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== unlocktables ==&lt;br /&gt;
&lt;br /&gt;
releases all user-level table locks held by this session&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-41&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-41&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== get_fk_target ==&lt;br /&gt;
&lt;br /&gt;
returns (ref_table ref_column) if a single-column FK exists for the given column, nil otherwise&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-42&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-42&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== renametable ==&lt;br /&gt;
&lt;br /&gt;
renames a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-43&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;oldname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): current name of the table&lt;br /&gt;
* &#039;&#039;&#039;newname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): new name of the table&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-43&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== insert ==&lt;br /&gt;
&lt;br /&gt;
inserts a new dataset into table and returns the number of successful items&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–7&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-44&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of column names, e.g. &#039;(&amp;amp;quot;ID&amp;amp;quot;, &amp;amp;quot;value&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;datasets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of list of column values, e.g. &#039;(&#039;(1 10) &#039;(2 15))&lt;br /&gt;
* &#039;&#039;&#039;onCollisionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns of the old dataset that have to be passed to onCollision. Can also request $update, $set:&amp;amp;lt;computed-column&amp;amp;gt;, or NEW.&amp;amp;lt;insert-column&amp;amp;gt;. &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;onCollision&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): function called for each collision. Its positional parameters are the values requested by onCollisionCols, in the same order. If omitted, collisions raise an error. &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;column values&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each onCollisionCols entry &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;mergeNull&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, it will handle NULL values as equal according to SQL 2003&#039;s definition of DISTINCT (https://en.wikipedia.org/wiki/Null_(SQL)#When_two_nulls_are_equal:_grouping,_sorting,_and_some_set_operations) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;onInsertid&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): called once with the first auto_increment id assigned for this INSERT &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;id&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): first assigned auto_increment id&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): ignored callback result&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-44&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== stat ==&lt;br /&gt;
&lt;br /&gt;
return system statistics as assoc: mem_available, mem_total, process_memory, shard_memory, shard_budget, persisted_memory, persisted_budget, cache_entry_count, cache_entry_size. (stat schema) and (stat schema tbl) return a string with detailed memory usage.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-45&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) database name for detailed string output &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) table name for detailed string output &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-45&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== totalmem ==&lt;br /&gt;
&lt;br /&gt;
Returns total physical memory in bytes (from /proc/meminfo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-46&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-46&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== resolve_column_name ==&lt;br /&gt;
&lt;br /&gt;
resolve a physical column name from immutable table metadata&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-47&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): database name&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): table name&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name&lt;br /&gt;
* &#039;&#039;&#039;ignorecase&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether identifier case is ignored&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-47&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== show ==&lt;br /&gt;
&lt;br /&gt;
show databases/tables/columns/shards&lt;br /&gt;
&lt;br /&gt;
(show) lists database names (show schema) lists table names (show table_handle) lists the memoized column defs (show table_handle true) returns table metadata (show table_handle &amp;amp;quot;statistics&amp;amp;quot;) returns index statistics (show schema true) lists tables with full info: [{name,engine,row_count,size_bytes,collation,comment},...] (show schema tbl) lists column defs (show schema tbl true) returns assoc {columns,meta,shards} (show schema tbl N) returns shard N overview assoc {shard,state,main_count,delta,deletions,size_bytes} (show schema tbl N true) returns shard N full assoc adding columns and indexes (show schema tbl &amp;amp;quot;statistics&amp;amp;quot;) returns INFORMATION_SCHEMA index statistics (show schema tbl &amp;amp;quot;indexes&amp;amp;quot;) returns MySQL SHOW INDEX rows&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-48&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema_or_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|table|recset&amp;lt;/code&amp;gt;): (optional) database name or resolved table/recset handle &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;table_or_property&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|bool&amp;lt;/code&amp;gt;): (optional) table name, true for full info, or &amp;amp;quot;statistics&amp;amp;quot; for a handle &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;property&#039;&#039;&#039; (&amp;lt;code&amp;gt;int|bool|string&amp;lt;/code&amp;gt;): (optional) shard index (int), true for full table info, or &amp;amp;quot;statistics&amp;amp;quot; &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;full&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) true to include columns and indexes in shard detail &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-48&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== show_triggers ==&lt;br /&gt;
&lt;br /&gt;
show triggers for a given table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-49&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): database name&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) table name, if omitted shows all triggers in schema &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-49&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== rebuild ==&lt;br /&gt;
&lt;br /&gt;
rebuilds main storages and returns the amount of time it took; with a table handle, rebuilds only that table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-50&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table_or_all&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool|table&amp;lt;/code&amp;gt;): table handle for a table-local rebuild; otherwise whether to rebuild unchanged shards globally (default: false) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;all_or_repartition&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): with a table: whether to rebuild unchanged shards; globally: whether to repartition (default: true) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;repartition&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): with a table handle, whether to repartition that table (default: true) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-50&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;loadcsv&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== loadCSV ==&lt;br /&gt;
&lt;br /&gt;
loads a CSV stream into a table and returns the amount of time it took. The first line of the file must be the headlines. The headlines must match the table&#039;s columns exactly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-51&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): CSV file, load with: (stream filename)&lt;br /&gt;
* &#039;&#039;&#039;delimiter&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) delimiter defaults to &amp;amp;quot;;&amp;amp;quot; &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;firstline&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if the first line contains the column names (otherwise, the tables column order is used) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-51&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;loadjson&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== loadJSON ==&lt;br /&gt;
&lt;br /&gt;
loads a .jsonl file from stream into a database and returns the amount of time it took. JSONL is a linebreak separated file of JSON objects. Each JSON object is one dataset in the database. Before you add rows, you must declare the table in a line &#039;#table &amp;amp;lt;tablename&amp;amp;gt;&#039;. All other lines starting with # are comments. Columns are created dynamically as soon as they occur in a json object.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-52&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database where you want to put the tables in&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): stream of the .jsonl file, read with: (stream filename)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-52&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== settings ==&lt;br /&gt;
&lt;br /&gt;
reads or writes a global settings value. This modifies your data/settings.json.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-53&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;key&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the key to set or get (for reference, rts) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): new value of that setting &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-53&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createcreatetabletrigger ==&lt;br /&gt;
&lt;br /&gt;
registers a lifecycle trigger that fires synchronously after a future createtable for the given schema/table succeeds&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 6–6&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-54&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table to watch for creation&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;source_sql&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): original SQL body text (for diagnostics)&lt;br /&gt;
* &#039;&#039;&#039;body&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): trigger body (Scheme procedure or deferred trigger expression)&lt;br /&gt;
* &#039;&#039;&#039;visible&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true = user trigger, false = internal trigger&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-54&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropcreatetabletrigger ==&lt;br /&gt;
&lt;br /&gt;
removes a registered create-table lifecycle trigger&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-55&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table watched for creation&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): don&#039;t throw error if trigger doesn&#039;t exist&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-55&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createtrigger ==&lt;br /&gt;
&lt;br /&gt;
creates a new trigger on a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 6–6&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-56&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;timing&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): one of: before_insert, after_insert, before_update, after_update, before_delete, after_delete&lt;br /&gt;
* &#039;&#039;&#039;source_sql&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): original SQL body text (for SHOW TRIGGERS)&lt;br /&gt;
* &#039;&#039;&#039;body&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): trigger body (parsed Scheme expression)&lt;br /&gt;
* &#039;&#039;&#039;visible&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true = user trigger (shown in SHOW TRIGGERS), false = internal trigger (hidden)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-56&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== droptrigger ==&lt;br /&gt;
&lt;br /&gt;
removes a trigger from a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-57&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): don&#039;t throw error if trigger doesn&#039;t exist&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-57&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== mysql_import ==&lt;br /&gt;
&lt;br /&gt;
imports schema+data from a MySQL server into MemCP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–8&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-58&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;host&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): MySQL host (nil =&amp;amp;gt; 127.0.0.1)&lt;br /&gt;
* &#039;&#039;&#039;port&#039;&#039;&#039; (&amp;lt;code&amp;gt;int|nil&amp;lt;/code&amp;gt;): MySQL port (nil =&amp;amp;gt; 3306)&lt;br /&gt;
* &#039;&#039;&#039;username&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): MySQL username&lt;br /&gt;
* &#039;&#039;&#039;password&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): MySQL password&lt;br /&gt;
* &#039;&#039;&#039;sourcedb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source database (omit/nil =&amp;amp;gt; all non-system dbs) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targetdb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target database (omit/nil =&amp;amp;gt; sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sourcetable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source table (omit/nil =&amp;amp;gt; all tables in sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targettable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target table (omit/nil =&amp;amp;gt; sourcetable) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-58&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== psql_import ==&lt;br /&gt;
&lt;br /&gt;
imports schema+data from a PostgreSQL server into MemCP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–9&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-59&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;host&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): PostgreSQL host (nil =&amp;amp;gt; 127.0.0.1)&lt;br /&gt;
* &#039;&#039;&#039;port&#039;&#039;&#039; (&amp;lt;code&amp;gt;int|nil&amp;lt;/code&amp;gt;): PostgreSQL port (nil =&amp;amp;gt; 5432)&lt;br /&gt;
* &#039;&#039;&#039;username&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): PostgreSQL username&lt;br /&gt;
* &#039;&#039;&#039;password&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): PostgreSQL password&lt;br /&gt;
* &#039;&#039;&#039;sourcedb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source database (omit/nil =&amp;amp;gt; all non-system dbs) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sourceschema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source schema (omit/nil =&amp;amp;gt; all non-system schemas in sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targetdb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target database (omit/nil =&amp;amp;gt; sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sourcetable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source table (omit/nil =&amp;amp;gt; all tables in sourceschema) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targettable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target table (omit/nil =&amp;amp;gt; sourcetable) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-59&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Settings&amp;diff=402</id>
		<title>Settings</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Settings&amp;diff=402"/>
		<updated>2026-08-28T10:14:03Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;settings&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Settings =&lt;br /&gt;
&lt;br /&gt;
Read, write, or list runtime settings from Scheme:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;(settings &amp;quot;ShardSize&amp;quot;)&lt;br /&gt;
(settings &amp;quot;ExplainWidth&amp;quot; 80)&lt;br /&gt;
(settings)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Settings are stored with the database catalog. Validate production changes in a staging workload; memory, planner, and durability-related values affect behavior.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Setting&lt;br /&gt;
! style=&amp;quot;text-align: right;&amp;quot;| Default&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Backtrace&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| false&lt;br /&gt;
| Retain more Scheme source/backtrace information.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;Trace&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TracePrint&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| false&lt;br /&gt;
| Runtime trace collection and printing.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PartitionMaxDimensions&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 10&lt;br /&gt;
| Maximum adaptive partition dimensions.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;DefaultEngine&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;&lt;br /&gt;
| One of &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ShardSize&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 60000&lt;br /&gt;
| Target rows used by shard/repartition decisions.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;AnalyzeMinItems&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 50&lt;br /&gt;
| Minimum work before recording scan statistics.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;IndexThreshold&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 5&lt;br /&gt;
| Minimum shard rows for a new adaptive index.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MaxRamPercent&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 50&lt;br /&gt;
| Overall MemCP RAM budget when byte override is zero.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MaxRamBytes&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 0&lt;br /&gt;
| Exact overall budget; zero uses percentage.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MaxPersistPercent&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 30&lt;br /&gt;
| Budget for reloadable persisted data.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MaxPersistBytes&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 0&lt;br /&gt;
| Exact persisted-data budget.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MetricsTracing&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| false&lt;br /&gt;
| Periodically write performance metrics.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MetricsTracingInterval&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 60&lt;br /&gt;
| Metrics interval in seconds when zero/defaulted.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ShutdownDrainSeconds&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 10&lt;br /&gt;
| Wait for in-flight requests during shutdown.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;LogJIT&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| false&lt;br /&gt;
| Log native JIT compilation details.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ScanDebugging&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| false&lt;br /&gt;
| Log scan boundaries, index selection, and scan details.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ExplainWidth&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 20&lt;br /&gt;
| Pretty-print width for EXPLAIN expressions.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;JoinReorderDPBudget&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 256&lt;br /&gt;
| Connected subsets retained by exact join search.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ErrorQueryLog&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| false&lt;br /&gt;
| Store failed queries in &amp;lt;code&amp;gt;system_statistic.errors&amp;lt;/code&amp;gt;.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MaxErrorQueryLog&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 0&lt;br /&gt;
| Error-log row limit; zero is unlimited.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PrintLog&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| false&lt;br /&gt;
| Store Scheme print/time output.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;MaxPrintLog&amp;lt;/code&amp;gt;&lt;br /&gt;
| style=&amp;quot;text-align: right;&amp;quot;| 0&lt;br /&gt;
| Print-log row limit; zero is unlimited.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Use [[Memory_Management_and_Eviction|Memory Management and Eviction]], [[Query_Planner_and_Physical_Lowering|Query Planner and Physical Lowering]], and [[Dashboard_and_Operations|Dashboard and Operations]] for operational context.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Scan&amp;diff=401</id>
		<title>Scan</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Scan&amp;diff=401"/>
		<updated>2026-08-28T10:14:03Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Scan =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_order_multi&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_exists&amp;lt;/code&amp;gt;, and transaction-bound variants are physical storage operators emitted after logical planning. Their exact generated signatures are listed under [[Storage]].&lt;br /&gt;
&lt;br /&gt;
The physical lowerer extracts safe equality, range, IN-list, LIKE-prefix, computed-expression, ordering, and RecSet constraints. A boundary may be exact or merely a candidate superset. Candidate boundaries always retain the original SQL predicate as a residual filter.&lt;br /&gt;
&lt;br /&gt;
Column values are read in batches through encoding-specific range or multi-record fast paths. Ordered scans can combine main-index and delta ordering, propagate early stop, and use offset/limit or top-k braking when semantics and cost allow. [[RecSets]] identify records for one base relation and visibility snapshot; they do not define join multiplicity or result order. Their adaptive ranges, positive-ID lists, and bitmaps let later scans reuse a narrow domain without materializing wide rows.&lt;br /&gt;
&lt;br /&gt;
Application code should use SQL. Planner contributors must keep scan objects, RecSets, ORC columns, and helper tables out of the parser and logical IR. See [[Query Planner and Physical Lowering]] and the repository&#039;s &amp;lt;code&amp;gt;INVARIANTS.md&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Reading a plan ==&lt;br /&gt;
&lt;br /&gt;
For a query such as:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT customer_id, SUM(total)&lt;br /&gt;
FROM orders&lt;br /&gt;
WHERE created_at &amp;gt;= &#039;2026-01-01&#039;&lt;br /&gt;
GROUP BY customer_id&lt;br /&gt;
ORDER BY SUM(total) DESC&lt;br /&gt;
LIMIT 20;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
the logical plan establishes filtering, grouping, ordering, and LIMIT semantics. Physical lowering can then choose a bounded date range, read only &amp;lt;code&amp;gt;created_at&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;customer_id&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;total&amp;lt;/code&amp;gt;, fuse filter/aggregation, and apply top-k braking. Use &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt; to see what was actually selected; SQL spelling alone does not force an index or RecSet.&lt;br /&gt;
&lt;br /&gt;
== Low-level callback contract ==&lt;br /&gt;
&lt;br /&gt;
Unordered scans can perform shard-local map/reduce work and combine partial accumulators with a second reducer. Ordered scans retain serial output order and own OFFSET/LIMIT/early stop. Update-capable callbacks receive a controlled row-update handle under the scan&#039;s transaction and locking rules. The generated [[Storage]] chapter is authoritative for parameter names and return types at the referenced commit.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Stage !! Unordered &amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt; !! Ordered &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Filter/access path || Parallel per eligible shard; may use indexes/boundaries || Parallel candidate filtering and local ordering where useful&lt;br /&gt;
|-&lt;br /&gt;
| Map || Parallel per shard || Applied in requested global order&lt;br /&gt;
|-&lt;br /&gt;
| Reduce || Shard-local partial reductions plus a final combine || Serial in output order when order affects semantics&lt;br /&gt;
|-&lt;br /&gt;
| Early stop || Cancellation or consumer stop || OFFSET/LIMIT and compatible ordered braking&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Scheme examples ==&lt;br /&gt;
&lt;br /&gt;
These examples illustrate the callback roles; use the exact current signatures from [[Storage]] when writing low-level code.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* resolve the current transaction and table once */&lt;br /&gt;
(set tx ((context &amp;quot;session&amp;quot;) &amp;quot;__memcp_tx&amp;quot;))&lt;br /&gt;
(set tbl1 (table &amp;quot;schema&amp;quot; &amp;quot;tbl1&amp;quot;))&lt;br /&gt;
(set tbl2 (table &amp;quot;schema&amp;quot; &amp;quot;tbl2&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
/* print key/value pairs */&lt;br /&gt;
(scan tx tbl1 &#039;() (lambda () true)&lt;br /&gt;
	&#039;(&amp;quot;k&amp;quot; &amp;quot;v&amp;quot;) (lambda (k v) (print &amp;quot;tbl1[&amp;quot; k &amp;quot;] = &amp;quot; v)))&lt;br /&gt;
&lt;br /&gt;
/* find a key through an indexable equality predicate */&lt;br /&gt;
(scan tx tbl1 &#039;(&amp;quot;k&amp;quot;) (lambda (k) (equal? k 12))&lt;br /&gt;
	&#039;(&amp;quot;v&amp;quot;) (lambda (v) v))&lt;br /&gt;
&lt;br /&gt;
/* shard-local sum with neutral value */&lt;br /&gt;
(scan tx tbl2 &#039;() (lambda () true)&lt;br /&gt;
	&#039;(&amp;quot;weight&amp;quot;) (lambda (weight) weight) + 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An ordered scan additionally receives sort expressions/directions, OFFSET and LIMIT. Filtering and local ordering may run in parallel, but output order and order-sensitive reduction remain serial. Do not use side effects as a substitute for a reducer when result order matters. See [[RecSets]] for ordered membership intersection and progressively filtered candidate batches.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=SQL_over_REST&amp;diff=400</id>
		<title>SQL over REST</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=SQL_over_REST&amp;diff=400"/>
		<updated>2026-08-28T10:14:03Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= SQL over REST =&lt;br /&gt;
&lt;br /&gt;
Submit MySQL-dialect SQL to &amp;lt;code&amp;gt;/sql/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt; and PostgreSQL-dialect SQL to &amp;lt;code&amp;gt;/psql/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt;. The HTTP interface is useful for scripts, jobs, dashboards, and services that do not need a MySQL driver. It uses the same parser, planner, permissions, storage engine, and transaction machinery as the other SQL frontend.&lt;br /&gt;
&lt;br /&gt;
POST keeps credentials and SQL out of the URL and avoids URL-length and escaping problems:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --fail-with-body -u root:strong-password \&lt;br /&gt;
  -H &#039;Content-Type: text/plain; charset=utf-8&#039; \&lt;br /&gt;
  --data-binary &#039;SELECT id, name FROM users ORDER BY id LIMIT 10&#039; \&lt;br /&gt;
  http://localhost:4321/sql/myapp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
GET with URL-encoded SQL after the database name remains a compatibility convenience. Prefer POST for applications and logs.&lt;br /&gt;
&lt;br /&gt;
== JSONL results and errors ==&lt;br /&gt;
&lt;br /&gt;
Row-producing queries return newline-delimited JSON (NDJSON/JSONL): one object per row. Clients can therefore process a large result incrementally instead of waiting for one enclosing array.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
{&amp;quot;id&amp;quot;: 1, &amp;quot;name&amp;quot;: &amp;quot;Ada&amp;quot;}&lt;br /&gt;
{&amp;quot;id&amp;quot;: 2, &amp;quot;name&amp;quot;: &amp;quot;Grace&amp;quot;}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A successful write that emits no result rows returns an &amp;lt;code&amp;gt;affected_rows&amp;lt;/code&amp;gt; object. Authentication failures use HTTP 401; SQL failures use a non-success status and a text error body. Always check both status and body. A fast 401 or SQL error is not successful query throughput.&lt;br /&gt;
&lt;br /&gt;
== Parameters ==&lt;br /&gt;
&lt;br /&gt;
URL query parameters are placed into the SQL session and can be referenced as named variables such as &amp;lt;code&amp;gt;@user_id&amp;lt;/code&amp;gt;. Keep the SQL text in the POST body and URL-encode values:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --fail-with-body -u root:strong-password \&lt;br /&gt;
  --data-binary &#039;SELECT id, name FROM users WHERE id = @user_id&#039; \&lt;br /&gt;
  &#039;http://localhost:4321/sql/myapp?user_id=42&#039;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This avoids SQL string concatenation, but applications must still validate type, range, and authorization. Never use a parameter supplied by the caller to choose an unrestricted schema, table, or column name.&lt;br /&gt;
&lt;br /&gt;
== PostgreSQL syntax ==&lt;br /&gt;
&lt;br /&gt;
Use the &amp;lt;code&amp;gt;/psql/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt; endpoint for PostgreSQL-style syntax and JSON operators:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --fail-with-body -u root:strong-password \&lt;br /&gt;
  --data-binary &amp;quot;SELECT payload-&amp;gt;&amp;gt;&#039;name&#039; FROM events LIMIT 10&amp;quot; \&lt;br /&gt;
  http://localhost:4321/psql/myapp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a syntax frontend, not the PostgreSQL wire protocol and not a promise of complete PostgreSQL compatibility. See [[Supported SQL]] and [[JSON]].&lt;br /&gt;
&lt;br /&gt;
== Transactions across HTTP requests ==&lt;br /&gt;
&lt;br /&gt;
Without an explicit session identifier, each request uses its request-local session and automatic transaction handling. To retain transaction state across multiple HTTP requests, send the same unpredictable &amp;lt;code&amp;gt;X-Session-Id&amp;lt;/code&amp;gt; header on each request. Treat it like a credential, prevent sharing between users, and always finish with COMMIT or ROLLBACK. For conventional long-lived database sessions, the MySQL protocol is often the simpler interface.&lt;br /&gt;
&lt;br /&gt;
== Security and custom APIs ==&lt;br /&gt;
&lt;br /&gt;
HTTP Basic authentication uses MemCP users and grants. Never expose the development default password, and terminate TLS at a trusted proxy or restrict the network before sending credentials. General SQL access is powerful; browsers and public clients should normally receive a narrowly scoped application endpoint instead.&lt;br /&gt;
&lt;br /&gt;
For custom routing, response formats, authentication, or WebSockets, see [[In-Database WebApps and REST Services]]. Also see [[Security and Authentication]], [[Database Tools compatibility with MemCP]], and [[Performance Measurement]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Process_Hibernation&amp;diff=399</id>
		<title>Process Hibernation</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Process_Hibernation&amp;diff=399"/>
		<updated>2026-08-28T10:14:02Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Process Hibernation =&lt;br /&gt;
&lt;br /&gt;
Linux CRIU can checkpoint and restore a complete process, including RAM-only state. This makes it interesting for development experiments with &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; tables, but it is not MemCP&#039;s supported durability, backup or upgrade mechanism. Open sockets, kernel features, file descriptors, JIT mappings and external storage connections can make restoration fail or restore an unsafe environment.&lt;br /&gt;
&lt;br /&gt;
An experimental local workflow is:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo criu dump -t PID -j -D DUMP_DIRECTORY&lt;br /&gt;
sudo criu restore -j -D DUMP_DIRECTORY&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Stop incoming traffic and test the exact kernel, CRIU and MemCP build before relying on this even temporarily. A checkpoint is tied to its host/runtime environment and does not replace a portable data backup. Persistent production data should use &amp;lt;code&amp;gt;ENGINE=safe&amp;lt;/code&amp;gt; and tested storage-level backup/restore procedures.&lt;br /&gt;
&lt;br /&gt;
See [[Persistency and Performance Guarantees]], [[File System]] and [[Deployment]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Persistency_and_Performance_Guarantees&amp;diff=398</id>
		<title>Persistency and Performance Guarantees</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Persistency_and_Performance_Guarantees&amp;diff=398"/>
		<updated>2026-08-28T10:14:02Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;persistency-and-performance-guarantees&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Persistency and Performance Guarantees =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Verified against commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 28 August 2026.&#039;&#039;&#039; The durability contract applies to committed changes and depends on the configured persistence backend honoring its documented synchronization/acknowledgement semantics.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MemCP lets every table choose its own balance between durability and write latency with &amp;lt;code&amp;gt;ENGINE=&amp;amp;lt;mode&amp;amp;gt;&amp;lt;/code&amp;gt;. The default is &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;. This is a data-safety decision, not merely a performance hint: the modes differ in what is written, when it becomes durable, what survives a failure, and whether memory pressure may discard the data.&lt;br /&gt;
&lt;br /&gt;
MemCP&#039;s performance promise is architectural: hot data is processed from compact columnar memory, independent shards can run in parallel, and aggregation is reduced from shard-local partial results. Actual latency still depends on the workload, hardware, storage backend, transaction conflicts, constraints, cache residency, and JIT coverage.&lt;br /&gt;
&lt;br /&gt;
== Choose an ENGINE at a glance ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
! Engine !! Rows stored in !! Write path !! Survives process crash !! Survives kernel crash/power loss !! May be evicted !! Typical use&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; &#039;&#039;&#039;(default)&#039;&#039;&#039; || Compressed column files plus RAM/delta state || WAL, synchronized at transaction commit || Yes || Yes, when the persistence backend honors the required durable synchronization || Reloadable RAM representation only; disk data remains || Business data, accounting, orders, identities, anything that must not be lost&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; || Compressed column files plus RAM/delta state || WAL without &amp;lt;code&amp;gt;fsync&amp;lt;/code&amp;gt;; measured write paths have reached about 10× &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; throughput || Yes || Recent committed writes may be lost || Reloadable RAM representation only; disk data remains || High write rates with explicitly accepted power-loss risk, preferably protected by UPS/battery-backed storage&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; || Rebuilt compressed column files plus unlogged RAM delta || No WAL; normally one bulk compression/rebuild publication every 15 minutes || Main storage yes; delta since the last successful rebuild is lost || Same: recent inserts/updates/deletes may be lost || Reloadable persisted main data; an unflushed delta prevents eviction || Reconstructible telemetry, staging data, usage statistics, sensor data, and flash-backed workloads that deliberately trade a loss window for fewer continuous writes&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; || RAM only; schema is retained || No WAL or row files || No || No || No, because eviction would destroy the only copy || Process-lifetime sessions, transient coordination, scratch state&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; || RAM only; reconstructible definition/&amp;lt;code&amp;gt;oninit&amp;lt;/code&amp;gt; is retained || No WAL or row files || No || No || &#039;&#039;&#039;Yes; the complete contents may disappear while MemCP is running&#039;&#039;&#039; || Rebuildable caches, observer handles, optimizer/helper data&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In shorthand:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; provide the shortest RAM-only write path but no row persistence;&lt;br /&gt;
* &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; avoid a synchronous durability fence, but accept different loss windows;&lt;br /&gt;
* &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; waits for durable WAL synchronization at commit and is the mode for irreplaceable data.&lt;br /&gt;
&lt;br /&gt;
Do not infer isolation semantics from the ENGINE. Isolation and transaction visibility are documented separately under [[Transactions and Isolation]]. A transaction touching several tables inherits the durability strengths and risks of every involved table.&lt;br /&gt;
&lt;br /&gt;
== Performance guarantees and read speed ==&lt;br /&gt;
&lt;br /&gt;
=== Hot reads stay in the columnar execution path ===&lt;br /&gt;
&lt;br /&gt;
MemCP is designed so that the active working set is read from RAM and remains fast. Filters, projections, [[RecSets]], grouping, and aggregates can consume only the referenced compressed columns, in batches, without first reconstructing wide rows. This reduces cache misses and memory traffic.&lt;br /&gt;
&lt;br /&gt;
Persistent cold columns may nevertheless be unloaded from RAM. Their next access transparently reloads them from the configured filesystem or object store. Therefore “all reads come from RAM” describes the intended &#039;&#039;&#039;hot path&#039;&#039;&#039;, not a promise that a cold or undersized deployment never performs storage I/O. A repeatedly evicted hot set becomes I/O-bound even though the result remains correct.&lt;br /&gt;
&lt;br /&gt;
=== Writes scale across independent shards ===&lt;br /&gt;
&lt;br /&gt;
INSERT and UPDATE operations without unique-key checks, foreign-key checks, hot-row conflicts, or other serializing work can execute shard-locally and scale across shards. Adding CPU cores and distributing data over enough useful shards is intended to preserve response time as the dataset and concurrent work grow.&lt;br /&gt;
&lt;br /&gt;
Scaling is not automatic when all writes target one shard or key range. Unique and foreign-key probes, transaction conflicts, triggers, WAL synchronization, repartitioning, and a storage backend with limited throughput can become the governing cost.&lt;br /&gt;
&lt;br /&gt;
=== Aggregates use parallel partial results ===&lt;br /&gt;
&lt;br /&gt;
Associative aggregates such as &amp;lt;code&amp;gt;SUM&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;COUNT&amp;lt;/code&amp;gt;, and the partial state behind &amp;lt;code&amp;gt;AVG&amp;lt;/code&amp;gt; can be computed independently per shard and reduced afterwards. With enough rows and shards, this is designed to scale close to the available CPU count until another shared resource becomes limiting. Tiny inputs, ordered/window semantics, skewed shards, or a serial final stage do not benefit in the same way.&lt;br /&gt;
&lt;br /&gt;
=== Memory bandwidth remains finite ===&lt;br /&gt;
&lt;br /&gt;
An earlier MemCP description recorded about 40&amp;amp;nbsp;GiB/s of memory bandwidth on the tested machines and observed that an uncompressed scan on a 128-core CPU stopped improving beyond roughly eight cores. The exact hardware, data shape, and benchmark protocol were not retained, so these figures are historical orientation rather than a current universal limit.&lt;br /&gt;
&lt;br /&gt;
The design response remains important: [[Columnar Storage]] and adaptive compression reduce the number of cache lines moved per qualifying value. A compact 3-, 5-, or 12-bit representation may use more lightweight decoding but still finish sooner than an uncompressed representation that saturates memory bandwidth. This is why MemCP aims to scale useful scans beyond the core count at which a wider row representation has already exhausted the memory channels.&lt;br /&gt;
&lt;br /&gt;
== Persistency guarantees and write speed ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;ENGINE=safe&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; is the default and strongest mode:&lt;br /&gt;
&lt;br /&gt;
* the rebuilt main storage is kept as compressed column files;&lt;br /&gt;
* changes in the delta are recorded in a write-ahead log (WAL);&lt;br /&gt;
* a transaction succeeds only after the WALs of touched &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; shards have been synchronized at commit;&lt;br /&gt;
* after a process crash, kernel crash, or power failure, the WAL is replayed and committed changes are recovered;&lt;br /&gt;
* one transaction can contain many changed rows while paying one commit-time synchronization round per touched WAL rather than one per row;&lt;br /&gt;
* the synchronization fence adds latency, especially for single-row autocommit workloads.&lt;br /&gt;
&lt;br /&gt;
Use it for accounting records, customer data, orders, permissions, and any data whose loss would be unacceptable. The power-loss guarantee assumes the configured persistence backend provides the durability promised by its sync/ack operation. For example, remote/object backends must be evaluated according to their own replication and acknowledgement contract; see [[Storage Backends]].&lt;br /&gt;
&lt;br /&gt;
An early system measurement reported approximately 1,700 individually synchronized writes per second. It did not retain the device, filesystem, transaction size, or commit used. Keep the number as project history, not as a fixed MemCP limit. Modern NVMe, group commit through larger transactions, storage caches, and backend behavior can all change the result substantially.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;ENGINE=logged&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; keeps the WAL but deliberately omits &amp;lt;code&amp;gt;fsync&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* main storage is represented by compressed column files;&lt;br /&gt;
* every delta change is written to WAL files;&lt;br /&gt;
* the operation may succeed while the operating system still holds WAL bytes in volatile page cache;&lt;br /&gt;
* a MemCP process crash can recover the written log;&lt;br /&gt;
* a kernel crash, abrupt power loss, or storage-controller loss can discard recent committed changes that were not flushed physically;&lt;br /&gt;
* buffering improves write latency at the price of that explicit loss window.&lt;br /&gt;
&lt;br /&gt;
In project write measurements, switching the same write path from &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; has reached roughly &#039;&#039;&#039;10× the write throughput&#039;&#039;&#039;. The mechanism is straightforward: &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; must wait for a durable storage fence at commit, whereas &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; can return after writing into the operating system&#039;s buffered path. The exact gain depends on transaction size, WAL device, filesystem/backend, queueing and concurrency; a larger transaction can also amortize &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; synchronization without weakening durability.&lt;br /&gt;
&lt;br /&gt;
Use this mode only when process-crash recovery is sufficient or when external power and storage protection make the remaining risk acceptable. It is not a substitute for &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; merely because the WAL file exists.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;ENGINE=sloppy&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; persists compact main storage but has no WAL:&lt;br /&gt;
&lt;br /&gt;
* current main columns are stored on the persistence backend;&lt;br /&gt;
* new inserts, updates, and deletions remain in the in-memory delta until rebuild;&lt;br /&gt;
* MemCP schedules a compression/rebuild pass every 15 minutes and also rebuilds during a clean shutdown;&lt;br /&gt;
* after an unclean stop, the last successfully published main generation is recovered;&lt;br /&gt;
* an unpersisted insert/update can disappear, and an unpersisted deletion can reappear;&lt;br /&gt;
* writes avoid WAL and synchronization latency.&lt;br /&gt;
&lt;br /&gt;
This write pattern is useful on SD cards and other flash media when the data is reconstructible or a documented loss window is acceptable. Instead of producing a continuously synchronized WAL stream, MemCP normally publishes one compressed main generation during the 15-minute rebuild cycle. Fewer, batched persistence events can reduce write amplification and flash wear. The rebuild itself still writes data, and its successful completion must be monitored; &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; is not a durability technique for irreplaceable records.&lt;br /&gt;
&lt;br /&gt;
The old documentation described data older than 15 minutes as guaranteed persistent. More precisely, 15 minutes is the normal &#039;&#039;&#039;rebuild schedule&#039;&#039;&#039;. A long-running, blocked, failed, or postponed rebuild can make the exposure window larger. Monitor rebuild completion and errors if the acceptable-loss window matters.&lt;br /&gt;
&lt;br /&gt;
This remains an extremely fast persistent-main-storage choice for replaceable data: high-volume usage statistics, sensor samples, import staging, or derived tables that can be reconstructed. It must not hold irreplaceable data merely because most rows already exist on disk.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;ENGINE=memory&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; keeps rows alive for the life of the MemCP process:&lt;br /&gt;
&lt;br /&gt;
* all row contents exist only in RAM;&lt;br /&gt;
* no WAL or persistent column files protect them;&lt;br /&gt;
* a normal shutdown, restart, process crash, kernel crash, or power loss empties the table;&lt;br /&gt;
* the table schema is retained;&lt;br /&gt;
* a closed &amp;lt;code&amp;gt;oninit&amp;lt;/code&amp;gt; callback stored with the schema can repopulate the empty generation when the application&#039;s idempotent table-creation guard runs after restart;&lt;br /&gt;
* the memory manager will not evict a memory-engine shard, because RAM is its only copy.&lt;br /&gt;
&lt;br /&gt;
Use it for session state, short-lived observer handles, and other process-lifetime data that must remain present while the process is running but can be recreated after restart. Its writes follow the RAM-only path, but its contents still count toward the memory budget and cannot be reclaimed safely.&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;code&amp;gt;ENGINE=cache&amp;lt;/code&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; is also RAM-only, but more disposable than &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* row contents have no WAL or persistent column files;&lt;br /&gt;
* schema/reconstructible definition and a closed &amp;lt;code&amp;gt;oninit&amp;lt;/code&amp;gt; callback can be retained;&lt;br /&gt;
* the table starts empty after restart and can be repopulated by its creation guard;&lt;br /&gt;
* under memory pressure, MemCP may evict the complete data generation while the server is still running;&lt;br /&gt;
* after eviction the schema remains usable and new rows may be written again;&lt;br /&gt;
* hidden optimizer/helper tables use this mode because their data can be rebuilt.&lt;br /&gt;
&lt;br /&gt;
Use it only when disappearance is part of the application&#039;s contract: result caches, derived lookup structures, observer state, and other data whose authoritative copy lives elsewhere. Code reading a cache table must tolerate an empty/rebuilt generation.&lt;br /&gt;
&lt;br /&gt;
== Transaction boundaries and batching ==&lt;br /&gt;
&lt;br /&gt;
Every SQL statement runs in an implicit transaction unless the session already has an explicit transaction. For &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; tables, synchronization happens at commit. Consequently:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-- Each statement commits separately and may require a durability fence.&lt;br /&gt;
INSERT INTO events (id, payload) VALUES (1, &#039;a&#039;);&lt;br /&gt;
INSERT INTO events (id, payload) VALUES (2, &#039;b&#039;);&lt;br /&gt;
&lt;br /&gt;
-- One explicit transaction amortizes commit work across both writes.&lt;br /&gt;
START TRANSACTION;&lt;br /&gt;
INSERT INTO events (id, payload) VALUES (3, &#039;c&#039;);&lt;br /&gt;
INSERT INTO events (id, payload) VALUES (4, &#039;d&#039;);&lt;br /&gt;
COMMIT;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Batch only as far as the application&#039;s atomicity, lock duration, conflict rate, and latency budget allow. There is no universal writes-per-second guarantee: transaction size, number of touched shards, WAL device, filesystem, backend acknowledgements, constraints, and concurrency determine the result.&lt;br /&gt;
&lt;br /&gt;
== Creating and inspecting tables ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
CREATE TABLE invoices (&lt;br /&gt;
    id BIGINT PRIMARY KEY,&lt;br /&gt;
    total DECIMAL(18,2)&lt;br /&gt;
) ENGINE=safe;&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE sensor_buffer (&lt;br /&gt;
    measured_at DATETIME,&lt;br /&gt;
    value DOUBLE&lt;br /&gt;
) ENGINE=sloppy;&lt;br /&gt;
&lt;br /&gt;
CREATE TABLE rendered_pages (&lt;br /&gt;
    cache_key VARCHAR(255),&lt;br /&gt;
    body TEXT&lt;br /&gt;
) ENGINE=cache;&lt;br /&gt;
&lt;br /&gt;
SHOW CREATE TABLE invoices;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose the mode table by table. A single application can keep invoices in &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;, replaceable telemetry in &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt;, sessions in &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;, and derived objects in &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; without weakening the durable tables.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;dangerous-engine-transitions&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Changing ENGINE safely ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Irreversible data-safety boundary:&#039;&#039;&#039; changing a persisted table (&amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt;) to &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; &#039;&#039;&#039;or &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt;&#039;&#039;&#039; deletes its on-disk column files and WAL immediately. The currently loaded rows remain in RAM, but there is no persistent copy and no undo after shutdown or eviction. Back up and verify the table first.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Transition !! What happens !! Required caution&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; || WAL and column files are removed; rows continue only in RAM || Irreversible; &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; rows may additionally be evicted while running&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; || WAL is closed and removed || Future delta changes are unsafe until rebuilt&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; → persisted || Current RAM rows are serialized to column files || Wait for successful completion before assuming durability&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; → &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; || A WAL is opened || Future writes get the new guarantee; retain backups of earlier state&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; ↔ &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; || Column layout and WAL stay; synchronization policy changes || Moving to &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; accepts power-loss risk immediately&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; ↔ &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; || Both remain RAM-only; cache-manager registration changes || Moving to cache permits live eviction&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
-- Make and verify a backup before this destructive transition:&lt;br /&gt;
ALTER TABLE historical_events ENGINE=memory;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
LRU cleanup is not a hidden ENGINE transition. For persistent engines it may release reloadable in-memory columns, but it must never delete their disk files. Physical removal is reserved for explicit &amp;lt;code&amp;gt;DROP TABLE&amp;lt;/code&amp;gt; and an explicit persisted-to-&amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; transition.&lt;br /&gt;
&lt;br /&gt;
== Failure scenarios in plain language ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Event !! &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; !! &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; !! &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; !! &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; !! &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| MemCP process crashes, OS remains alive || Recover WAL || Recover WAL already written to OS cache || Recover last rebuilt main generation || Rows lost || Rows lost&lt;br /&gt;
|-&lt;br /&gt;
| Kernel crash or sudden power loss || Recover committed WAL, subject to backend durability || Recent changes may be lost || Delta since last successful rebuild lost || Rows lost || Rows lost&lt;br /&gt;
|-&lt;br /&gt;
| Clean MemCP shutdown/restart || Rows retained || Rows retained || Shutdown rebuild normally persists current state || Schema retained, rows start empty || Schema/rebuilder retained, rows start empty&lt;br /&gt;
|-&lt;br /&gt;
| Memory pressure while running || Reloadable data may leave RAM; disk copy remains || Same || Persisted clean main data may be unloaded; dirty delta is protected || Rows are not evicted || Complete contents may be evicted&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Backups and operations ==&lt;br /&gt;
&lt;br /&gt;
Durability is not a backup. &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; protects committed writes against failures; it does not undo an accidental &amp;lt;code&amp;gt;DROP TABLE&amp;lt;/code&amp;gt;, a destructive ENGINE transition, an application-level deletion, corrupted credentials, or loss of the whole storage system. Maintain tested backups and restore procedures independently.&lt;br /&gt;
&lt;br /&gt;
For production operation, monitor:&lt;br /&gt;
&lt;br /&gt;
* rebuild start, completion, duration, and errors, especially for &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt;;&lt;br /&gt;
* WAL write/sync latency and storage-backend acknowledgements;&lt;br /&gt;
* dirty delta growth and long-running transactions;&lt;br /&gt;
* cache eviction, cold reload latency, and whether the hot set fits the memory budget;&lt;br /&gt;
* query latency together with shard distribution, CPU utilization, and memory bandwidth.&lt;br /&gt;
&lt;br /&gt;
See [[Memory Management and Eviction]], [[Storage Backends]], [[Hardware Requirements]], [[Performance Measurement]], [[Transactions and Isolation]], and [[Deployment]] for sizing, measurement, and operational guidance.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Performance_Measurement&amp;diff=397</id>
		<title>Performance Measurement</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Performance_Measurement&amp;diff=397"/>
		<updated>2026-08-28T10:14:02Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;performance-measurement&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Performance Measurement =&lt;br /&gt;
&lt;br /&gt;
Every published result must be reproducible and count successful work.&lt;br /&gt;
&lt;br /&gt;
Record MemCP commit/build flags, comparison-system version/configuration, schema, data generator and row count, query text, ENGINE mode, hardware, filesystem or remote backend, memory limits, concurrency, warm/cold state, and raw samples.&lt;br /&gt;
&lt;br /&gt;
Verify correctness before timing: HTTP status, error body, row count, values, and restart behavior. A fast 401 or other non-2xx response is not query throughput.&lt;br /&gt;
&lt;br /&gt;
== Current headline observations ==&lt;br /&gt;
&lt;br /&gt;
MemCP has reached &#039;&#039;&#039;speedups of 10× and more over MariaDB/PostgreSQL&#039;&#039;&#039; in measured OLAP and search-oriented workflows. The relevant mechanisms include compact RecSet domains, compressed column scans, batch execution, late materialization, adaptive physical structures and shard parallelism.&lt;br /&gt;
&lt;br /&gt;
Current isolated OLTP measurements show the opposite trade-off: those paths take about &#039;&#039;&#039;1.3–2.0× as long&#039;&#039;&#039; on MemCP. In complete WordPress- and wiki-style page builds, this has made &#039;&#039;&#039;no significant difference to overall page-loading time&#039;&#039;&#039; in the measured application workflows. The application, the number and mix of queries, and the share of time spent outside SQL determine the end-to-end effect. By contrast, one filtered-list workflow over roughly one million documents took around &#039;&#039;&#039;30 seconds on PostgreSQL&#039;&#039;&#039; and &#039;&#039;&#039;1.6 seconds on MemCP&#039;&#039;&#039; for the same query. That makes search, filtering, grouping and analytical reads the clearest current migration targets while OLTP/JIT work continues.&lt;br /&gt;
&lt;br /&gt;
These headline figures should be stated rather than hidden, but they do not replace the reproducibility record below. A benchmark publication must attach the exact competing versions, schema/query, dataset and distribution, hardware, durability settings, cache state, concurrency, result validation and raw samples. Do not combine the best result from one workload with the conditions of another.&lt;br /&gt;
&lt;br /&gt;
Write-path measurements have also reached about &#039;&#039;&#039;10× the throughput&#039;&#039;&#039; when changing the same table/workload from &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; to &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt;. Report that result together with the durability difference: &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; synchronizes WAL at commit, whereas &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; leaves recent WAL bytes in volatile operating-system buffers. A comparison that changes ENGINE without naming the changed failure guarantee is incomplete.&lt;br /&gt;
&lt;br /&gt;
Use calibrated SQL performance suites for end-to-end plans and Go benchmarks for isolated storage primitives. Run multiple samples, report distributions rather than the best run, and compare against current master under identical conditions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;make test&lt;br /&gt;
PERF_TEST=1 PERF_EXPLAIN=1 make test&lt;br /&gt;
go test ./storage/ -bench &#039;BenchmarkName&#039; -run &#039;^$&#039; -count=5&amp;lt;/pre&amp;gt;&lt;br /&gt;
For A/B changes, save raw output for both commits and use &amp;lt;code&amp;gt;benchstat&amp;lt;/code&amp;gt;. Profiles should distinguish compile time, physical preparation, execution, allocation, lock waits, storage reload, and background maintenance. Attach EXPLAIN and &amp;lt;code&amp;gt;EXPLAIN COMPILE&amp;lt;/code&amp;gt; for planner-sensitive results.&lt;br /&gt;
&lt;br /&gt;
== SQL performance regression framework ==&lt;br /&gt;
&lt;br /&gt;
Suites below &amp;lt;code&amp;gt;tests/performance/&amp;lt;/code&amp;gt; are disabled during ordinary correctness runs unless &amp;lt;code&amp;gt;PERF_TEST=1&amp;lt;/code&amp;gt; is set. The runner stores machine-specific row counts and timings in &amp;lt;code&amp;gt;.perf_baseline.json&amp;lt;/code&amp;gt;, performs warm-up work, repeats measured cases (five times by default), and reports the median. A result above the stored baseline plus tolerance fails the gate.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Run with existing baselines&lt;br /&gt;
PERF_TEST=1 make test&lt;br /&gt;
&lt;br /&gt;
# Recalibrate row counts/times for this machine&lt;br /&gt;
PERF_TEST=1 PERF_CALIBRATE=1 make test&lt;br /&gt;
&lt;br /&gt;
# Freeze row counts while bisecting a regression&lt;br /&gt;
PERF_TEST=1 PERF_NORECALIBRATE=1 make test&lt;br /&gt;
&lt;br /&gt;
# Include query-plan output&lt;br /&gt;
PERF_TEST=1 PERF_EXPLAIN=1 make test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Calibration aims for sufficiently long cases (currently roughly 10–20 seconds) and adjusts rows gradually. The runner also applies one protected pre-server wall-clock calibration for the execution architecture; a regression inside MemCP must not be allowed to enlarge its own time allowance.&lt;br /&gt;
&lt;br /&gt;
A performance line shows the measured duration, threshold, calibrated rows, per-row time, heap and CPU utilization, for example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Perf: COUNT (4.3s / 13s, 100,000,000 rows, 0.04µs/row, 25GB heap, 1522%/2400% CPU)&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Read all fields together: lower per-row time is meaningless if the query failed, row count changed unexpectedly, the process swapped, or a different plan/durability mode was used.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Variable !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PERF_TEST=1&amp;lt;/code&amp;gt; || Enable performance suites.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PERF_CALIBRATE=1&amp;lt;/code&amp;gt; || Reset/update the local performance baseline.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PERF_NORECALIBRATE=1&amp;lt;/code&amp;gt; || Keep row counts fixed for commit-to-commit or bisect comparisons.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PERF_EXPLAIN=1&amp;lt;/code&amp;gt; || Print plans for performance cases.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;PERF_REPEAT=N&amp;lt;/code&amp;gt; || Change the number of measured repetitions; default is five.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Do not commit a baseline produced while the machine was thermally throttled, heavily loaded, swapping, or using a different build configuration. Preserve the known-good baseline before a bisect.&lt;br /&gt;
&lt;br /&gt;
For a regression bisect, calibrate on the known-good commit, keep a copy of its baseline, and freeze row counts while Git tests candidate commits:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git checkout GOOD_COMMIT&lt;br /&gt;
PERF_TEST=1 PERF_CALIBRATE=1 make test  # repeat until stable&lt;br /&gt;
cp .perf_baseline.json /tmp/memcp-perf-good.json&lt;br /&gt;
&lt;br /&gt;
git bisect start HEAD GOOD_COMMIT&lt;br /&gt;
cp /tmp/memcp-perf-good.json .perf_baseline.json&lt;br /&gt;
git bisect run bash -c &#039;PERF_TEST=1 PERF_NORECALIBRATE=1 make test&#039;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Storage microbenchmarks and profiles ==&lt;br /&gt;
&lt;br /&gt;
For a storage encoding or hot loop, benchmark the smallest relevant package and compare several samples:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
go test ./storage/ -bench &#039;BenchmarkEnumPerElem&#039; -run &#039;^$&#039; -count=5 &amp;gt; /tmp/before.txt&lt;br /&gt;
# apply/build the candidate under the same conditions&lt;br /&gt;
go test ./storage/ -bench &#039;BenchmarkEnumPerElem&#039; -run &#039;^$&#039; -count=5 &amp;gt; /tmp/after.txt&lt;br /&gt;
benchstat /tmp/before.txt /tmp/after.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Microbenchmarks establish mechanism, not end-to-end query benefit. Confirm the change with SQL, result validation, representative cardinalities, and warm/cold conditions. Use CPU, memory/allocation, mutex/block, and I/O profiles to explain a difference instead of attributing every gain to the edited function.&lt;br /&gt;
&lt;br /&gt;
== Coverage is not performance ==&lt;br /&gt;
&lt;br /&gt;
Coverage builds are useful for finding untested paths but add instrumentation and must not supply release benchmark numbers. Build and collect coverage separately with &amp;lt;code&amp;gt;MEMCP_COVERAGE=1&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MEMCP_COVERDIR&amp;lt;/code&amp;gt; when the goal is test quality.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=MySQL_is_too_slow&amp;diff=396</id>
		<title>MySQL is too slow</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=MySQL_is_too_slow&amp;diff=396"/>
		<updated>2026-08-28T10:14:01Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= MySQL is too slow? Evaluate MemCP Database =&lt;br /&gt;
&lt;br /&gt;
If slow SQL queries are holding back an application, evaluate &#039;&#039;&#039;MemCP Database&#039;&#039;&#039; before accepting ever larger MySQL servers, more caches, or a separate OLAP copy as the only options. MemCP is an open-source, MySQL-protocol-compatible, compressed columnar database built for querying operational data in memory.&lt;br /&gt;
&lt;br /&gt;
MemCP aims to be a fast, compact alternative for MySQL-style applications whose bottleneck is scanning, joining, grouping, sorting or aggregating operational data. It combines compressed column storage, late materialization, adaptive indexes, parallel shards and a Scheme-based query compiler.&lt;br /&gt;
&lt;br /&gt;
That performance ambition is part of the product, even while MemCP remains Beta. It does not mean every current query beats mature MySQL: point workloads, connector behavior and application suites such as WordPress can still lose when a plan stays interpreted, misses a JIT fast path, compiles too much work or exercises an unsupported optimization. Those results identify roadmap work rather than changing MemCP&#039;s design goal.&lt;br /&gt;
&lt;br /&gt;
== Observed performance profile ==&lt;br /&gt;
&lt;br /&gt;
Project measurements have shown two deliberately different sides of the current system:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Workload !! Observed result !! Interpretation&lt;br /&gt;
|-&lt;br /&gt;
| OLAP, aggregation, and search-oriented workflows || &#039;&#039;&#039;Speedups of 10× and more&#039;&#039;&#039; over MariaDB/PostgreSQL in measured cases || RecSets, compressed column scans, batching, late materialization, and parallel execution match the workload&lt;br /&gt;
|-&lt;br /&gt;
| Conventional OLTP application paths || Currently about &#039;&#039;&#039;1.3–2.0× the elapsed time&#039;&#039;&#039; in measured cases || Broader JIT coverage, compile cost, point paths, and connector compatibility remain optimization work&lt;br /&gt;
|-&lt;br /&gt;
| Complete WordPress- and wiki-style page builds || &#039;&#039;&#039;No significant difference in overall page-loading time&#039;&#039;&#039; in the measured application workflows || End-to-end impact depends on application work and on the number and mix of SQL queries&lt;br /&gt;
|-&lt;br /&gt;
| Filtered list over roughly one million documents || Around &#039;&#039;&#039;30 seconds on PostgreSQL&#039;&#039;&#039; versus &#039;&#039;&#039;1.6 seconds on MemCP&#039;&#039;&#039; for the same query || The search/list path is the urgent migration candidate even if the smaller OLTP path is not yet faster&lt;br /&gt;
|-&lt;br /&gt;
| Write-heavy tables using &amp;lt;code&amp;gt;ENGINE=logged&amp;lt;/code&amp;gt; || About &#039;&#039;&#039;10× the write throughput&#039;&#039;&#039; of &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; in project measurements || Avoids commit-time &amp;lt;code&amp;gt;fsync&amp;lt;/code&amp;gt;, but recent committed writes can be lost on kernel crash or power failure&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The practical conclusion is not that every statement must move at once. Move the workflows where physical design dominates: filtered lists, search, aggregation, dashboards, and mixed operational analytics. Keep or shadow OLTP paths until their compatibility and latency are acceptable, then expand the migration as JIT and point-query execution improve.&lt;br /&gt;
&lt;br /&gt;
These figures describe observed application and benchmark cases, not portable guarantees. The detailed record should name versions, queries, data distribution, hardware, durability, concurrency, cache state, successful response counts, and raw samples as required by [[Performance Measurement]].&lt;br /&gt;
&lt;br /&gt;
Durability is part of the comparison. &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; retains a WAL and survives a MemCP process crash, but it does not promise power-loss durability. For replaceable, flash-backed data, &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; avoids a continuous WAL and normally publishes compressed storage every 15 minutes, reducing SD-card write pressure at the cost of losing the unrebuilt delta after an unclean stop. See [[Persistency and Performance Guarantees]].&lt;br /&gt;
&lt;br /&gt;
== When MemCP can help ==&lt;br /&gt;
&lt;br /&gt;
* dashboards repeatedly aggregate fresh transactional data;&lt;br /&gt;
* wide tables are queried through a small subset of columns;&lt;br /&gt;
* repeated categories, ranges or sequences compress well;&lt;br /&gt;
* analytical scans should run beside writes without maintaining a separate OLAP copy;&lt;br /&gt;
* SQL over HTTP or an embedded endpoint can remove an application/database network hop;&lt;br /&gt;
* reconstructible caches and durable business tables need different persistence trade-offs.&lt;br /&gt;
&lt;br /&gt;
== Common SQL performance problems ==&lt;br /&gt;
&lt;br /&gt;
These are the symptoms users usually see before they search for another database. Each one should be tested as a complete query and application workflow, not reduced to an isolated operator.&lt;br /&gt;
&lt;br /&gt;
=== MySQL query slow on a large table ===&lt;br /&gt;
&lt;br /&gt;
A query that was fast with thousands of rows may cross a threshold at millions of rows: a scan touches too many row pages, an index returns too many candidates, or fetching wide rows dominates after lookup. Adding another index can help one predicate but cannot turn a wide row store into a compact column scan.&lt;br /&gt;
&lt;br /&gt;
MemCP reads only referenced columns, keeps suitable values compressed and selects a scan/index/RecSet path from cardinality and reuse costs. This is especially relevant when a page needs a few output columns from a wide document or event table.&lt;br /&gt;
&lt;br /&gt;
=== PostgreSQL WHERE plus ORDER BY LIMIT is slow ===&lt;br /&gt;
&lt;br /&gt;
The difficult shape is not a plain LIMIT. It combines selective or correlated filters with an order that favors another access path:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT id, title, changed_at&lt;br /&gt;
FROM documents&lt;br /&gt;
WHERE tenant_id = ?&lt;br /&gt;
  AND state IN (&#039;open&#039;, &#039;review&#039;)&lt;br /&gt;
  AND EXISTS (SELECT 1 FROM permissions p&lt;br /&gt;
              WHERE p.document_id = documents.id&lt;br /&gt;
                AND p.user_id = ?)&lt;br /&gt;
ORDER BY changed_at DESC&lt;br /&gt;
LIMIT 100;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A conventional optimizer may walk the ordering index and reject rows until it finds 100 matches, or materialize/filter a large intermediate result before sorting. MemCP can represent the permission/filter domain as a RecSet, intersect it with other boundaries, read ordered candidates in batches and stop when enough accepted rows have been emitted. See [[RecSets]], [[Scan]], and [[Advanced SQL Tutorial]].&lt;br /&gt;
&lt;br /&gt;
=== GROUP BY, COUNT DISTINCT or dashboard query is slow ===&lt;br /&gt;
&lt;br /&gt;
Repeated dashboards often aggregate a small number of columns across a large, recently updated relation. MemCP can scan compressed values in batches, compute shard-local partial aggregates, and cost reusable group caches or computed columns. The application continues to query current operational data instead of waiting for an ETL copy merely to answer a dashboard.&lt;br /&gt;
&lt;br /&gt;
=== Search and filtered lists become slower as documents grow ===&lt;br /&gt;
&lt;br /&gt;
Faceted lists combine permissions, tags, states, text/prefix filters, joins, counts, sorting and pagination. Their cost can grow with the candidate domain even though the user sees only 20 or 100 rows. This is the workflow in which project measurements have produced speedups of 10× and more over MariaDB/PostgreSQL. In one concrete list over roughly one million documents, the same query took around 30 seconds on PostgreSQL and 1.6 seconds on MemCP.&lt;br /&gt;
&lt;br /&gt;
RecSets are designed to carry compact membership between those operators without copying wide result rows. Ordered batch acceptance and late materialization then avoid doing full output work for every candidate.&lt;br /&gt;
&lt;br /&gt;
=== MySQL INSERT or UPDATE becomes slow because of fsync ===&lt;br /&gt;
&lt;br /&gt;
If durable commit latency is the bottleneck, first batch statements within the application&#039;s atomicity budget. Where process-crash recovery is sufficient and power-loss risk is externally accepted, &amp;lt;code&amp;gt;ENGINE=logged&amp;lt;/code&amp;gt; removes commit-time WAL synchronization and has reached about 10× &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; write throughput in project measurements.&lt;br /&gt;
&lt;br /&gt;
This is a durability choice, not a harmless tuning flag. Keep irreplaceable data on &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;; see [[Persistency and Performance Guarantees]].&lt;br /&gt;
&lt;br /&gt;
=== Database writes are wearing out a Raspberry Pi SD card ===&lt;br /&gt;
&lt;br /&gt;
For reconstructible telemetry, caches, imports or derived state, &amp;lt;code&amp;gt;ENGINE=sloppy&amp;lt;/code&amp;gt; avoids continuous WAL traffic and normally publishes a compressed generation during the 15-minute rebuild cycle. This batches flash writes and makes the possible loss of the unrebuilt delta explicit. Durable business records still belong on &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; and appropriate storage media.&lt;br /&gt;
&lt;br /&gt;
== Why it can be fast ==&lt;br /&gt;
&lt;br /&gt;
MemCP reduces bytes moved through the cache hierarchy, reads columns in batches, delays row materialization, executes independent shards in parallel and can fuse filter, projection and aggregation. The planner decorrelates supported subqueries before choosing direct scans, adaptive indexes, RecSets, group caches, computed columns or ordered top-k paths. Supported Scheme hot paths can be compiled by the x86-64 JIT.&lt;br /&gt;
&lt;br /&gt;
This architecture attacks common SQL-performance costs directly:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! SQL performance problem !! MemCP approach&lt;br /&gt;
|-&lt;br /&gt;
| Large scans move whole rows || Read only referenced compressed columns in batches&lt;br /&gt;
|-&lt;br /&gt;
| Repeated GROUP BY or correlated lookups || Cost reusable group caches, computed columns, indexes, or RecSets&lt;br /&gt;
|-&lt;br /&gt;
| ORDER BY builds a large temporary result before LIMIT || Use ordered scans, late materialization, top-k selection, and braking where semantics permit&lt;br /&gt;
|-&lt;br /&gt;
| Application-to-database round trips dominate || Use the MySQL protocol, SQL over HTTP, or a narrowly scoped in-database endpoint&lt;br /&gt;
|-&lt;br /&gt;
| One row-store must serve transactions and analytics || Keep recent writes in delta storage while scanning compressed main columns&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Try the slow query on MemCP ==&lt;br /&gt;
&lt;br /&gt;
Start an isolated instance with persistent storage:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;docker volume create memcp_eval_data&lt;br /&gt;
docker run -d --name memcp-eval \&lt;br /&gt;
  -e ROOT_PASSWORD=&#039;choose-a-password&#039; \&lt;br /&gt;
  -v memcp_eval_data:/data \&lt;br /&gt;
  -p 127.0.0.1:4321:4321 -p 127.0.0.1:3307:3307 \&lt;br /&gt;
  carli2/memcp:latest&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then import a copy of the relevant schema and data, run the real query through the same client path, and inspect its physical plan:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;EXPLAIN PHYSICAL&lt;br /&gt;
SELECT ...;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not stop at a synthetic &amp;lt;code&amp;gt;SELECT 1&amp;lt;/code&amp;gt;. Test the query that users actually wait for, with representative cardinalities, concurrency, authentication, durability and cold/warm states. [[Migration from MySQL and PostgreSQL]] describes a staged evaluation; [[Advanced SQL Tutorial]] explains the optimizations visible in the plan.&lt;br /&gt;
&lt;br /&gt;
== Evaluate honestly ==&lt;br /&gt;
&lt;br /&gt;
Import a copy, validate results, restart and recovery, then benchmark the real authenticated workload against the same data and durability requirement. Record plans and compilation time as well as execution time. A current loss caused by missing JIT coverage, planner choice or compatibility work should be published with that diagnosis, not hidden and not generalized into a claim that MemCP cannot become faster for the workload.&lt;br /&gt;
&lt;br /&gt;
The outcome should be actionable: if MemCP returns the same results, satisfies the required durability and operations gates, and improves the real workload, migrate that workload instead of continuing to tune around the limitations of an unsuitable physical design. Keep MySQL available as the source of truth or rollback path until those gates have been demonstrated.&lt;br /&gt;
&lt;br /&gt;
== Frequently asked questions ==&lt;br /&gt;
&lt;br /&gt;
=== Is MemCP a drop-in replacement for MySQL? ===&lt;br /&gt;
&lt;br /&gt;
MemCP speaks the MySQL client protocol and implements a broad, tested SQL subset, but it is not a byte-for-byte implementation of every MySQL feature. Verify all application-critical queries, metadata calls, transactions, constraints and connector behavior. See [[Supported SQL]] and [[Database Tools compatibility with MemCP]].&lt;br /&gt;
&lt;br /&gt;
=== Is MemCP an MCP server for AI assistants? ===&lt;br /&gt;
&lt;br /&gt;
No. MemCP Database is a relational SQL database. It is unrelated to Model Context Protocol memory servers that happen to use a similar name.&lt;br /&gt;
&lt;br /&gt;
=== Is MemCP related to memcpy()? ===&lt;br /&gt;
&lt;br /&gt;
No. &amp;lt;code&amp;gt;memcpy()&amp;lt;/code&amp;gt; is a C/C++ library function for copying memory. MemCP Database is a server and storage engine queried with SQL, HTTP, RDF or embedded Scheme interfaces.&lt;br /&gt;
&lt;br /&gt;
Start with [[Comparison: MemCP vs. MySQL]], [[Migration from MySQL and PostgreSQL]], [[Advanced SQL Tutorial]], [[Performance Measurement]] and [[Current Status and Open Issues]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Migration_from_MySQL_and_PostgreSQL&amp;diff=395</id>
		<title>Migration from MySQL and PostgreSQL</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Migration_from_MySQL_and_PostgreSQL&amp;diff=395"/>
		<updated>2026-08-28T10:14:01Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;migration-from-mysql-and-postgresql&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Migration from MySQL and PostgreSQL =&lt;br /&gt;
&lt;br /&gt;
Migration is a compatibility and operations project, not only a data copy. MemCP can import through live MySQL/PostgreSQL connections or supported dump formats, while applications connect through the MySQL protocol or the HTTP SQL endpoints. It does not expose a PostgreSQL wire-protocol server and does not claim complete syntax, metadata, type, or administration compatibility with either source system.&lt;br /&gt;
&lt;br /&gt;
Keep the source database authoritative until schema translation, row counts, constraints, representative queries, writes, timezone behavior, and restart recovery have been validated. Measure import duration and application latency with successful results, retain a rollback path, and separately design ongoing change capture when the source continues receiving writes during a staged migration.&lt;br /&gt;
&lt;br /&gt;
[[File:Ports.svg|thumb|none|640px|MemCP client and import connection paths]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;live-import&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Live import ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;; MySQL: host/port nil use 127.0.0.1:3306&lt;br /&gt;
(mysql_import nil nil &amp;quot;import_user&amp;quot; &amp;quot;secret&amp;quot; &amp;quot;source_db&amp;quot; &amp;quot;target_db&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
; PostgreSQL: database, source schema, target database&lt;br /&gt;
(psql_import nil nil &amp;quot;postgres&amp;quot; &amp;quot;secret&amp;quot; &amp;quot;source_db&amp;quot; &amp;quot;public&amp;quot; &amp;quot;target_db&amp;quot;)&amp;lt;/pre&amp;gt;&lt;br /&gt;
Optional trailing arguments select or rename individual tables. Use a least-privilege read-only source account and protect credentials from shell and process listings.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;dumps&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Dumps ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;load_sql&amp;lt;/code&amp;gt; reads MySQL SQL; &amp;lt;code&amp;gt;load_psql&amp;lt;/code&amp;gt; reads PostgreSQL SQL and supported pg_dump/archive inputs. A compressed input must be decompressed (&amp;lt;code&amp;gt;zcat&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;xzcat&amp;lt;/code&amp;gt;), not passed through the &amp;lt;code&amp;gt;gzip&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;xz&amp;lt;/code&amp;gt; compression functions.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;gzip -dk dump.sql.gz&lt;br /&gt;
# Then in the MemCP console:&lt;br /&gt;
# (load_sql &amp;quot;target_db&amp;quot; (stream &amp;quot;dump.sql&amp;quot;))&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For large or live migrations, prefer the importer functions above rather than assuming every vendor-specific dump statement is accepted.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;application-connection&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Application connection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;$db = new PDO(&lt;br /&gt;
    &#039;mysql:host=127.0.0.1;port=3307;dbname=target_db&#039;,&lt;br /&gt;
    &#039;root&#039;,&lt;br /&gt;
    &#039;strong-password&#039;&lt;br /&gt;
);&lt;br /&gt;
echo $db-&amp;gt;query(&amp;quot;SELECT &#039;it works&#039;&amp;quot;)-&amp;gt;fetchColumn();&amp;lt;/pre&amp;gt;&lt;br /&gt;
PostgreSQL SQL syntax is available over &amp;lt;code&amp;gt;/psql/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt;; MemCP does not expose a PostgreSQL wire-protocol port.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;validation-checklist&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Validation checklist ==&lt;br /&gt;
&lt;br /&gt;
* compare schemas, types, defaults, indexes, constraints, triggers, and views;&lt;br /&gt;
* compare counts and checksums per table;&lt;br /&gt;
* replay representative reads and writes against both systems;&lt;br /&gt;
* verify AUTO_INCREMENT and timezone behavior;&lt;br /&gt;
* restart MemCP and repeat checks;&lt;br /&gt;
* measure import duration, query latency, errors, and CDC lag if live replication is used;&lt;br /&gt;
* retain a tested rollback path until cutover gates pass.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=MemCP_for_Microservices&amp;diff=394</id>
		<title>MemCP for Microservices</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=MemCP_for_Microservices&amp;diff=394"/>
		<updated>2026-08-28T10:14:01Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= MemCP for Microservices =&lt;br /&gt;
&lt;br /&gt;
MemCP can combine database storage, SQL-over-HTTP, and custom Scheme handlers in one process. This removes an application-to-database network hop and can simplify small services, but it is an architectural option rather than a latency guarantee.&lt;br /&gt;
&lt;br /&gt;
== Deployment patterns ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Pattern !! Benefit !! Trade-off&lt;br /&gt;
|-&lt;br /&gt;
| Ordinary service plus MySQL protocol || Familiar drivers, connection pools, and separation of concerns || Network/serialization hop remains&lt;br /&gt;
|-&lt;br /&gt;
| Service plus SQL over HTTP || Minimal client dependency and streamable JSONL || General SQL endpoint needs strict network and grant controls&lt;br /&gt;
|-&lt;br /&gt;
| Embedded Scheme handler || Prepared plans and storage access in one process; custom JSON or WebSocket API || Application failure and database failure share a process and deployment lifecycle&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Good candidates include small internal APIs, real-time dashboards, local/edge services, event lookup, and low-latency state whose data model remains relational. A large product with independent teams, many language-specific libraries, complex application logic, or strict process-isolation requirements may be easier to operate with a conventional separate service.&lt;br /&gt;
&lt;br /&gt;
== Preparing work outside the request path ==&lt;br /&gt;
&lt;br /&gt;
The repository&#039;s &amp;lt;code&amp;gt;apps/keyvalue.scm&amp;lt;/code&amp;gt; example creates a table and parses fixed SELECT/upsert statements once during startup. Each request creates a session, binds the key/value, and evaluates the prepared formula. That avoids parsing and planning the same statement on every request while keeping caller values separate from SQL text.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(set item_get (parse_sql &amp;quot;keyvalue&amp;quot;&lt;br /&gt;
	&amp;quot;SELECT value FROM kv WHERE key = @key&amp;quot;))&lt;br /&gt;
(set item_set (parse_sql &amp;quot;keyvalue&amp;quot;&lt;br /&gt;
	&amp;quot;INSERT INTO kv(key, value) VALUES (@key, @value)&lt;br /&gt;
	 ON DUPLICATE KEY UPDATE value = @value&amp;quot;))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The complete example installs a request handler and starts its own HTTP listener:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(createdatabase &amp;quot;keyvalue&amp;quot; true)&lt;br /&gt;
(eval (parse_sql &amp;quot;keyvalue&amp;quot;&lt;br /&gt;
	&amp;quot;CREATE TABLE IF NOT EXISTS kv(key TEXT, value TEXT, UNIQUE KEY PRIMARY(key))&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
(set item_get (parse_sql &amp;quot;keyvalue&amp;quot; &amp;quot;SELECT value FROM kv WHERE key = @key&amp;quot;))&lt;br /&gt;
(set item_set (parse_sql &amp;quot;keyvalue&amp;quot;&lt;br /&gt;
	&amp;quot;INSERT INTO kv(key,value) VALUES (@key,@value)&lt;br /&gt;
	 ON DUPLICATE KEY UPDATE value=@value&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
(define http_handler (lambda (req res) (begin&lt;br /&gt;
	(set session (newsession))&lt;br /&gt;
	(session &amp;quot;key&amp;quot; (req &amp;quot;path&amp;quot;))&lt;br /&gt;
	(if (equal? (req &amp;quot;method&amp;quot;) &amp;quot;GET&amp;quot;)&lt;br /&gt;
		(begin&lt;br /&gt;
			(set resultrow (lambda (row) ((res &amp;quot;print&amp;quot;) (row &amp;quot;value&amp;quot;))))&lt;br /&gt;
			(eval item_get))&lt;br /&gt;
		(begin&lt;br /&gt;
			(session &amp;quot;value&amp;quot; ((req &amp;quot;body&amp;quot;)))&lt;br /&gt;
			(eval item_set)&lt;br /&gt;
			((res &amp;quot;print&amp;quot;) &amp;quot;ok&amp;quot;))))))&lt;br /&gt;
&lt;br /&gt;
(serve 1266 (lambda (req res) (http_handler req res)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run the maintained repository version with &amp;lt;code&amp;gt;./memcp apps/keyvalue.scm&amp;lt;/code&amp;gt;, store a value using &amp;lt;code&amp;gt;curl --data-binary value http://localhost:1266/key&amp;lt;/code&amp;gt;, and retrieve it with &amp;lt;code&amp;gt;curl http://localhost:1266/key&amp;lt;/code&amp;gt;. This demonstration intentionally omits production authentication and limits; do not expose it unchanged.&lt;br /&gt;
&lt;br /&gt;
Use SQL constraints and one-statement atomic patterns even inside an embedded handler. In-process access removes transport overhead; it does not remove concurrent requests, transaction conflicts, authorization, or durability decisions.&lt;br /&gt;
&lt;br /&gt;
== Historical HTTP microbenchmark ==&lt;br /&gt;
&lt;br /&gt;
An early AMD Ryzen 9 7900X3D run used ApacheBench against a tiny embedded endpoint with concurrency 10. It reported 1,000,000 completed requests, zero failures, 42.083 seconds, 23,762.78 requests/s, 0.421 ms mean request latency (0.042 ms across concurrent requests), p95 1 ms and maximum 2 ms. The author also observed that &amp;lt;code&amp;gt;ab&amp;lt;/code&amp;gt; saturated one client core while MemCP used roughly 20% across other cores.&lt;br /&gt;
&lt;br /&gt;
The original record does not include the exact command, commit, response validation beyond ApacheBench&#039;s failure count, server build or repeat runs. It demonstrates that the embedded path can be very small, but it is not a database-query or current-release throughput guarantee. A new comparison must include the handler code, successful body validation, client/server CPU profiles and several raw samples.&lt;br /&gt;
&lt;br /&gt;
== Production checklist ==&lt;br /&gt;
&lt;br /&gt;
Choose each table ENGINE according to data-loss tolerance, configure total and persistent RAM budgets, and provide health checks, backups, monitoring, and restart validation. Set a strong root password before exposing either the HTTP or MySQL port. Persistent data should use &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; unless the documented risks of another engine are explicitly acceptable.&lt;br /&gt;
&lt;br /&gt;
Handler latency depends on query shape, compilation and plan-cache state, concurrency, memory pressure, and storage reloads. Benchmark the full authenticated request path with successful-response validation instead of quoting a fixed sub-millisecond figure.&lt;br /&gt;
&lt;br /&gt;
Run embedded services under a supervisor, use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt;, implement external liveness/readiness checks, limit bodies and queues, propagate cancellation, and test restart/restore. Scaling the process horizontally requires an explicit ownership, replication, or routing design; the current local shard engine is not an automatic multi-node database.&lt;br /&gt;
&lt;br /&gt;
See [[In-Database WebApps and REST Services]], [[Persistency and Performance Guarantees]], [[Memory Management and Eviction]], [[Security and Authentication]], and [[Performance Measurement]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=MemCP_Console&amp;diff=393</id>
		<title>MemCP Console</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=MemCP_Console&amp;diff=393"/>
		<updated>2026-08-28T10:14:00Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= MemCP Console =&lt;br /&gt;
&lt;br /&gt;
The interactive Scheme console is enabled when MemCP starts without &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./memcp lib/main.scm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Run an expression non-interactively with:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./memcp -c &#039;(help)&#039; lib/main.scm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Background and service deployments must use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt;; otherwise closing standard input ends the REPL and may stop the process. Capture stdout/stderr through the service manager and use the dashboard, processlist, and configured logs for operations.&lt;br /&gt;
&lt;br /&gt;
Authorized MySQL sessions may expose an administrative Scheme parser mode when that capability is intentionally enabled. Scheme execution has direct process and storage access and must not be offered to untrusted database users. See [[Introduction to Scheme]], [[Security and Authentication]], and [[Dashboard and Operations]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Lists_and_Objects&amp;diff=392</id>
		<title>Lists and Objects</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Lists_and_Objects&amp;diff=392"/>
		<updated>2026-08-28T10:14:00Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Lists and Objects =&lt;br /&gt;
&lt;br /&gt;
Lists are central to MemCP&#039;s Scheme dialect: they represent ordinary collections, associative objects and executable code. This tutorial explains the programming model; [[Lists]] and [[Associative Lists / Dictionaries]] provide the generated function reference.&lt;br /&gt;
&lt;br /&gt;
== List values ==&lt;br /&gt;
&lt;br /&gt;
A quoted list is data. Mapping and filtering return new lists; reduction combines them into one value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&#039;(1 2 3)&lt;br /&gt;
(cons 0 &#039;(1 2 3))                         /* (0 1 2 3) */&lt;br /&gt;
(append &#039;(1 2 3) 4 5)                     /* (1 2 3 4 5) */&lt;br /&gt;
(has? &#039;(1 2 3) 2)                         /* true */&lt;br /&gt;
(filter &#039;(1 2 3) (lambda (x) (&amp;lt; x 3)))    /* (1 2) */&lt;br /&gt;
(map &#039;(1 2 3) (lambda (x) (* x 2)))       /* (2 4 6) */&lt;br /&gt;
(reduce &#039;(1 2 3) + 0)                     /* 6 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Choose a correct neutral value and an associative reducer when work may run in parallel. Order-sensitive string concatenation, floating-point sums and callbacks with I/O require particular care.&lt;br /&gt;
&lt;br /&gt;
== Associative lists as objects ==&lt;br /&gt;
&lt;br /&gt;
An object is a flat list of alternating keys and values. Calling it with a key performs lookup. Updates are functional: &amp;lt;code&amp;gt;set_assoc&amp;lt;/code&amp;gt; returns a new value instead of mutating the old list.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(set obj &#039;(&amp;quot;a&amp;quot; 1 &amp;quot;b&amp;quot; 2 &amp;quot;c&amp;quot; 3))&lt;br /&gt;
(obj &amp;quot;a&amp;quot;)&lt;br /&gt;
(set obj (set_assoc obj &amp;quot;a&amp;quot; 5))&lt;br /&gt;
(filter_assoc obj (lambda (key value) (not (equal? key &amp;quot;c&amp;quot;))))&lt;br /&gt;
(map_assoc obj (lambda (key value) (* value 2)))&lt;br /&gt;
(reduce_assoc obj (lambda (acc key value) (+ acc value)) 0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;has_assoc?&amp;lt;/code&amp;gt; when absence differs from a stored &amp;lt;code&amp;gt;nil&amp;lt;/code&amp;gt;. Request objects, JSON objects, SQL result rows and sessions may expose a similar callable lookup style, but they are not necessarily represented by the same physical type.&lt;br /&gt;
&lt;br /&gt;
== Lists as generated code ==&lt;br /&gt;
&lt;br /&gt;
Scheme code is list-shaped data. Quoting controls which computation happens while building a program and which is delayed until &amp;lt;code&amp;gt;eval&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(set program &#039;(&#039;print &amp;quot;Hello World&amp;quot;))&lt;br /&gt;
(eval program)&lt;br /&gt;
(set add_expression &#039;(&#039;+ 4 5))&lt;br /&gt;
(eval add_expression)                       /* 9 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Symbols naming delayed procedures remain quoted. Values that must be computed while building the outer expression are embedded without an extra quote. Generated lambdas need a quoted &amp;lt;code&amp;gt;lambda&amp;lt;/code&amp;gt; symbol, a parameter list and exactly one body; use &amp;lt;code&amp;gt;begin&amp;lt;/code&amp;gt; for several forms.&lt;br /&gt;
&lt;br /&gt;
The optimizer may fuse safe list operations or JIT-compile supported hot procedures, but observable functional semantics remain unchanged. See [[Introduction to Scheme]], [[JIT Compilation]] and [[Parallel Computing]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Introduction_to_Scheme&amp;diff=391</id>
		<title>Introduction to Scheme</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Introduction_to_Scheme&amp;diff=391"/>
		<updated>2026-08-28T10:13:59Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Introduction to Scheme =&lt;br /&gt;
&lt;br /&gt;
MemCP embeds a small Scheme dialect used by the SQL parsers, query planner, modules, and application endpoints. Start the interactive console with &amp;lt;code&amp;gt;./memcp lib/main.scm&amp;lt;/code&amp;gt;; background services use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Scheme represents calls and code with the same list syntax. That makes the dialect well suited to MemCP&#039;s query compiler: the SQL planner constructs Scheme programs as data, optimizes them, and evaluates or compiles them.&lt;br /&gt;
&lt;br /&gt;
The console prints each expression result, which makes the evaluation model easy to explore:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;amp;gt; 12&lt;br /&gt;
= 12&lt;br /&gt;
&amp;amp;gt; (+ 1 2 3)&lt;br /&gt;
= 6&lt;br /&gt;
&amp;amp;gt; (+ 2 (* 2 4))&lt;br /&gt;
= 10&lt;br /&gt;
&amp;amp;gt; (concat &amp;quot;Hello &amp;quot; &amp;quot;World&amp;quot;)&lt;br /&gt;
= &amp;quot;Hello World&amp;quot;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Startup also loads the configured data directory and Scheme modules before opening the SQL/HTTP listeners. The exact banner and number of startup tests change between releases, so scripts should not parse that text.&lt;br /&gt;
&lt;br /&gt;
== Values and calls ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(+ 1 2)&lt;br /&gt;
(concat &amp;quot;hello &amp;quot; &amp;quot;world&amp;quot;)&lt;br /&gt;
(map &#039;(1 2 3) (lambda (x) (* x x)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Numbers, booleans, strings, symbols, lists, functions, sessions, and storage objects are ordinary values. A list in expression position is a call: its first item is the procedure and the rest are arguments. Whitespace separates forms; parentheses define nesting.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Form !! Meaning&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;42&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;3.5&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;true&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;&amp;quot;text&amp;quot;&amp;lt;/code&amp;gt; || Literal values&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;(+ 1 2)&amp;lt;/code&amp;gt; || Call &amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; with two arguments&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&#039;name&amp;lt;/code&amp;gt; || The symbol &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, not the value bound to it&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&#039;(1 2 3)&amp;lt;/code&amp;gt; || Construct a list value instead of calling &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;&#039;(&amp;quot;name&amp;quot; &amp;quot;Ada&amp;quot; &amp;quot;active&amp;quot; true)&amp;lt;/code&amp;gt; || Flat key/value list used as an associative object&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Quoting and generated code ==&lt;br /&gt;
&lt;br /&gt;
Use quoting to build code or data: &amp;lt;code&amp;gt;&#039;(+ 4 5)&amp;lt;/code&amp;gt; constructs delayed code, while &amp;lt;code&amp;gt;(eval &#039;(+ 4 5))&amp;lt;/code&amp;gt; evaluates it. Values that should be computed now can be embedded into a quoted outer form; procedure symbols whose execution is delayed remain quoted. This distinction matters throughout the query planner.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(set delayed &#039;(+ 4 5))&lt;br /&gt;
(eval delayed)                 /* 9 */&lt;br /&gt;
(map &#039;(1 2 3) (lambda (x) (* x x)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not add or remove parentheses by visual guesswork in large generated expressions. Repository Scheme files are formatted and checked with &amp;lt;code&amp;gt;python3 tools/lint_scm.py&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Functions and scope ==&lt;br /&gt;
&lt;br /&gt;
Lambdas have exactly a parameter list and one body. Use &amp;lt;code&amp;gt;begin&amp;lt;/code&amp;gt; when that body needs several forms:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(define greet (lambda (name) (begin&lt;br /&gt;
	(print &amp;quot;greeting &amp;quot; name)&lt;br /&gt;
	(concat &amp;quot;Hello, &amp;quot; name))))&lt;br /&gt;
&lt;br /&gt;
(greet &amp;quot;Ada&amp;quot;)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Functions are closures and may be passed to &amp;lt;code&amp;gt;map&amp;lt;/code&amp;gt;, reducers, scanners, parsers, and handlers. &amp;lt;code&amp;gt;define&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; create a binding in the current scope in this dialect; &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; is not an imperative mutation of an outer lexical variable.&lt;br /&gt;
&lt;br /&gt;
== Pattern matching and modules ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;match&amp;lt;/code&amp;gt; is the usual way to express alternatives and destructure lists, strings, or regular-expression results. Modules are loaded with &amp;lt;code&amp;gt;import&amp;lt;/code&amp;gt;; application entrypoints typically import the required library files and then install handlers or start a server.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(match value&lt;br /&gt;
	&#039;(x y) (+ x y)&lt;br /&gt;
	(regex &amp;quot;^/users/([0-9]+)$&amp;quot; path id) id&lt;br /&gt;
	false)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
See [[Parsers]], [[Lists and Objects]], and the matching examples in the repository for the exact pattern forms.&lt;br /&gt;
&lt;br /&gt;
== State and concurrency ==&lt;br /&gt;
&lt;br /&gt;
The dialect is functional by default. &amp;lt;code&amp;gt;set&amp;lt;/code&amp;gt; defines a binding in the current scope; it does not imperatively mutate an outer binding. Use &amp;lt;code&amp;gt;(newsession)&amp;lt;/code&amp;gt; when code intentionally needs a thread-safe mutable key/value context shared across parallel work.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(set request_state (newsession))&lt;br /&gt;
(request_state &amp;quot;user_id&amp;quot; 42)&lt;br /&gt;
(request_state &amp;quot;user_id&amp;quot;)       /* 42 */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Independent functional work may run in parallel. Supported hot procedures can be compiled by the native x86-64 JIT; unsupported shapes remain interpreted without changing language semantics. See [[Full SCM API documentation]], [[Parallel Computing]], and [[In-Database WebApps and REST Services]].&lt;br /&gt;
&lt;br /&gt;
== Where to continue ==&lt;br /&gt;
&lt;br /&gt;
* [[Full SCM API documentation]] lists generated chapters and signatures.&lt;br /&gt;
* [[Lists and Objects]] explains lists, associative objects, mapping, and reduction.&lt;br /&gt;
* [[IO]] covers files, HTTP request/response objects, and servers.&lt;br /&gt;
* [[Storage]] documents the low-level table and scan interface; application code normally starts with SQL.&lt;br /&gt;
* [[JIT Compilation]] and [[Parallel Computing]] explain runtime optimization boundaries.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Introduction_to_RDF&amp;diff=390</id>
		<title>Introduction to RDF</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Introduction_to_RDF&amp;diff=390"/>
		<updated>2026-08-28T10:13:59Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Introduction to RDF =&lt;br /&gt;
&lt;br /&gt;
RDF represents facts as subject–predicate–object triples. MemCP stores and queries triples through its RDF module and exposes a tested SPARQL subset over HTTP.&lt;br /&gt;
&lt;br /&gt;
Unlike a fixed relational row, a resource can gain another predicate without altering a table schema. IRIs identify resources and predicates; objects may be another resource or a literal. For example, one person can have a type, name, mailbox, and &amp;lt;code&amp;gt;knows&amp;lt;/code&amp;gt; edge:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Subject !! Predicate !! Object&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;item:1&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;rdf:type&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;foaf:Person&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;item:1&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;foaf:name&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;&amp;quot;Ada&amp;quot;&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;item:1&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;foaf:knows&amp;lt;/code&amp;gt; || &amp;lt;code&amp;gt;item:2&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
SPARQL graph patterns join triples by shared variables. RDF is useful for heterogeneous metadata, semantic relationships, knowledge graphs, or integrations that already exchange Turtle/RDF. A conventional SQL schema is often simpler for stable, strongly constrained business records.&lt;br /&gt;
&lt;br /&gt;
Submit a query to &amp;lt;code&amp;gt;/rdf/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt; using HTTP Basic authentication. Load Turtle through &amp;lt;code&amp;gt;/rdf/&amp;amp;lt;database&amp;amp;gt;/load_ttl&amp;lt;/code&amp;gt;. Supported behavior includes core triple patterns, selected FILTER expressions and escaping, OPTIONAL left-join behavior, and tested update templates.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --fail-with-body -u root:strong-password \&lt;br /&gt;
  --data-binary &#039;SELECT ?s ?p ?o WHERE { ?s ?p ?o . } LIMIT 20&#039; \&lt;br /&gt;
  http://localhost:4321/rdf/mygraph&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Do not infer support for an unlisted SPARQL feature from the standard. Validate application queries and malformed-input behavior against the deployed version. See [[Advanced Graph Querying]] and [[Security and Authentication]].&lt;br /&gt;
&lt;br /&gt;
The external [https://github.com/launix-de/rdfop rdfop project] contains a larger RDF browser and templating application built around the same model.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Integer_Compression&amp;diff=389</id>
		<title>Integer Compression</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Integer_Compression&amp;diff=389"/>
		<updated>2026-08-28T10:13:59Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Integer Compression =&lt;br /&gt;
&lt;br /&gt;
MemCP can store an integer column relative to its minimum and bit-pack the remaining range. A range of eight values needs three value bits instead of a fixed 32- or 64-bit slot. Constant, sparse, low-cardinality, and arithmetic-sequence representations may win for other distributions.&lt;br /&gt;
&lt;br /&gt;
== Frame-of-reference layout ==&lt;br /&gt;
&lt;br /&gt;
The compact structure is easiest to understand without the later batch and JIT optimizations:&lt;br /&gt;
&lt;br /&gt;
* find &amp;lt;code&amp;gt;minimum&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;maximum&amp;lt;/code&amp;gt; inside one rebuilt shard;&lt;br /&gt;
* store &amp;lt;code&amp;gt;offset = minimum&amp;lt;/code&amp;gt;;&lt;br /&gt;
* choose &amp;lt;code&amp;gt;bitwidth = ceil(log2(maximum - minimum + 1))&amp;lt;/code&amp;gt; (plus a code when the chosen NULL representation needs one);&lt;br /&gt;
* allocate enough 64-bit words for &amp;lt;code&amp;gt;row_count × bitwidth&amp;lt;/code&amp;gt; bits;&lt;br /&gt;
* encode row &amp;lt;code&amp;gt;item_id&amp;lt;/code&amp;gt; at bit position &amp;lt;code&amp;gt;item_id × bitwidth&amp;lt;/code&amp;gt; as &amp;lt;code&amp;gt;value - offset&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;type packedFrame struct {&lt;br /&gt;
    offset   int64&lt;br /&gt;
    bitwidth uint8&lt;br /&gt;
    words    []uint64&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
bitpos := uint64(itemID) * uint64(frame.bitwidth)&lt;br /&gt;
word := bitpos / 64&lt;br /&gt;
shift := bitpos % 64&lt;br /&gt;
// read/write the value bits; a value may cross into words[word+1]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This is a frame-of-reference, fixed-bit packed representation sometimes discussed alongside FOR/PFOR techniques. The current &amp;lt;code&amp;gt;StorageInt&amp;lt;/code&amp;gt; does not need a classic Patched-FOR exception list: the observed shard range determines one lossless width, while sparse/default and sequence wrappers handle distributions for which another representation wins. See also [https://github.com/lemire/FastPFor FastPFor] and [https://wwwdb.inf.tu-dresden.de/wp-content/uploads/T_2014_Master_Patrick_Damme.pdf Patrick Damme&#039;s work on lightweight compression].&lt;br /&gt;
&lt;br /&gt;
For observed minimum &amp;lt;code&amp;gt;min&amp;lt;/code&amp;gt; and maximum &amp;lt;code&amp;gt;max&amp;lt;/code&amp;gt;, the encoder stores &amp;lt;code&amp;gt;value - min&amp;lt;/code&amp;gt; using enough bits for the complete range. Packed values cross 64-bit word boundaries when necessary; batch readers share bit-position work across consecutive RecordIDs. Binary values can therefore approach one payload bit per row, while IDs and local timestamp ranges use only the width their shard actually needs.&lt;br /&gt;
&lt;br /&gt;
Representation selection happens per rebuilt physical column. Scan code uses range and multi-record batch access so unpacking remains sequential and cache-friendly. Delta values written since the last rebuild are merged with main storage visibility by the scan path.&lt;br /&gt;
&lt;br /&gt;
== NULLs, defaults, and alternatives ==&lt;br /&gt;
&lt;br /&gt;
NULL/default-heavy columns can store exceptions sparsely instead of paying a full value slot for every row. A constant column needs no per-row payload, while a low-cardinality column may use dictionary or entropy-oriented identifiers. A regular counter or timestamp can be represented as arithmetic runs. The analyzer chooses among these options; “integer column” therefore does not imply one fixed byte width.&lt;br /&gt;
&lt;br /&gt;
When a packed range has a spare code, an implementation can reserve it for NULL; distributions where that would increase width may favor a sparse/default wrapper instead. The important contract is lossless SQL NULL round-trip, not one mandatory representation. Format choice is made from the actual shard values during rebuild.&lt;br /&gt;
&lt;br /&gt;
The reduced decision looks like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;if value == nil {&lt;br /&gt;
    hasNull = true&lt;br /&gt;
    return&lt;br /&gt;
}&lt;br /&gt;
observe(value)&lt;br /&gt;
&lt;br /&gt;
// During final width selection, reserve a code for NULL if it fits.&lt;br /&gt;
// Otherwise choose a lossless wrapper/representation that keeps NULL separate.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Example: values from 1,000 through 1,031 need five payload bits after subtracting 1,000. Adding a nullable sentinel may require another code, while a column with only a handful of NULL rows can encode those exceptional RecordIDs separately.&lt;br /&gt;
&lt;br /&gt;
For random values spanning most of a 64-bit range, bit packing may save little. Sorting or clustering can create smaller local ranges and longer sequences, but changing application order only for compression must be weighed against write behavior and query access paths.&lt;br /&gt;
&lt;br /&gt;
Space and speed depend on range width, null/default density, ordering, shard size, and access pattern. Publish the dataset and storage statistics with any ratio. Persistent layout changes must preserve old magic/version readers.&lt;br /&gt;
&lt;br /&gt;
In one early workload, nullable columns that had fallen back to the generic representation contributed to a reported 23 MiB footprint; after NULL-capable integer packing, the same workload was reported at 16 MiB. The old article described that as “40% savings”; arithmetically it is about a 30% reduction from 23 MiB. The dataset and measurement method were not preserved, so the result documents why the NULL code mattered but is not a current benchmark guarantee.&lt;br /&gt;
&lt;br /&gt;
See [[Columnar Storage]], [[Sequence Compression]], and [[Performance Measurement]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Install_MemCP_with_Docker&amp;diff=388</id>
		<title>Install MemCP with Docker</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Install_MemCP_with_Docker&amp;diff=388"/>
		<updated>2026-08-28T10:13:58Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;install-memcp-with-docker&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Install MemCP with Docker =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;docker pull carli2/memcp:latest&lt;br /&gt;
docker volume create memcp_data&lt;br /&gt;
docker run -d --name memcp --restart unless-stopped \&lt;br /&gt;
  -e ROOT_PASSWORD=&#039;replace-with-a-strong-password&#039; \&lt;br /&gt;
  -v memcp_data:/data -p 4321:4321 -p 3307:3307 \&lt;br /&gt;
  carli2/memcp:latest&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;ROOT_PASSWORD&amp;lt;/code&amp;gt; is used only for a fresh &amp;lt;code&amp;gt;/data&amp;lt;/code&amp;gt;. The image runs with &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt;, persists under &amp;lt;code&amp;gt;/data&amp;lt;/code&amp;gt;, and forwards stop signals to MemCP. Pin a release tag in production instead of &amp;lt;code&amp;gt;latest&amp;lt;/code&amp;gt;. Do not publish either port to an untrusted network without firewall/reverse-proxy protection.&lt;br /&gt;
&lt;br /&gt;
Pass additional flags through &amp;lt;code&amp;gt;PARAMS&amp;lt;/code&amp;gt;, for example &amp;lt;code&amp;gt;-e PARAMS=&#039;--disable-mysql --api-port=4321&#039;&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;APP&amp;lt;/code&amp;gt; selects the Scheme entry file and defaults to &amp;lt;code&amp;gt;lib/main.scm&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Back up the volume before upgrading. Verify the container log, authenticate a query, restart the container, and verify persisted data after every upgrade.&lt;br /&gt;
&lt;br /&gt;
== Build and application development ==&lt;br /&gt;
&lt;br /&gt;
To test the image produced by the current checkout instead of the published image:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git clone https://github.com/launix-de/memcp.git&lt;br /&gt;
cd memcp&lt;br /&gt;
docker build -t memcp-local .&lt;br /&gt;
docker volume create memcp_dev_data&lt;br /&gt;
docker run --rm -it \&lt;br /&gt;
  -e ROOT_PASSWORD=&#039;development-password&#039; \&lt;br /&gt;
  -v memcp_dev_data:/data -p 4321:4321 -p 3307:3307 \&lt;br /&gt;
  memcp-local&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Interactive mode is useful for Scheme application development; production containers should remain detached and use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt;. To load another Scheme entrypoint, mount or bake the application into the image and select it with &amp;lt;code&amp;gt;APP&amp;lt;/code&amp;gt;. Use &amp;lt;code&amp;gt;PARAMS&amp;lt;/code&amp;gt; only for command-line flags, not as a replacement for the application filename.&lt;br /&gt;
&lt;br /&gt;
Bind mounts such as &amp;lt;code&amp;gt;-v /var/lib/memcp:/data&amp;lt;/code&amp;gt; are also supported. Ensure the container user can write the directory and include it in backup and restore procedures.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Index_Compression&amp;diff=387</id>
		<title>Index Compression</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Index_Compression&amp;diff=387"/>
		<updated>2026-08-28T10:13:58Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Index Compression =&lt;br /&gt;
&lt;br /&gt;
MemCP indexes map ordered or matched values to compact record-ID sets and ranges. Main index state is stored with the rebuilt shard; an ordered index-local delta structure covers newer rows. Iteration merges both while respecting deletions, transaction visibility, and requested direction.&lt;br /&gt;
&lt;br /&gt;
Traditional trees store keys, child pointers and node slack. MemCP can exploit an immutable shard generation differently: sort a compact permutation of RecordIDs by the indexed columns, then binary-search column values through that permutation. Inserts do not splice into the immutable main array; the delta index covers them until rebuild. Wide strings therefore need not be copied into every tree entry.&lt;br /&gt;
&lt;br /&gt;
For a shard whose RecordIDs fit in 16 bits, 60,000 permutation entries need roughly 120 kB before surrounding metadata. Actual size varies with representation, shard size and auxiliary boundaries; inspect current statistics instead of treating that illustration as a guarantee.&lt;br /&gt;
&lt;br /&gt;
The essential data structure can be read from this reduced historical sketch. Current code adds transactions, delta ordering, richer boundary types and cost evidence, but the pointer-free permutation remains the central idea:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;type StorageIndex struct {&lt;br /&gt;
    columns     []string&lt;br /&gt;
    savings     float64&lt;br /&gt;
    sortedItems StorageInt // RecordIDs sorted by column values&lt;br /&gt;
    inactive    bool       // collect evidence before building&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Rows compare through &amp;lt;code&amp;gt;columns[0]&amp;lt;/code&amp;gt;, then &amp;lt;code&amp;gt;columns[1]&amp;lt;/code&amp;gt;, and so on. A lookup binary-searches the compressed RecordID permutation and reads the indexed column values from column storage. The index therefore avoids storing a second copy of wide keys and avoids one heap pointer per entry.&lt;br /&gt;
&lt;br /&gt;
The planner can build adaptive equality, range, prefix, computed-expression, and compact membership structures when observed workload and cost justify them. RecSets may carry exact record sets or safe candidate supersets; candidate sets retain a residual predicate. Index selection is a physical decision after logical decorrelation and join ordering.&lt;br /&gt;
&lt;br /&gt;
== Boundary extraction and reuse ==&lt;br /&gt;
&lt;br /&gt;
Conjunctions can provide equality prefixes followed by at most one useful ordered range, for example &amp;lt;code&amp;gt;a = ? AND b = ? AND c BETWEEN ? AND ?&amp;lt;/code&amp;gt;. Canonical column/expression identities allow related queries to share an index. A longer compatible index can serve a shorter prefix, avoiding a second physical structure. LIKE-prefix and other inexact matchers may return candidates and keep the original predicate as proof.&lt;br /&gt;
&lt;br /&gt;
== Adaptive build decision ==&lt;br /&gt;
&lt;br /&gt;
A syntactically possible index starts as an opportunity, not an immediate allocation. The analyzer estimates full-scan cost, build cost, indexed probe cost, shard population and expected reuse. Evidence accumulates until the projected savings amortize construction. Small shards may never build; ORDER/LIMIT benefit is weighted by the number of rows it can actually avoid.&lt;br /&gt;
&lt;br /&gt;
An early postcode experiment recorded an 8.275 ms full scan, an 18.188 ms scan that also built the index, followed by indexed lookups of 43.871, 45.681 and 39.021 µs. That observation motivated the original “build on the second use” heuristic. It lacks a current commit, dataset details, repetitions and result validation, so the figures are retained as design history rather than a current 200× claim. The current cost model is richer: creation should be paid for by observed future work, not triggered by every possible WHERE clause.&lt;br /&gt;
&lt;br /&gt;
Index size and performance depend on cardinality, clustering, fingerprint/range choices, update rate, and query distribution. A B-Heap layout was proposed to improve cache locality while traversing a tree; it remains an interesting future representation, not part of the supported current index. Persisted index formats obey the same permanent magic/version compatibility contract as columns.&lt;br /&gt;
&lt;br /&gt;
See [[Data Auto Sharding and Auto Indexing]], [[Scan]], and [[Query Planner and Physical Lowering]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=In-Database_WebApps_and_REST_Services&amp;diff=386</id>
		<title>In-Database WebApps and REST Services</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=In-Database_WebApps_and_REST_Services&amp;diff=386"/>
		<updated>2026-08-28T10:13:58Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= In-Database WebApps and REST Services =&lt;br /&gt;
&lt;br /&gt;
Embedded handlers run in the MemCP process and can access Scheme and storage APIs without a separate database connection. &amp;lt;code&amp;gt;lib/main.scm&amp;lt;/code&amp;gt; defines &amp;lt;code&amp;gt;http_handler&amp;lt;/code&amp;gt;; application modules can wrap the previous handler and route only their own path prefix.&lt;br /&gt;
&lt;br /&gt;
This is useful for small JSON APIs, dashboards, webhooks, static assets, or WebSocket gateways whose hot path is mostly database work. It reduces deployment pieces and transport overhead, but also couples application code to the database process. Keep CPU-heavy, blocking, untrusted, or independently deployed workloads outside MemCP.&lt;br /&gt;
&lt;br /&gt;
== Routing a path prefix ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(define http_handler (begin&lt;br /&gt;
	(set old_handler http_handler)&lt;br /&gt;
	(lambda (req res) (begin&lt;br /&gt;
		(match (req &amp;quot;path&amp;quot;)&lt;br /&gt;
			(regex &amp;quot;^/my-api/(.*)$&amp;quot; path rest) (begin&lt;br /&gt;
				((res &amp;quot;header&amp;quot;) &amp;quot;Content-Type&amp;quot; &amp;quot;application/json&amp;quot;)&lt;br /&gt;
				((res &amp;quot;status&amp;quot;) 200)&lt;br /&gt;
				((res &amp;quot;print&amp;quot;) &amp;quot;{\&amp;quot;ok\&amp;quot;:true}&amp;quot;))&lt;br /&gt;
			(old_handler req res))))))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Always delegate unmatched paths to the previous handler. Replacing the global handler without chaining it can hide the dashboard, SQL endpoints, or routes installed by other modules.&lt;br /&gt;
&lt;br /&gt;
The request object exposes method, host, path, query fields, headers, username/password, remote address, and lazy body readers. The response object sets headers and status, writes text/lines or JSONL rows, and can upgrade a connection to WebSocket. See [[IO]] for the generated function reference and &amp;lt;code&amp;gt;apps/&amp;lt;/code&amp;gt; for executable examples.&lt;br /&gt;
&lt;br /&gt;
== Prepared SQL and response streaming ==&lt;br /&gt;
&lt;br /&gt;
Parse and optimize fixed SQL outside the request hot path where practical; bind request values rather than concatenating untrusted SQL. The exact request/response functions are documented in [[IO]] and examples under &amp;lt;code&amp;gt;apps/&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(set find_user (parse_sql &amp;quot;myapp&amp;quot;&lt;br /&gt;
	&amp;quot;SELECT id, name FROM users WHERE id = @user_id&amp;quot;))&lt;br /&gt;
&lt;br /&gt;
/* inside a request handler */&lt;br /&gt;
(set session (newsession))&lt;br /&gt;
(session &amp;quot;user_id&amp;quot; requested_id)&lt;br /&gt;
(set resultrow (res &amp;quot;jsonl&amp;quot;))&lt;br /&gt;
(eval find_user)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Prepared formulas capture a fixed query shape, not permission to trust their parameters. Validate request types, authorize the selected record, and do not let callers choose arbitrary identifiers. Stream rows when possible; do not collect an unbounded result merely to turn it into one JSON array.&lt;br /&gt;
&lt;br /&gt;
The RDF frontend follows the same preparation pattern with &amp;lt;code&amp;gt;parse_sparql&amp;lt;/code&amp;gt;. Prepare a fixed SPARQL shape outside the handler, bind request-specific values through the intended context and stream results through the response. Do not concatenate caller text into either SQL or SPARQL.&lt;br /&gt;
&lt;br /&gt;
== Error handling and service boundaries ==&lt;br /&gt;
&lt;br /&gt;
Set the content type and status before writing the body. Convert expected validation and not-found cases into explicit 4xx responses; log unexpected failures without returning stack traces, SQL, secrets, or internal paths. Define request timeouts and body limits at the reverse proxy and inside application logic.&lt;br /&gt;
&lt;br /&gt;
== Security and lifecycle ==&lt;br /&gt;
&lt;br /&gt;
Handlers execute with in-process capabilities. Authenticate before database access, validate paths, headers and bodies, enforce request-size limits, and never expose default &amp;lt;code&amp;gt;root/admin&amp;lt;/code&amp;gt; credentials. Bound queues and long operations, propagate cancellation, and avoid retaining request objects after completion. Use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt; for daemon deployment. See [[Security and Authentication]], [[SQL over REST]], and [[Websockets in MemCP]].&lt;br /&gt;
&lt;br /&gt;
Minimal maintained examples live below &amp;lt;code&amp;gt;apps/&amp;lt;/code&amp;gt;. The external [https://github.com/launix-de/rdfop rdfop project] is a larger RDF browser and templating example; treat it as application source, not as part of MemCP&#039;s compatibility contract.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Deployment&amp;diff=385</id>
		<title>Deployment</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Deployment&amp;diff=385"/>
		<updated>2026-08-28T10:13:57Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;deployment&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Deployment =&lt;br /&gt;
&lt;br /&gt;
This page covers a single-node MemCP service from build through shutdown and upgrade. A production deployment must choose a durability ENGINE, protect credentials and listeners, provide a writable data directory or configured remote backend, and install the executable together with the exact matching Scheme libraries and assets.&lt;br /&gt;
&lt;br /&gt;
MemCP is currently Beta. Treat deployment as an operational workflow rather than merely starting a binary: establish backups, restart tests, resource limits, monitoring, upgrade rollback, and application-level compatibility checks before accepting production traffic. Multi-node ownership and failover are not yet provided by the [[Cluster Monitor]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;build-and-run&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Build and run ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;git clone https://github.com/launix-de/memcp&lt;br /&gt;
cd memcp&lt;br /&gt;
go mod download&lt;br /&gt;
make&lt;br /&gt;
./memcp -data /var/lib/memcp --no-repl \&lt;br /&gt;
  --api-port=4321 --mysql-port=3307 \&lt;br /&gt;
  --root-password=&#039;replace-on-first-start&#039; lib/main.scm&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;--root-password&amp;lt;/code&amp;gt; initializes a fresh data directory only. Never expose the HTTP or MySQL port using &amp;lt;code&amp;gt;root/admin&amp;lt;/code&amp;gt;. Put the service behind the intended firewall or reverse proxy and protect the data directory and configuration file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;interfaces&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Interfaces ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Interface&lt;br /&gt;
! Default&lt;br /&gt;
|-&lt;br /&gt;
| HTTP SQL/dashboard&lt;br /&gt;
| TCP 4321&lt;br /&gt;
|-&lt;br /&gt;
| MySQL protocol&lt;br /&gt;
| TCP 3307&lt;br /&gt;
|-&lt;br /&gt;
| MySQL Unix socket&lt;br /&gt;
| &amp;lt;code&amp;gt;/tmp/memcp.sock&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Data directory&lt;br /&gt;
| &amp;lt;code&amp;gt;./data&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Disable unused listeners with &amp;lt;code&amp;gt;--disable-api&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;--disable-mysql&amp;lt;/code&amp;gt;, or an empty socket setting. Use &amp;lt;code&amp;gt;--config=FILE&amp;lt;/code&amp;gt; for one argument per line; explicit command line options override configuration entries.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;service-installation&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Service installation ==&lt;br /&gt;
&lt;br /&gt;
MemCP supplies &amp;lt;code&amp;gt;make install&amp;lt;/code&amp;gt;, Debian and RPM package targets, systemd lifecycle scripts, and &amp;lt;code&amp;gt;make memcp.sif&amp;lt;/code&amp;gt; for Singularity/Apptainer. Packages install the binary and Scheme libraries in system paths and provide service configuration. Review paths and credentials before starting the service.&lt;br /&gt;
&lt;br /&gt;
For a source checkout, PM2 remains a lightweight supervisor option:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;pm2 start ./memcp --name memcp -- \&lt;br /&gt;
  --no-repl -data /var/lib/memcp \&lt;br /&gt;
  --api-port=4321 --mysql-port=3307 lib/main.scm&lt;br /&gt;
pm2 save&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After rebuilding, restart the named process with &amp;lt;code&amp;gt;pm2 restart memcp&amp;lt;/code&amp;gt;. Keep the binary, &amp;lt;code&amp;gt;lib/&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;assets/&amp;lt;/code&amp;gt; from the same commit. Docker is the other common deployment path; it consumes additional image/runtime resources but provides a reproducible bundle and a persistent &amp;lt;code&amp;gt;/data&amp;lt;/code&amp;gt; volume. See [[Install MemCP with Docker]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;shutdown-and-upgrades&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Shutdown and upgrades ==&lt;br /&gt;
&lt;br /&gt;
SIGTERM/SIGINT stops new work, drains in-flight requests up to &amp;lt;code&amp;gt;ShutdownDrainSeconds&amp;lt;/code&amp;gt;, and closes storage. Before upgrading persistent data:&lt;br /&gt;
&lt;br /&gt;
# back up the data directory or remote backend;&lt;br /&gt;
# read serialization and durability notes for the target release;&lt;br /&gt;
# stop MemCP cleanly;&lt;br /&gt;
# install the new binary and matching &amp;lt;code&amp;gt;lib/&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;assets/&amp;lt;/code&amp;gt; files;&lt;br /&gt;
# start it and verify logs, schema, representative reads/writes, and restart.&lt;br /&gt;
&lt;br /&gt;
Do not copy only the binary while retaining incompatible Scheme libraries. See [[Install_MemCP_with_Docker|Install MemCP with Docker]], [[Storage_Backends|Storage Backends]], and [[Persistency_and_Performance_Guarantees|Persistency and Performance Guarantees]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Database_Tools_compatibility_with_MemCP&amp;diff=384</id>
		<title>Database Tools compatibility with MemCP</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Database_Tools_compatibility_with_MemCP&amp;diff=384"/>
		<updated>2026-08-28T10:13:56Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Database Tools compatibility with MemCP =&lt;br /&gt;
&lt;br /&gt;
MemCP speaks the MySQL wire protocol over TCP and a Unix socket. Compatibility depends on both SQL behavior and the metadata queries issued by a particular client version.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Tool !! Connection !! Current status !! Notes&lt;br /&gt;
|-&lt;br /&gt;
| MySQL CLI || MySQL protocol || Supported || Core SQL, prepared statements, SHOW metadata, and process control&lt;br /&gt;
|-&lt;br /&gt;
| PDO MySQL || MySQL protocol || Supported || Use the MySQL PDO driver&lt;br /&gt;
|-&lt;br /&gt;
| DBeaver || MySQL driver || Supported with limitations || Retest schema editing and metadata against the concrete release&lt;br /&gt;
|-&lt;br /&gt;
| PHPMyAdmin || MySQL driver || Compatibility target || Do not claim a version supported without a dated test run&lt;br /&gt;
|-&lt;br /&gt;
| VS Code SQLTools || MySQL/MariaDB driver || Supported with limitations || No dedicated MemCP extension is required&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MemCP implements prepared statements, selected &amp;lt;code&amp;gt;INFORMATION_SCHEMA&amp;lt;/code&amp;gt; relations, SHOW metadata, processlist, TCP, and a Unix socket. It does not claim byte-for-byte MySQL server behavior. Record the MemCP commit, client version, connection mode, and failed metadata query when reporting incompatibility.&lt;br /&gt;
&lt;br /&gt;
== Connecting a tool ==&lt;br /&gt;
&lt;br /&gt;
Select a MySQL or MariaDB driver, use the configured host and MySQL port (3307 in the documentation examples), and authenticate with a least-privilege MemCP user. Disable driver features that require an unsupported server capability rather than assuming the connection failure is network-related. For the command line:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mysql --protocol=TCP -h 127.0.0.1 -P 3307 -u app_user -p myapp&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When a GUI opens a connection but fails while browsing schemas, capture its first failing metadata statement and reproduce that SQL through the CLI. Tool compatibility often depends on those discovery queries rather than ordinary SELECT/INSERT behavior.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Matrix reviewed against MemCP commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026; individual GUI versions still require concrete verification.&#039;&#039;&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Current_Status_and_Open_Issues&amp;diff=383</id>
		<title>Current Status and Open Issues</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Current_Status_and_Open_Issues&amp;diff=383"/>
		<updated>2026-08-28T10:13:56Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;current-status-and-open-issues&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Current Status and Open Issues =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Verified against commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026.&#039;&#039;&#039; Update this marker whenever the implementation-facing inventory is refreshed.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
MemCP is &#039;&#039;&#039;Beta&#039;&#039;&#039;. Core SQL, persistence, compression, parallel scans, REST, and MySQL-protocol access are usable, but compatibility and complex planner cases continue to evolve.&lt;br /&gt;
&lt;br /&gt;
MemCP&#039;s stated ambition remains a &#039;&#039;&#039;fast, compact database for mixed OLTP and OLAP&#039;&#039;&#039;. Measured OLAP and search-oriented workflows have reached &#039;&#039;&#039;speedups of 10× and more over MariaDB/PostgreSQL&#039;&#039;&#039;, particularly where RecSets and compressed column scans avoid wide intermediate rows. In one filtered-list workflow over approximately one million documents, the same query took around &#039;&#039;&#039;30 seconds on PostgreSQL&#039;&#039;&#039; and &#039;&#039;&#039;1.6 seconds on MemCP&#039;&#039;&#039;. Isolated OLTP paths currently take about &#039;&#039;&#039;1.3–2.0× as long&#039;&#039;&#039;, but in complete WordPress- and wiki-style page builds this has made &#039;&#039;&#039;no significant difference to overall page-loading time&#039;&#039;&#039; in the measured application workflows. The OLTP gap is tracked as JIT, compilation, point-path and compatibility work rather than used to dilute the search/analytics performance proposition.&lt;br /&gt;
&lt;br /&gt;
For write-heavy workloads, project measurements have reached about &#039;&#039;&#039;10× &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; throughput&#039;&#039;&#039; with &amp;lt;code&amp;gt;ENGINE=logged&amp;lt;/code&amp;gt;. That result is inseparable from its durability trade-off: the WAL survives a process crash but is not synchronized against kernel crash or power loss. &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; instead publishes compressed main storage on the normal 15-minute rebuild cycle, which can protect SD-card lifetime for reconstructible data while accepting loss of the unrebuilt delta.&lt;br /&gt;
&lt;br /&gt;
== Readiness by area ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Area !! Current position !! What adopters should verify&lt;br /&gt;
|-&lt;br /&gt;
| SQL applications || Broad tested relational subset, views, CTEs/subqueries, UNION, windows, DML/DDL, constraints, triggers, and JSON || Every production query, collation/type edge, error expectation, and metadata query&lt;br /&gt;
|-&lt;br /&gt;
| Transactions/durability || Implicit/explicit transactions, cursor stability, snapshot/OCC infrastructure, per-table engines, WAL/replay || Required isolation/conflict patterns, power-loss behavior, backup and restore&lt;br /&gt;
|-&lt;br /&gt;
| Analytics || Compressed columns, batch/parallel scans, grouping/windows, adaptive indexes and reusable physical structures || Plans, memory, concurrent write latency, warm/cold performance&lt;br /&gt;
|-&lt;br /&gt;
| Interfaces || MySQL TCP/socket, SQL/HTTP, PostgreSQL-syntax HTTP, RDF, Scheme/custom HTTP/WebSocket || Concrete connector/tool versions, authentication, protocol assumptions&lt;br /&gt;
|-&lt;br /&gt;
| Operations || Dashboard, processlist/cancellation, settings, logs, packaging, local/S3/Ceph storage || Monitoring, capacity, upgrades, restore drills, backend outages&lt;br /&gt;
|-&lt;br /&gt;
| Scale-out || Local sharding and parallel execution within one instance || Multi-node cluster/HA is not implemented as a production feature&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
This page intentionally does not duplicate a static TODO list. Current bugs, planned work, and release blockers live in the [https://github.com/launix-de/memcp/issues GitHub issue tracker].&lt;br /&gt;
&lt;br /&gt;
== Product and engineering roadmap ==&lt;br /&gt;
&lt;br /&gt;
The repository also contains design documents for longer-term work. They describe direction and invariants, not promised release dates:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Broader JIT and vectorized execution:&#039;&#039;&#039; compile more scan filters, expressions, storage decoders and reducers into tight architecture-specific loops while retaining safe interpreter fallback.&lt;br /&gt;
* &#039;&#039;&#039;Lower compile time:&#039;&#039;&#039; bounded planner traversals, structural sharing and recipe-based physical emission for very large application-generated queries.&lt;br /&gt;
* &#039;&#039;&#039;Remote SQL tables:&#039;&#039;&#039; treat MySQL/PostgreSQL sources as scannable relations with explicit capability discovery, predicate/projection pushdown, transaction limits and safe fallback.&lt;br /&gt;
* &#039;&#039;&#039;Vector search:&#039;&#039;&#039; combine scalar partition boundaries with local vector “bubble” clusters and hierarchical top-k search.&lt;br /&gt;
* &#039;&#039;&#039;Cluster mode:&#039;&#039;&#039; leaderless CRUSH directory assignment, MOESI-inspired shard caches, RADOS persistence and remote partial scans; a later distributed catalog removes global registries for extremely large deployments.&lt;br /&gt;
* &#039;&#039;&#039;Specialized indexes and [[RecSets]]:&#039;&#039;&#039; choose ranges, sparse IDs, bitmaps, prefix/full-text and computed access paths according to observed density and cost.&lt;br /&gt;
&lt;br /&gt;
See [[Cluster Monitor]], [[Query Planner and Physical Lowering]], [[RecSets]], [[JIT Compilation]], [[Vectors]] and [[Data Auto Sharding and Auto Indexing]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;implemented-since-the-old-status-page&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Implemented since the old status page ==&lt;br /&gt;
&lt;br /&gt;
* per-table &amp;lt;code&amp;gt;ALTER TABLE … ENGINE&amp;lt;/code&amp;gt; transitions;&lt;br /&gt;
* configurable LRU memory management and system-pressure eviction;&lt;br /&gt;
* AUTO_INCREMENT persistence and tested unique/not-null/foreign-key behavior;&lt;br /&gt;
* main/delta ordered index merging and LIKE/pattern access improvements;&lt;br /&gt;
* persistent SQL triggers and computed-column invalidation hooks;&lt;br /&gt;
* cursor-stability transactions plus ACID snapshot/OCC infrastructure;&lt;br /&gt;
* UNION, windows, views, broad subquery decorrelation, and join reordering;&lt;br /&gt;
* cost-based physical lowering, RecSets, group caches, ORC, and plan variants;&lt;br /&gt;
* native x86-64 Scheme JIT for supported procedures;&lt;br /&gt;
* processlist, query cancellation, dashboard, metrics, logs, and packaging;&lt;br /&gt;
* S3-compatible and optional Ceph/RADOS persistence;&lt;br /&gt;
* MySQL/PostgreSQL live import and PostgreSQL dump/archive import.&lt;br /&gt;
* native BSON-backed MySQL and PostgreSQL JSON support, including path access, mutation, constructors, aggregates, relational expansion, and computed-index acceleration.&lt;br /&gt;
&lt;br /&gt;
== Outcome of the earlier roadmap ==&lt;br /&gt;
&lt;br /&gt;
The former status page was also a design record. The compact inventory below preserves what those concrete proposals became instead of silently deleting them when they left the TODO list.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
! Earlier proposal !! Outcome&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;ALTER TABLE … ENGINE&amp;lt;/code&amp;gt; || Implemented for all five engines; persisted → &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; is deliberately destructive and documented as such.&lt;br /&gt;
|-&lt;br /&gt;
| LRU cleanup for temporary columns || Expanded into budgets and eviction for reloadable columns, indexes, computed data, keytables, cache tables and dictionaries; memory-engine rows remain non-evictable.&lt;br /&gt;
|-&lt;br /&gt;
| Change hooks for computed columns || Implemented through SQL triggers and internal dependency/invalidation triggers for computed, grouped, prejoined and ordered data.&lt;br /&gt;
|-&lt;br /&gt;
| Enforced foreign keys || Implemented for tested CREATE TABLE RESTRICT, CASCADE and SET NULL paths; some ALTER compatibility forms remain non-operative.&lt;br /&gt;
|-&lt;br /&gt;
| One memory-mapped database-sized key/value file || Not adopted. MemCP keeps versioned per-column files and WALs, with optional object backends; selected subsystems may still use mmap internally.&lt;br /&gt;
|-&lt;br /&gt;
| Merge sorted index delta data with the main index || Implemented with a compressed main permutation plus an ordered index-local delta structure.&lt;br /&gt;
|-&lt;br /&gt;
| One multi-table &amp;lt;code&amp;gt;scan_star&amp;lt;/code&amp;gt;/merge-join operator || Superseded by reordered logical join trees and costed nested, indexed, ordered, RecSet, cached and parallel physical paths.&lt;br /&gt;
|-&lt;br /&gt;
| Process IDs, request context and kill switch || Implemented through PROCESSLIST, dashboard controls, KILL QUERY/CONNECTION and cancellation-aware waits.&lt;br /&gt;
|-&lt;br /&gt;
| Transaction insert/delete overlays and conflicts || Expanded into cursor-stability handling plus snapshot/OCC infrastructure, rollback, visibility and commit conflict checks.&lt;br /&gt;
|-&lt;br /&gt;
| LIKE indexes || Implemented as prefix/match boundaries with residual predicates whenever the boundary is only a candidate set.&lt;br /&gt;
|-&lt;br /&gt;
| SPARQL updates and OPTIONAL || Implemented for the tested DELETE/INSERT/WHERE, template and OPTIONAL subset; this is not complete SPARQL coverage.&lt;br /&gt;
|-&lt;br /&gt;
| AUTO_INCREMENT persistence || Implemented, including restart and ALTER behavior.&lt;br /&gt;
|-&lt;br /&gt;
| Convert subqueries into joins || Expanded into logical decorrelation of scalar, IN/NOT IN and EXISTS/NOT EXISTS forms before join ordering.&lt;br /&gt;
|-&lt;br /&gt;
| Shard group tables and prejoin complex plans || Implemented as costed physical alternatives alongside direct scans, FK/PK reuse, group caches and RecSets.&lt;br /&gt;
|-&lt;br /&gt;
| Restrict users to databases || Implemented through system users, grants, revokes and frontend enforcement.&lt;br /&gt;
|-&lt;br /&gt;
| DBeaver/phpMyAdmin metadata compatibility || Ongoing and version-specific; protocol, prepared statements, SHOW and selected INFORMATION_SCHEMA relations exist.&lt;br /&gt;
|-&lt;br /&gt;
| Native Scheme JIT || Implemented for supported x86-64 procedures with interpreter fallback.&lt;br /&gt;
|-&lt;br /&gt;
| Arbitrary HTTP/IPFS stream filenames || Not generally implemented; local files and supported archive paths are the documented contract.&lt;br /&gt;
|-&lt;br /&gt;
| Stable native C++/GPU plugin ABI || Not implemented; internal extension hooks are not a promised public plugin ABI.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The earlier multi-phase JSON plan is now represented by the implemented capability inventory in [[JSON]] and [[Supported SQL]]. Keeping it labelled as future work here would be misleading.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;areas-still-requiring-verification&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Areas still requiring verification ==&lt;br /&gt;
&lt;br /&gt;
* complete MySQL/PostgreSQL grammar and metadata compatibility;&lt;br /&gt;
* rare correlated, outer-join, UNION, window, and three-valued-logic shapes;&lt;br /&gt;
* high-contention transaction behavior and long-running repartition/rebuild work;&lt;br /&gt;
* compatibility of individual ORMs and administration tools;&lt;br /&gt;
* platform coverage outside the main Linux/x86-64 development path;&lt;br /&gt;
* reproducible performance results across representative workloads.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;reporting-a-problem&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Reporting a problem ==&lt;br /&gt;
&lt;br /&gt;
Include the MemCP commit/version, schema, minimal query, expected result, actual result, ENGINE mode, frontend, and whether the problem reproduces after restart. For performance reports include row counts, EXPLAIN output, cache state, hardware, concurrency, raw timings, and a current-master comparison.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Compile_MemCP_from_Source&amp;diff=382</id>
		<title>Compile MemCP from Source</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Compile_MemCP_from_Source&amp;diff=382"/>
		<updated>2026-08-28T10:13:56Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Compile MemCP from Source =&lt;br /&gt;
&lt;br /&gt;
Building from source is the recommended path for development, debugging, unreleased planner work, and installations that need optional build variants such as Ceph/RADOS or the native JIT. A source build produces the &amp;lt;code&amp;gt;memcp&amp;lt;/code&amp;gt; executable, but a working installation also needs the matching &amp;lt;code&amp;gt;lib/&amp;lt;/code&amp;gt; Scheme modules and, where used, the accompanying assets.&lt;br /&gt;
&lt;br /&gt;
Use a supported Go toolchain and build from a specific release tag or recorded commit so the binary and runtime libraries remain reproducible. Run the complete test suite before deploying a locally built executable, especially after changing storage formats, transaction behavior, SQL parsing, or query planning.&lt;br /&gt;
&lt;br /&gt;
== Requirements ==&lt;br /&gt;
&lt;br /&gt;
MemCP requires &#039;&#039;&#039;Go 1.24 or newer&#039;&#039;&#039;, GNU Make, and Git. Optional Ceph/RADOS support additionally requires the RADOS development headers.&lt;br /&gt;
&lt;br /&gt;
== Build and test ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
git clone https://github.com/launix-de/memcp&lt;br /&gt;
cd memcp&lt;br /&gt;
go mod download&lt;br /&gt;
make&lt;br /&gt;
make test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The test command builds &amp;lt;code&amp;gt;./memcp&amp;lt;/code&amp;gt; and runs the Scheme unit tests and SQL YAML integration suites. Planner changes must also respect &amp;lt;code&amp;gt;INVARIANTS.md&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Run ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./memcp --api-port=4321 --mysql-port=3307 lib/main.scm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When no Scheme file is supplied, MemCP searches the working directory, executable directory, &amp;lt;code&amp;gt;/usr/local/lib/memcp&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;/usr/lib/memcp&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;lib/main.scm&amp;lt;/code&amp;gt;. Background services must use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt;. See [[Deployment]] and [[Security and Authentication]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Comparison:_MemCP_vs._MySQL&amp;diff=381</id>
		<title>Comparison: MemCP vs. MySQL</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Comparison:_MemCP_vs._MySQL&amp;diff=381"/>
		<updated>2026-08-28T10:13:55Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Comparison: MemCP vs. MySQL =&lt;br /&gt;
&lt;br /&gt;
MemCP is a Beta persistent main-memory, column-oriented database with MySQL protocol compatibility. It targets mixed operational and analytical workloads whose active columns benefit from compression, batch scans, and in-process APIs. It is not a complete replacement for every MySQL feature.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Area !! MySQL !! MemCP&lt;br /&gt;
|-&lt;br /&gt;
| Physical layout || Primarily row-oriented InnoDB pages || Compressed columns with main and delta storage&lt;br /&gt;
|-&lt;br /&gt;
| Working set || Buffer pool and operating-system cache || Active data and query structures managed in RAM, with reloadable persistent columns&lt;br /&gt;
|-&lt;br /&gt;
| Compatibility || Reference implementation of the MySQL dialect/protocol || Tested subset plus compatibility syntax; unsupported features remain&lt;br /&gt;
|-&lt;br /&gt;
| Durability || InnoDB configuration and transaction log || Per-table &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| APIs || Normally accessed through a connector || MySQL protocol, SQL/HTTP, PostgreSQL-syntax HTTP, RDF, and embedded Scheme handlers&lt;br /&gt;
|-&lt;br /&gt;
| Analytical scans || Row pages and secondary indexes; columnar analytics commonly use another system or service || Compressed columns, batch reads, late materialization, parallel shards, and fused scan pipelines&lt;br /&gt;
|-&lt;br /&gt;
| Operational writes || Mature InnoDB row storage, locking, replication, and tooling || Main/delta column storage, indexes, constraints, transactions, and per-table durability for mixed read/write workloads&lt;br /&gt;
|-&lt;br /&gt;
| Query optimization || Mature general-purpose MySQL optimizer || Logical decorrelation and join ordering followed by cost-based selection of scans, RecSets, caches, computed columns, and streaming paths&lt;br /&gt;
|-&lt;br /&gt;
| Extensibility || Functions, plugins, stored programs, and a large connector ecosystem || Embedded functional Scheme runtime, custom HTTP/WebSocket handlers, SQL operator extensions, and Go storage engine&lt;br /&gt;
|-&lt;br /&gt;
| Operations || Established backup, replication, HA, cloud, and observability ecosystem || Built-in dashboard/process controls and multiple storage backends; smaller ecosystem and no production multi-node cluster today&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Where MemCP can be attractive ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Mixed operational and analytical work:&#039;&#039;&#039; recent inserts and updates can feed dashboards, grouping, and ad-hoc analysis without first exporting a second analytical copy.&lt;br /&gt;
* &#039;&#039;&#039;Wide tables and selective columns:&#039;&#039;&#039; a query can read only referenced compressed columns instead of moving whole rows through memory.&lt;br /&gt;
* &#039;&#039;&#039;Repeated categories and ordered values:&#039;&#039;&#039; dictionary, bit-packed, sparse, prefix, and sequence representations can reduce cache traffic when the data distribution fits.&lt;br /&gt;
* &#039;&#039;&#039;Application-specific services:&#039;&#039;&#039; SQL over HTTP and embedded Scheme handlers can remove a separate middleware-to-database connection for small, carefully secured services.&lt;br /&gt;
* &#039;&#039;&#039;Per-table trade-offs:&#039;&#039;&#039; durable business data and reconstructible caches can use different engines in one instance.&lt;br /&gt;
* &#039;&#039;&#039;Natural ordering:&#039;&#039;&#039; MemCP exposes collations that can compare embedded numeric parts naturally, so values such as 2 and 10 need not sort lexicographically as 10 before 2.&lt;br /&gt;
* &#039;&#039;&#039;Flexible identifiers:&#039;&#039;&#039; long logical column names are not tied to the local persistence filename; long names are represented with stable hashed filenames. Applications must still test connector and MySQL-metadata limits.&lt;br /&gt;
&lt;br /&gt;
These are architectural opportunities, not automatic wins. Point-heavy workloads that already fit MySQL&#039;s buffer pool, write-heavy contention, poorly compressible high-cardinality values, cold remote storage, or an unsuitable physical plan may favor MySQL.&lt;br /&gt;
&lt;br /&gt;
== Current measured trade-off ==&lt;br /&gt;
&lt;br /&gt;
In project measurements, OLAP and search-oriented cases have reached &#039;&#039;&#039;speedups of 10× and more over MariaDB/PostgreSQL&#039;&#039;&#039;. RecSets are particularly important for large filtered domains and correlated membership workflows: they carry compact record-ID sets between operators, can adapt between ranges, sparse IDs and bitmaps, and let later column scans avoid materializing wide intermediate rows.&lt;br /&gt;
&lt;br /&gt;
Isolated OLTP paths have taken about &#039;&#039;&#039;1.3–2.0× as long&#039;&#039;&#039; as on the established database. In complete WordPress- and wiki-style page builds, however, this has made &#039;&#039;&#039;no significant difference to overall page-loading time&#039;&#039;&#039; in the measured application workflows; the end-to-end effect depends on the application&#039;s own work and on the number and mix of SQL queries it issues. That is real optimization debt, especially for high-throughput APIs, but it is a different user impact from a filtered-list search over roughly one million documents in which the same query took around &#039;&#039;&#039;30 seconds on PostgreSQL&#039;&#039;&#039; and &#039;&#039;&#039;1.6 seconds on MemCP&#039;&#039;&#039;. MemCP&#039;s immediate performance case is strongest where users wait on search, filtering, grouping and analytical reads.&lt;br /&gt;
&lt;br /&gt;
The figures are workload observations rather than a promise for arbitrary SQL. Reproduce them with the deployed versions, representative data, equal durability and successful responses; see [[Performance Measurement]].&lt;br /&gt;
&lt;br /&gt;
Write performance can be chosen independently per table. Project measurements have reached about &#039;&#039;&#039;10× the &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; write throughput&#039;&#039;&#039; after switching to &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt;, because the latter omits the commit-time &amp;lt;code&amp;gt;fsync&amp;lt;/code&amp;gt;. This is not a free optimization: process-crash recovery remains, but recent commits may be lost on kernel crash or power failure. &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; goes further by omitting the WAL and normally publishing one compressed generation every 15 minutes; for reconstructible data this can reduce continuous SD-card writes and flash wear.&lt;br /&gt;
&lt;br /&gt;
== Where MySQL remains the safer default ==&lt;br /&gt;
&lt;br /&gt;
Choose or retain MySQL when the application requires complete MySQL behavior, certified vendor integrations, mature replication and failover, a broad managed-service ecosystem, XA/distributed transactions, or operational practices that have not yet been reproduced and tested for MemCP. Protocol compatibility does not mean every SQL feature, metadata query, collation, error code, or connector edge case behaves identically.&lt;br /&gt;
&lt;br /&gt;
== Migration and fair evaluation ==&lt;br /&gt;
&lt;br /&gt;
Start with a copy or shadow workload rather than replacing the source of truth. Import the schema/data, run representative reads against both systems, compare results, exercise constraints and transaction conflicts, restart and restore, then measure latency and throughput. Keep MySQL available until SQL compatibility, durability, capacity, and operational rollback gates are satisfied.&lt;br /&gt;
&lt;br /&gt;
Performance and compression depend on schema, cardinality, ordering, query shape, hardware, durability mode, cache state, and concurrency. Numeric comparisons must name both versions, dataset, query, hardware, ENGINE, warm-up procedure, number of successful responses, and raw samples. The observed &#039;&#039;&#039;order-of-magnitude OLAP/search gains&#039;&#039;&#039;—including the 30-second versus 1.6-second filtered-list case—and historical compression reductions are important evidence for MemCP&#039;s target workloads, but they are not universal guarantees.&lt;br /&gt;
&lt;br /&gt;
MemCP nevertheless aims to outperform conventional row storage for its target workloads. Publishing current losses—including application suites that remain interpreter- or compile-time-bound—is part of reaching that goal, not a reason to erase the performance proposition.&lt;br /&gt;
&lt;br /&gt;
If SQL performance is the limiting factor, the useful next step is not another abstract feature comparison: run the slow production-shaped queries against MemCP. When result parity, durability, operations and rollback gates pass and MemCP wins the workload, move that workload to MemCP. Start with [[MySQL is too slow|the hands-on evaluation]].&lt;br /&gt;
&lt;br /&gt;
See [[Migration from MySQL and PostgreSQL]], [[Performance Measurement]], [[Supported SQL]], [[Database Tools compatibility with MemCP]], and [[Persistency and Performance Guarantees]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Columnar_Storage&amp;diff=380</id>
		<title>Columnar Storage</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Columnar_Storage&amp;diff=380"/>
		<updated>2026-08-28T10:13:55Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Columnar Storage =&lt;br /&gt;
&lt;br /&gt;
Column-oriented storage keeps the values of each column together instead of storing complete rows next to one another. For MemCP this serves two related goals:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Compression:&#039;&#039;&#039; values of one column usually have similar types, ranges, repetition, or ordering and can use a specialized compact encoding.&lt;br /&gt;
* &#039;&#039;&#039;Cache locality:&#039;&#039;&#039; a query reads only referenced columns, so scans avoid moving unrelated row fields through memory and CPU caches.&lt;br /&gt;
&lt;br /&gt;
Compression is not only a capacity feature. A lightweight decoder can be cheaper than fetching additional cache lines from a larger uncompressed representation.&lt;br /&gt;
&lt;br /&gt;
== Main and delta storage ==&lt;br /&gt;
&lt;br /&gt;
Each shard separates stable main rows from recent changes. Main storage is columnar and compressed. Inserts, updates, and deletions are represented through delta structures and transaction visibility metadata until rebuild work produces a new main generation.&lt;br /&gt;
&lt;br /&gt;
Scans combine main and delta data without exposing that physical split to SQL. Ordered indexes merge their compressed main-record permutation with index-local delta entries; deleted or invisible records remain filtered according to the active transaction.&lt;br /&gt;
&lt;br /&gt;
This design keeps immutable compressed columns efficient while allowing writes without rebuilding the complete column for every statement. See [[Shards, RecordIDs, Main Storage, Delta Storage]].&lt;br /&gt;
&lt;br /&gt;
== Interface design ==&lt;br /&gt;
&lt;br /&gt;
The storage interface has to support several competing requirements:&lt;br /&gt;
&lt;br /&gt;
* concurrent random reads for point lookups;&lt;br /&gt;
* efficient sequential and arbitrary-ID batch reads;&lt;br /&gt;
* format-specific cached decoding without sharing mutable reader state between goroutines;&lt;br /&gt;
* analysis of incoming values before selecting a representation;&lt;br /&gt;
* statistics for query planning;&lt;br /&gt;
* stable persistence across software upgrades;&lt;br /&gt;
* optional native JIT emission for hot value access.&lt;br /&gt;
&lt;br /&gt;
The original implementation can be understood through this deliberately reduced two-pass model. It is not the complete current Go interface, but it exposes the stable idea more clearly than the optimized implementation:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;type ColumnStorage interface {&lt;br /&gt;
    GetValue(recordID uint32) any&lt;br /&gt;
&lt;br /&gt;
    // analysis pass&lt;br /&gt;
    prepare()&lt;br /&gt;
    scan(recordID uint32, value any)&lt;br /&gt;
    proposeCompression() ColumnStorage&lt;br /&gt;
&lt;br /&gt;
    // build pass&lt;br /&gt;
    init(size uint32)&lt;br /&gt;
    build(recordID uint32, value any)&lt;br /&gt;
    finish()&lt;br /&gt;
&lt;br /&gt;
    Serialize(io.Writer)&lt;br /&gt;
    Deserialize(io.Reader)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The optimized code adds batch readers, transaction-aware access, statistics, versioned serialization and JIT hooks around this model; it does not change the analyze → choose representation → build sequence.&lt;br /&gt;
&lt;br /&gt;
The current read side is split into &amp;lt;code&amp;gt;ColumnStorage&amp;lt;/code&amp;gt; and a per-goroutine &amp;lt;code&amp;gt;ColumnReader&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;type ColumnReader interface {&lt;br /&gt;
    GetValue(recid uint32) Scmer&lt;br /&gt;
    GetValueMulti(recids []uint32, target []Scmer, stride int)&lt;br /&gt;
    GetValueRange(recid, count uint32, target []Scmer, stride int)&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;GetValue&amp;lt;/code&amp;gt; supports one random RecordID. &amp;lt;code&amp;gt;GetValueRange&amp;lt;/code&amp;gt; reads consecutive IDs, allowing bit-position calculations, binary searches, or decoder initialization to be shared by a complete run. &amp;lt;code&amp;gt;GetValueMulti&amp;lt;/code&amp;gt; gathers arbitrary IDs such as an index permutation and detects consecutive regions where the encoding benefits from a sequential path.&lt;br /&gt;
&lt;br /&gt;
Both batch methods write into a caller-provided target with a configurable stride. A scan assembling an interleaved row buffer can therefore fetch one column at a time without allocating an intermediate list for every value.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;GetCachedReader()&amp;lt;/code&amp;gt; returns a reader optimized for repeated access. Such a reader belongs to one goroutine and must not be shared. Transaction-dependent formats can provide a transaction-bound reader; callers should use shard/table helpers rather than reaching into column maps directly.&lt;br /&gt;
&lt;br /&gt;
== Analysis and build phases ==&lt;br /&gt;
&lt;br /&gt;
Column creation and shard rebuild use a two-pass process so the format can be selected from the actual data before allocating its final representation.&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;Analyze&#039;&#039;&#039;&lt;br /&gt;
#* &amp;lt;code&amp;gt;prepare()&amp;lt;/code&amp;gt; resets format-specific observations.&lt;br /&gt;
#* Each future value is passed to &amp;lt;code&amp;gt;scan(recordId, value)&amp;lt;/code&amp;gt;.&lt;br /&gt;
#* The implementation records facts such as type, range, scale, distinctness, repetition, NULL/default frequency, run structure, and string dictionary potential.&lt;br /&gt;
#* &amp;lt;code&amp;gt;proposeCompression(size)&amp;lt;/code&amp;gt; may return a more suitable lossless storage implementation.&lt;br /&gt;
#* If the format changes, analysis repeats for the proposed representation.&lt;br /&gt;
# &#039;&#039;&#039;Build&#039;&#039;&#039;&lt;br /&gt;
#* &amp;lt;code&amp;gt;init(size)&amp;lt;/code&amp;gt; allocates the final structures.&lt;br /&gt;
#* &amp;lt;code&amp;gt;build(recordId, value)&amp;lt;/code&amp;gt; encodes every value.&lt;br /&gt;
#* &amp;lt;code&amp;gt;finish()&amp;lt;/code&amp;gt; releases temporary builder state and finalizes dictionaries or indexes needed by the representation.&lt;br /&gt;
&lt;br /&gt;
This makes compression a data-dependent decision rather than a fixed mapping from SQL type to one physical format. The selected storage still reports a cheap distinct-count estimate for physical planning.&lt;br /&gt;
&lt;br /&gt;
== Storage formats ==&lt;br /&gt;
&lt;br /&gt;
The current implementation includes and composes formats such as:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Format&lt;br /&gt;
! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageSCMER&amp;lt;/code&amp;gt;&lt;br /&gt;
| Generic Scheme values and the universal starting representation when no narrower format is yet known.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageConst&amp;lt;/code&amp;gt;&lt;br /&gt;
| One repeated value without storing it once per record.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageSparse&amp;lt;/code&amp;gt;&lt;br /&gt;
| Sparse/default-heavy columns represented by exceptional RecordIDs and values.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageInt&amp;lt;/code&amp;gt;&lt;br /&gt;
| Bit-packed integers whose width and offset are derived from the observed range.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageSeq&amp;lt;/code&amp;gt;&lt;br /&gt;
| Arithmetic sequences and runs such as ordered identifiers.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageDecimal&amp;lt;/code&amp;gt;&lt;br /&gt;
| Exact fixed-scale decimals backed by an appropriate integer representation.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageFloat&amp;lt;/code&amp;gt;&lt;br /&gt;
| IEEE floating-point values.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageString&amp;lt;/code&amp;gt;&lt;br /&gt;
| Dictionary or buffer-based strings with specialized batch decoding.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StoragePrefix&amp;lt;/code&amp;gt;&lt;br /&gt;
| Prefix/suffix decomposition for strings where that representation is applicable; currently experimental for automatic selection.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;StorageEnum&amp;lt;/code&amp;gt;&lt;br /&gt;
| rANS entropy coding for suitable low-cardinality values.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;OverlayBlob&amp;lt;/code&amp;gt;&lt;br /&gt;
| External large binary/blob values layered over a base representation.&lt;br /&gt;
|-&lt;br /&gt;
| computed/cache proxy&lt;br /&gt;
| Values derived from other columns or populated on demand while retaining the column-reader contract.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Formats can be nested. For example, a decimal delegates its scaled integer payload to another storage, and string or sequence metadata can itself use compressed integer representations.&lt;br /&gt;
&lt;br /&gt;
== Batch execution and late materialization ==&lt;br /&gt;
&lt;br /&gt;
MemCP scan operators fetch filter columns first and process RecordIDs in batches. Only surviving IDs need map, join, or output columns. Consecutive survivors use &amp;lt;code&amp;gt;GetValueRange&amp;lt;/code&amp;gt;; ordered or index-derived ID lists use &amp;lt;code&amp;gt;GetValueMulti&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
This is late materialization: complete logical rows are assembled only at an edge that needs them. Filters, projections, aggregation, RecSet operations, and ordered scans can remain column-oriented in the hot path. It also avoids one interface call and one decoder restart per element.&lt;br /&gt;
&lt;br /&gt;
For supported hot expressions, a storage can emit native access code through &amp;lt;code&amp;gt;JITEmit&amp;lt;/code&amp;gt;. Unsupported JIT shapes retain the normal reader path and must preserve identical values.&lt;br /&gt;
&lt;br /&gt;
== Concurrency and locking ==&lt;br /&gt;
&lt;br /&gt;
A stable &amp;lt;code&amp;gt;ColumnStorage&amp;lt;/code&amp;gt; pointer can be read concurrently, but the shard structures that publish it are protected by the shard lock. Scan and planner code must obtain storages through helpers such as &amp;lt;code&amp;gt;getColumnStorageOrPanic&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ColumnReader&amp;lt;/code&amp;gt;, or their transaction-aware forms instead of reading the shard&#039;s column map directly.&lt;br /&gt;
&lt;br /&gt;
Read-only snapshots use the shard read lock; mutation, rebuild, log replay, delta changes, and index publication require the write lock and concurrency rights. Locks and rights must be released through panic-safe cleanup. Per-goroutine cached readers avoid a lock or mutable decoder shared inside the element loop.&lt;br /&gt;
&lt;br /&gt;
== Persistence and compatibility ==&lt;br /&gt;
&lt;br /&gt;
Every serialized column begins with a permanently assigned magic byte identifying its storage type. Most types then carry a layout-version byte. Binary layout changes must increment that version and retain all older deserializers so existing database files remain readable.&lt;br /&gt;
&lt;br /&gt;
Legacy magic bytes &amp;lt;code&amp;gt;1&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;2&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;13&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;40&amp;lt;/code&amp;gt; have no version byte. An incompatible change to one of those layouts requires a new magic byte; the legacy assignment remains a read-only reader forever. Magic values must never be renumbered or reused.&lt;br /&gt;
&lt;br /&gt;
Serialization compatibility is therefore part of the user-visible durability contract, not merely an internal implementation detail. See [[Persistency and Performance Guarantees]].&lt;br /&gt;
&lt;br /&gt;
== Measuring compression ==&lt;br /&gt;
&lt;br /&gt;
An early 55 MiB JSONL experiment produced the following observations. It mixed disk and RAM measurements and did not record schema, cardinalities, process baseline, engine mode, versions, warm-up or repeatability, so it is historical evidence—not a controlled MySQL comparison or a universal ratio.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Representation !! Reported size&lt;br /&gt;
|-&lt;br /&gt;
| MySQL InnoDB source || 55 MiB disk&lt;br /&gt;
|-&lt;br /&gt;
| JSONL export || 55 MiB disk&lt;br /&gt;
|-&lt;br /&gt;
| Imported maps in delta storage || 233 MiB RAM&lt;br /&gt;
|-&lt;br /&gt;
| Main storage using only &amp;lt;code&amp;gt;StorageSCMER&amp;lt;/code&amp;gt; || 81 MiB RAM&lt;br /&gt;
|-&lt;br /&gt;
| Integer columns using &amp;lt;code&amp;gt;StorageInt&amp;lt;/code&amp;gt; || 46 MiB RAM&lt;br /&gt;
|-&lt;br /&gt;
| String columns using &amp;lt;code&amp;gt;StorageString&amp;lt;/code&amp;gt; || 58 MiB RAM&lt;br /&gt;
|-&lt;br /&gt;
| Combined integer and string encodings || 23 MiB RAM&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A useful evaluation should report the source dataset and generator, schema and row count, per-column cardinality/range, selected storage formats, main/delta split, MemCP commit, ENGINE, process baseline, measured column sizes, indexes, and repeatable query timings. Compare equal logical data and distinguish allocated RAM, resident memory, serialized bytes, and external backend usage. See [[Performance Measurement]] and [[In-Memory Compression, Columnar Compression Techniques]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Advanced_SQL_Tutorial&amp;diff=379</id>
		<title>Advanced SQL Tutorial</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Advanced_SQL_Tutorial&amp;diff=379"/>
		<updated>2026-08-28T10:13:54Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Advanced SQL Tutorial =&lt;br /&gt;
&lt;br /&gt;
MemCP accepts MySQL-dialect SQL over the MySQL protocol and &amp;lt;code&amp;gt;/sql/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt;; PostgreSQL syntax is available through &amp;lt;code&amp;gt;/psql/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt;. The examples below assume a database selected by the connection or URL.&lt;br /&gt;
&lt;br /&gt;
This tutorial combines SQL techniques with the corresponding MemCP planner behavior. A described optimization is a possible physical choice, not a promise for every data distribution. Statistics, selectivity, indexes, ordering, row counts, and &amp;lt;code&amp;gt;LIMIT&amp;lt;/code&amp;gt; can change the selected plan.&lt;br /&gt;
&lt;br /&gt;
== Atomic counters through unique-key checks ==&lt;br /&gt;
&lt;br /&gt;
Consider a counter table whose key identifies the event or object being counted:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;CREATE TABLE counters (&lt;br /&gt;
    id INT PRIMARY KEY,&lt;br /&gt;
    cnt INT NOT NULL&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
INSERT INTO counters VALUES (1, 2), (2, 4);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The MySQL form can create a missing counter or increment an existing counter in one atomic statement:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;INSERT INTO counters VALUES (2, 1)&lt;br /&gt;
ON DUPLICATE KEY UPDATE cnt = cnt + VALUES(cnt);&lt;br /&gt;
&lt;br /&gt;
SELECT id, cnt FROM counters ORDER BY id;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! id&lt;br /&gt;
! cnt&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 2&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 5&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The primary key already supplies the required uniqueness check. The statement avoids a client-side read-modify-write sequence such as &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt; followed by &amp;lt;code&amp;gt;UPDATE&amp;lt;/code&amp;gt;, where another transaction could change the counter between both statements.&lt;br /&gt;
&lt;br /&gt;
The PostgreSQL-syntax endpoint provides the corresponding &amp;lt;code&amp;gt;ON CONFLICT&amp;lt;/code&amp;gt; form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;INSERT INTO counters VALUES (2, 1)&lt;br /&gt;
ON CONFLICT (id) DO UPDATE&lt;br /&gt;
SET cnt = cnt + excluded.cnt;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use an explicit transaction when several statements must succeed or fail as one unit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;BEGIN;&lt;br /&gt;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;&lt;br /&gt;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;&lt;br /&gt;
COMMIT;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
An atomic statement and a multi-statement transaction solve different problems: the upsert protects one logical write, while the transaction groups several dependent writes. See [[Transactions and Isolation]].&lt;br /&gt;
&lt;br /&gt;
== Joins, grouping, and windows ==&lt;br /&gt;
&lt;br /&gt;
The following query joins customers with their recent orders, aggregates revenue, and ranks the resulting groups:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT c.id,&lt;br /&gt;
       c.name,&lt;br /&gt;
       SUM(o.amount) AS total,&lt;br /&gt;
       RANK() OVER (ORDER BY SUM(o.amount) DESC) AS position&lt;br /&gt;
FROM customers AS c&lt;br /&gt;
JOIN orders AS o ON o.customer_id = c.id&lt;br /&gt;
WHERE o.created_at &amp;gt;= &#039;2026-01-01&#039;&lt;br /&gt;
GROUP BY c.id, c.name&lt;br /&gt;
HAVING SUM(o.amount) &amp;gt; 100&lt;br /&gt;
ORDER BY total DESC&lt;br /&gt;
LIMIT 20;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This shape gives the planner several opportunities: it can derive scan boundaries from the date predicate, reorder inner joins, fuse filtering and aggregation into a scan pipeline, and use ordering information to avoid unnecessary work for the final &amp;lt;code&amp;gt;LIMIT&amp;lt;/code&amp;gt;. Window expressions whose order-dependent result is reusable can be backed by an ordered-reduce computed column (ORC).&lt;br /&gt;
&lt;br /&gt;
== Subqueries and decorrelation ==&lt;br /&gt;
&lt;br /&gt;
MemCP supports &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt;, scalar subqueries, correlated subqueries, and derived tables. Supported correlated shapes are decorrelated into logical stages before physical planning; MemCP does not use a hidden per-outer-row scalar fallback.&lt;br /&gt;
&lt;br /&gt;
=== IN and EXISTS ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT o.id, o.amount&lt;br /&gt;
FROM orders AS o&lt;br /&gt;
WHERE o.customer_id IN (&lt;br /&gt;
    SELECT c.id&lt;br /&gt;
    FROM customers AS c&lt;br /&gt;
    WHERE c.active = 1&lt;br /&gt;
);&lt;br /&gt;
&lt;br /&gt;
SELECT p.id, p.name&lt;br /&gt;
FROM products AS p&lt;br /&gt;
WHERE EXISTS (&lt;br /&gt;
    SELECT 1&lt;br /&gt;
    FROM inventory AS i&lt;br /&gt;
    WHERE i.product_id = p.id&lt;br /&gt;
      AND i.quantity &amp;gt; 0&lt;br /&gt;
);&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After logical decorrelation, physical lowering can implement membership through a direct indexed probe, a prepared key table, or a query-local RecSet. The cost model compares preparation cost with the expected number of probes and downstream rows. SQL NULL and three-valued-logic rules remain decisive, especially for &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt;; a truth-only RecSet must not erase UNKNOWN results.&lt;br /&gt;
&lt;br /&gt;
=== Correlated scalar aggregate ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT c.id,&lt;br /&gt;
       c.name,&lt;br /&gt;
       (&lt;br /&gt;
           SELECT SUM(o.amount)&lt;br /&gt;
           FROM orders AS o&lt;br /&gt;
           WHERE o.customer_id = c.id&lt;br /&gt;
       ) AS total&lt;br /&gt;
FROM customers AS c&lt;br /&gt;
ORDER BY total DESC&lt;br /&gt;
LIMIT 20;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The correlated aggregate is represented as a decorrelated group stage. Depending on cardinality and reuse, physical lowering can choose direct probes, a prepared group cache keyed by &amp;lt;code&amp;gt;customer_id&amp;lt;/code&amp;gt;, or a RecSet-based carrier. Identical nested work can be shared instead of being planned independently for every occurrence.&lt;br /&gt;
&lt;br /&gt;
A scalar subquery returns NULL when no row matches and must reject a result with more than one row unless its shape, such as an aggregate, guarantees scalar cardinality.&lt;br /&gt;
&lt;br /&gt;
=== Derived tables and UNION ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;SELECT totals.customer_id, totals.total&lt;br /&gt;
FROM (&lt;br /&gt;
    SELECT customer_id, SUM(amount) AS total&lt;br /&gt;
    FROM orders&lt;br /&gt;
    GROUP BY customer_id&lt;br /&gt;
) AS totals&lt;br /&gt;
WHERE totals.total &amp;gt; 1000&lt;br /&gt;
ORDER BY totals.total DESC&lt;br /&gt;
LIMIT 10;&lt;br /&gt;
&lt;br /&gt;
SELECT customer_id, amount FROM current_orders&lt;br /&gt;
UNION ALL&lt;br /&gt;
SELECT customer_id, amount FROM archived_orders;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Derived tables and set-operation branches remain logical operators through decorrelation and join optimization. Projections that are not consumed by the outer query can be removed, while required ordering, grouping, distinctness, and limits remain explicit semantic boundaries.&lt;br /&gt;
&lt;br /&gt;
== Optimization forms used by MemCP ==&lt;br /&gt;
&lt;br /&gt;
MemCP separates logical optimization from physical lowering. Logical planning describes relational meaning with query blocks, group stages, and union blocks. Only after decorrelation and join reordering does physical lowering choose scans, indexes, RecSets, caches, computed columns, and executable pipelines.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Optimization&lt;br /&gt;
! What MemCP can do&lt;br /&gt;
! Useful diagnostic&lt;br /&gt;
|-&lt;br /&gt;
| Subquery decorrelation&lt;br /&gt;
| Convert supported correlated scalar, &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt; forms into joined logical stages; reuse equivalent stages and remove unused payloads.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN IR&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Join reordering&lt;br /&gt;
| Use selectivity and join connectivity to choose a driver and join order. Small connected join graphs can use exact DPHyp search; larger graphs use a bounded search strategy.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN REORDER&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Predicate and projection pushdown&lt;br /&gt;
| Apply filters near their source and delay or remove columns that are not yet required, reducing rows and materialized width.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN IR&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Adaptive access paths&lt;br /&gt;
| Choose direct scans or compatible equality, range, pattern, and ordering indexes. Index-building evidence is accumulated so tiny or rarely useful indexes are not built immediately.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| RecSet algebra&lt;br /&gt;
| Represent qualifying record IDs compactly and combine candidates using union, intersection, difference, and complement when SQL semantics permit it. The adaptive, shard-parallel implementation is described in [[RecSets]].&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Group caches&lt;br /&gt;
| Prepare keyed aggregate results once when repeated probes amortize the build cost; reuse maintained results when their dependencies remain valid.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| ORC columns&lt;br /&gt;
| Materialize reusable order-dependent reductions for supported window and ordered-computation shapes, with dependency-aware invalidation.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Pipeline fusion and late materialization&lt;br /&gt;
| Keep filter, projection, and aggregate work close to batched scans and assemble wide rows only when a downstream consumer needs them.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;EXPLAIN COMPILE&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Range-based braking&lt;br /&gt;
| For compatible &amp;lt;code&amp;gt;ORDER BY&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;LIMIT&amp;lt;/code&amp;gt; plans, stop ordered work when remaining keys cannot improve the requested top-k result. Defer expensive scalar projections until after a bounding limit when semantics allow it.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Parallel shard execution&lt;br /&gt;
| Execute sufficiently large independent shard batches in parallel while avoiding goroutine overhead for small work units.&lt;br /&gt;
| &amp;lt;code&amp;gt;EXPLAIN&amp;lt;/code&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
These optimizations preserve SQL semantics. Physical choices can change after data growth, auto-index creation, cache invalidation, or updated selectivity evidence.&lt;br /&gt;
&lt;br /&gt;
== Reading MemCP plans ==&lt;br /&gt;
&lt;br /&gt;
Both SQL syntax modes expose the planner phases:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;EXPLAIN SELECT ...;&lt;br /&gt;
EXPLAIN IR SELECT ...;&lt;br /&gt;
EXPLAIN REORDER SELECT ...;&lt;br /&gt;
EXPLAIN PHYSICAL SELECT ...;&lt;br /&gt;
EXPLAIN COMPILE SELECT ...;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN&amp;lt;/code&amp;gt; shows the optimized executable Scheme plan.&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN IR&amp;lt;/code&amp;gt; shows the decorrelated logical representation before physical artifacts are introduced.&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN REORDER&amp;lt;/code&amp;gt; shows the optimized logical order and its planning facts.&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt; shows physical decisions and the selected executable plan, including alternatives such as direct probes, RecSets, and prepared carriers.&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN COMPILE&amp;lt;/code&amp;gt; reports phase timings and plan-shape metrics for parsing, decorrelation, reordering, physical preparation, emission, and final optimization.&lt;br /&gt;
&lt;br /&gt;
For example, compare the phases of a selective ordered membership query:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;EXPLAIN IR&lt;br /&gt;
SELECT o.id&lt;br /&gt;
FROM orders AS o&lt;br /&gt;
WHERE EXISTS (&lt;br /&gt;
    SELECT 1&lt;br /&gt;
    FROM customers AS c&lt;br /&gt;
    WHERE c.id = o.customer_id&lt;br /&gt;
      AND c.active = 1&lt;br /&gt;
)&lt;br /&gt;
ORDER BY o.created_at DESC&lt;br /&gt;
LIMIT 10;&lt;br /&gt;
&lt;br /&gt;
EXPLAIN REORDER&lt;br /&gt;
SELECT o.id&lt;br /&gt;
FROM orders AS o&lt;br /&gt;
WHERE EXISTS (&lt;br /&gt;
    SELECT 1&lt;br /&gt;
    FROM customers AS c&lt;br /&gt;
    WHERE c.id = o.customer_id&lt;br /&gt;
      AND c.active = 1&lt;br /&gt;
)&lt;br /&gt;
ORDER BY o.created_at DESC&lt;br /&gt;
LIMIT 10;&lt;br /&gt;
&lt;br /&gt;
EXPLAIN PHYSICAL&lt;br /&gt;
SELECT o.id&lt;br /&gt;
FROM orders AS o&lt;br /&gt;
WHERE EXISTS (&lt;br /&gt;
    SELECT 1&lt;br /&gt;
    FROM customers AS c&lt;br /&gt;
    WHERE c.id = o.customer_id&lt;br /&gt;
      AND c.active = 1&lt;br /&gt;
)&lt;br /&gt;
ORDER BY o.created_at DESC&lt;br /&gt;
LIMIT 10;&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The logical output should contain decorrelated stages rather than parser subquery markers. The reordered output explains which relation drives the work. The physical output reveals whether current costs favor direct probes, a prepared membership carrier, an ordered index, or another valid scan source.&lt;br /&gt;
&lt;br /&gt;
Do not copy plan text as a permanent performance guarantee. Validate application-critical queries against the deployed commit, representative cardinalities, current indexes, and realistic parameter values. See [[Query Planner and Physical Lowering]], [[Data Auto Sharding and Auto Indexing]], [[Performance Measurement]], and [[Supported SQL]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Advanced_Graph_Querying&amp;diff=378</id>
		<title>Advanced Graph Querying</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Advanced_Graph_Querying&amp;diff=378"/>
		<updated>2026-08-28T10:13:54Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Advanced Graph Querying =&lt;br /&gt;
&lt;br /&gt;
MemCP exposes its tested SPARQL subset at &amp;lt;code&amp;gt;/rdf/&amp;amp;lt;database&amp;amp;gt;&amp;lt;/code&amp;gt;. Queries can combine triple patterns, FILTER expressions, OPTIONAL blocks, bindings, and supported update forms. Turtle data can be loaded through &amp;lt;code&amp;gt;/rdf/&amp;amp;lt;database&amp;amp;gt;/load_ttl&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT ?person ?name WHERE {&lt;br /&gt;
  ?person &amp;lt;http://xmlns.com/foaf/0.1/name&amp;gt; ?name .&lt;br /&gt;
  OPTIONAL { ?person &amp;lt;http://example.org/active&amp;gt; ?active . }&lt;br /&gt;
  FILTER(!BOUND(?active) || ?active = true)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Update templates include tested DELETE/INSERT/WHERE forms. RDF literals and IRIs must use the supported escaping rules; application input must not be concatenated into query text without validation.&lt;br /&gt;
&lt;br /&gt;
This page documents a tested subset, not complete SPARQL standard conformance or a separate general-purpose graph execution engine. Add successful and must-fail integration tests before advertising another construct. See [[Introduction to RDF]] and [[SQL over REST]].&lt;br /&gt;
&lt;br /&gt;
== Property-path roadmap ==&lt;br /&gt;
&lt;br /&gt;
SPARQL property paths remain a planned extension. The intended progression covers one-step alternatives/sequences, inverse paths, optional paths and transitive &amp;lt;code&amp;gt;*&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt; traversal. Recursive traversal needs explicit visited-set semantics, cancellation, bounds and a physical representation that does not repeatedly materialize the same nodes. Until tests and documentation say otherwise, do not assume property-path syntax is accepted.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Add_custom_SQL_operators_to_MemCP&amp;diff=377</id>
		<title>Add custom SQL operators to MemCP</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Add_custom_SQL_operators_to_MemCP&amp;diff=377"/>
		<updated>2026-08-28T10:13:54Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Add custom SQL operators to MemCP =&lt;br /&gt;
&lt;br /&gt;
Applications can expose their own Scheme functions as scalar SQL functions. The SQL parsers look up function names in the shared &amp;lt;code&amp;gt;sql_builtins&amp;lt;/code&amp;gt; registry and place the registered Scheme procedure directly into the generated query plan.&lt;br /&gt;
&lt;br /&gt;
== Register a Scheme function for SQL ==&lt;br /&gt;
&lt;br /&gt;
The smallest example adds one to its argument:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(sql_builtins &amp;quot;ADD_1&amp;quot; (lambda (x) (+ x 1)))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
After the module containing this declaration has been imported, the function is available in SQL:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT ADD_1(4) AS result;&lt;br /&gt;
-- result: 5&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SQL function names are normalized to upper case before lookup, so registry keys should conventionally be uppercase. The function may still be written as &amp;lt;code&amp;gt;add_1(...)&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Add_1(...)&amp;lt;/code&amp;gt;, or &amp;lt;code&amp;gt;ADD_1(...)&amp;lt;/code&amp;gt; in SQL.&lt;br /&gt;
&lt;br /&gt;
The declaration must run after &amp;lt;code&amp;gt;lib/sql-parser.scm&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;lib/sql-builtins.scm&amp;lt;/code&amp;gt; has created the shared registry. A custom application module loaded after &amp;lt;code&amp;gt;lib/main.scm&amp;lt;/code&amp;gt; is a suitable place:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* apps/my-sql-functions.scm */&lt;br /&gt;
(define sql_add_1 (lambda (x)&lt;br /&gt;
	(if (nil? x) nil (+ x 1))))&lt;br /&gt;
&lt;br /&gt;
(sql_builtins &amp;quot;ADD_1&amp;quot; sql_add_1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load the module when starting MemCP:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./memcp --api-port=4321 --mysql-port=3307 \&lt;br /&gt;
  lib/main.scm apps/my-sql-functions.scm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then test it through the HTTP frontend:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --fail-with-body -u root:strong-password \&lt;br /&gt;
  --data-binary &#039;SELECT ADD_1(4), ADD_1(NULL)&#039; \&lt;br /&gt;
  http://localhost:4321/sql/test&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Parameters, NULL, and result types ==&lt;br /&gt;
&lt;br /&gt;
The lambda parameter list defines the accepted arity. A three-argument function is registered in exactly the same way:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(sql_builtins &amp;quot;CLAMP&amp;quot; (lambda (value lower upper)&lt;br /&gt;
	(if (nil? value) nil&lt;br /&gt;
		(max lower (min upper value)))))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT CLAMP(12, 0, 10);  -- 10&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A custom function is responsible for its observable SQL behavior:&lt;br /&gt;
&lt;br /&gt;
* decide whether SQL &amp;lt;code&amp;gt;NULL&amp;lt;/code&amp;gt; propagates, produces a boolean, or has another documented meaning;&lt;br /&gt;
* return values that the SQL result encoder and surrounding expression understand;&lt;br /&gt;
* avoid hidden mutable state when the function can run inside parallel shard scans;&lt;br /&gt;
* do not perform I/O or database writes from a function advertised as a pure scalar expression;&lt;br /&gt;
* validate strings, lists, numbers, JSON values, and other dynamic Scheme inputs explicitly.&lt;br /&gt;
&lt;br /&gt;
The registry stores a Scheme procedure, not a complete SQL type declaration. Consequently, type and arity mistakes are normally detected when the generated plan is optimized or executed. Add successful and must-fail tests for NULLs, wrong arity, invalid types, boundary values, and both SQL syntax frontends where the function is intended to work.&lt;br /&gt;
&lt;br /&gt;
== Use an existing Scheme builtin ==&lt;br /&gt;
&lt;br /&gt;
An existing Scheme function can be exported without wrapping it:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(sql_builtins &amp;quot;MY_UNIX_TIMESTAMP&amp;quot; unix_timestamp)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aliases in &amp;lt;code&amp;gt;lib/sql-builtins.scm&amp;lt;/code&amp;gt; use this pattern extensively. A wrapper lambda is preferable when SQL needs different NULL handling, argument order, defaults, or result normalization.&lt;br /&gt;
&lt;br /&gt;
== Implement the underlying builtin in Go ==&lt;br /&gt;
&lt;br /&gt;
For hot functionality that cannot be expressed efficiently in Scheme, first declare a typed Scheme builtin in Go. The reduced pattern below follows the runtime&#039;s &amp;lt;code&amp;gt;Declaration&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TypeDescriptor&amp;lt;/code&amp;gt; API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DeclareInSection(&amp;quot;Arithmetic / Logic&amp;quot;, &amp;amp;Globalenv, &amp;amp;Declaration{&lt;br /&gt;
	Name: &amp;quot;add_1&amp;quot;,&lt;br /&gt;
	Desc: &amp;quot;adds one to an integer and propagates nil&amp;quot;,&lt;br /&gt;
	Fn: func(args ...Scmer) Scmer {&lt;br /&gt;
		if args[0].IsNil() {&lt;br /&gt;
			return NewNil()&lt;br /&gt;
		}&lt;br /&gt;
		return NewInt(args[0].Int() + 1)&lt;br /&gt;
	},&lt;br /&gt;
	Type: &amp;amp;TypeDescriptor{&lt;br /&gt;
		Params: []*TypeDescriptor{&lt;br /&gt;
			{Kind: &amp;quot;int&amp;quot;, ParamName: &amp;quot;value&amp;quot;, ParamDesc: &amp;quot;value to increment&amp;quot;},&lt;br /&gt;
		},&lt;br /&gt;
		Return: &amp;amp;TypeDescriptor{Kind: &amp;quot;int&amp;quot;},&lt;br /&gt;
		Const:  true,&lt;br /&gt;
	},&lt;br /&gt;
})&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;DeclareInSection&amp;lt;/code&amp;gt; to place a function in an existing generated API chapter. A new chapter starts with &amp;lt;code&amp;gt;DeclareTitle&amp;lt;/code&amp;gt; and ordinary &amp;lt;code&amp;gt;Declare&amp;lt;/code&amp;gt; calls. A new initializer must also be called from the runtime initialization sequence; merely adding a Go function does not register it.&lt;br /&gt;
&lt;br /&gt;
Set &amp;lt;code&amp;gt;Const&amp;lt;/code&amp;gt; only when repeated calls with the same arguments are deterministic, side-effect-free, and safe to constant-fold. Describe every parameter and return value so &amp;lt;code&amp;gt;make docs&amp;lt;/code&amp;gt; can generate a useful SCM reference. More advanced declarations can describe optional or variadic parameters, nested list/association types, ownership, optimizer hooks, and a native JIT emitter.&lt;br /&gt;
&lt;br /&gt;
After the Scheme builtin exists, expose it to SQL separately:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(sql_builtins &amp;quot;ADD_1&amp;quot; add_1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This separation is intentional: declaring a Scheme builtin makes it available to Scheme and generated plans, while registering it in &amp;lt;code&amp;gt;sql_builtins&amp;lt;/code&amp;gt; gives the SQL parser a function name.&lt;br /&gt;
&lt;br /&gt;
== Scalar functions versus new SQL syntax ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;sql_builtins&amp;lt;/code&amp;gt; is the right mechanism for ordinary calls such as &amp;lt;code&amp;gt;ADD_1(x)&amp;lt;/code&amp;gt;. Adding an infix operator, aggregate syntax, table-producing function, clause, or construct that changes relational cardinality requires parser and planner work as well. Such a change must preserve the boundary between parser AST, logical decorrelation/join ordering, and physical lowering described in [[Query Planner and Physical Lowering]].&lt;br /&gt;
&lt;br /&gt;
See [[Introduction to Scheme]], [[SCM Builtins]], [[Full SCM API documentation]], and [[Contributing]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Transactions_and_Isolation&amp;diff=376</id>
		<title>Transactions and Isolation</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Transactions_and_Isolation&amp;diff=376"/>
		<updated>2026-08-28T10:13:53Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Transactions and Isolation =&lt;br /&gt;
&lt;br /&gt;
Every SQL statement runs in an implicit transaction unless its session is already inside an explicit &amp;lt;code&amp;gt;BEGIN&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;COMMIT&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;ROLLBACK&amp;lt;/code&amp;gt; transaction. This provides statement-level error rollback without requiring every client to manage a transaction for a single statement.&lt;br /&gt;
&lt;br /&gt;
== Visibility and conflict handling ==&lt;br /&gt;
&lt;br /&gt;
The default cursor-stability mode applies writes with undo information, provides statement atomicity, and rolls changes back on errors. MemCP also contains an ACID path with snapshot visibility and optimistic conflict detection at commit. Savepoints are used internally for nested trigger and error recovery.&lt;br /&gt;
&lt;br /&gt;
Transaction state is tracked per shard. A read combines main rows, delta rows, insertion/deletion overlays, its transaction snapshot, and the active shard generation. Commit locks and publishes touched shards; rollback reverses staged or directly applied work. Nested shard work uses bounded fanout to avoid unbounded goroutines and lock cycles.&lt;br /&gt;
&lt;br /&gt;
Applications should test their actual contention patterns. MemCP does not claim every MySQL isolation level, XA, distributed transactions, or every locking clause. An unsupported guarantee should be treated as unsupported rather than inferred from accepted syntax.&lt;br /&gt;
&lt;br /&gt;
== Atomic write patterns ==&lt;br /&gt;
&lt;br /&gt;
Prefer one atomic SQL statement where possible. For example, an upsert counter avoids a client-side read/modify/write race:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
INSERT INTO counters (name, value) VALUES (&#039;jobs&#039;, 1)&lt;br /&gt;
ON DUPLICATE KEY UPDATE value = value + 1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Use an explicit transaction when several statements must succeed or fail as a unit. Keep it short: long transactions retain visibility state, increase conflict probability, and can delay maintenance.&lt;br /&gt;
&lt;br /&gt;
== Durability is a separate axis ==&lt;br /&gt;
&lt;br /&gt;
Isolation describes which concurrent changes a transaction observes; durability describes what survives a failure. For &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; tables, WAL synchronization occurs at commit. &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; writes WAL without fsync; &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; skip WAL durability. A transaction spanning tables inherits the guarantees and risks of every table ENGINE involved.&lt;br /&gt;
&lt;br /&gt;
See [[Advanced SQL Tutorial]], [[Persistency and Performance Guarantees]], [[Triggers]], and [[Supported SQL]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Storage_Backends&amp;diff=375</id>
		<title>Storage Backends</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Storage_Backends&amp;diff=375"/>
		<updated>2026-08-28T10:13:53Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;storage-backends&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Storage Backends =&lt;br /&gt;
&lt;br /&gt;
MemCP can persist a database on the local filesystem, S3-compatible object storage, or optional Ceph/RADOS. ENGINE durability semantics still apply on top of the selected backend.&lt;br /&gt;
&lt;br /&gt;
The local backend uses a directory below &amp;lt;code&amp;gt;-data&amp;lt;/code&amp;gt;. For S3 or Ceph, create a JSON database configuration in the data directory. An S3 configuration names endpoint, region, bucket, prefix, credentials, and optional path-style access. Ceph names cluster, user, pool, prefix, and optional config file.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;{&lt;br /&gt;
  &amp;quot;backend&amp;quot;: &amp;quot;s3&amp;quot;,&lt;br /&gt;
  &amp;quot;access_key_id&amp;quot;: &amp;quot;...&amp;quot;,&lt;br /&gt;
  &amp;quot;secret_access_key&amp;quot;: &amp;quot;...&amp;quot;,&lt;br /&gt;
  &amp;quot;region&amp;quot;: &amp;quot;us-east-1&amp;quot;,&lt;br /&gt;
  &amp;quot;endpoint&amp;quot;: &amp;quot;http://minio:9000&amp;quot;,&lt;br /&gt;
  &amp;quot;bucket&amp;quot;: &amp;quot;memcp&amp;quot;,&lt;br /&gt;
  &amp;quot;prefix&amp;quot;: &amp;quot;databases&amp;quot;,&lt;br /&gt;
  &amp;quot;force_path_style&amp;quot;: true&lt;br /&gt;
}&amp;lt;/pre&amp;gt;&lt;br /&gt;
Ceph is built with &amp;lt;code&amp;gt;make ceph&amp;lt;/code&amp;gt; and requires &amp;lt;code&amp;gt;librados-dev&amp;lt;/code&amp;gt;. Keep secrets outside version control and restrict config-file permissions. Test schema writes, column reload, WAL replay, listing/deletion, outage behavior, and backups against the actual service. Object storage latency affects cold reads, rebuilds, and WAL handling even though hot query execution is memory-oriented.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=RecSets&amp;diff=374</id>
		<title>RecSets</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=RecSets&amp;diff=374"/>
		<updated>2026-08-28T10:13:52Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= RecSets: compact, parallel record-set processing =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Verified against commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026.&#039;&#039;&#039; RecSets are an internal physical execution mechanism. Applications normally use SQL and let the optimizer choose them.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;&#039;RecSet&#039;&#039;&#039; is a query-local subset of one MemCP table. Instead of materializing complete rows, it records the physical record IDs that currently qualify. The result remains table-shaped: &amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_batch&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_order_multi&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;scan_exists&amp;lt;/code&amp;gt; can consume it as a source while retaining columnar reads, indexes, transaction visibility, and parallel shard execution.&lt;br /&gt;
&lt;br /&gt;
This separation is valuable on large relations. A cheap predicate can identify a narrow working set once; expensive residual predicates, correlated access checks, joins, projections, ordering, and aggregation then operate only on those candidates. Millions of base rows need not become millions of Scheme lists or wide temporary rows.&lt;br /&gt;
&lt;br /&gt;
== What a RecSet represents ==&lt;br /&gt;
&lt;br /&gt;
A RecSet contains membership, not result rows:&lt;br /&gt;
&lt;br /&gt;
* it belongs to exactly one base table and one transaction/visibility context;&lt;br /&gt;
* it has set semantics: no duplicates and no join multiplicity;&lt;br /&gt;
* it carries no result order;&lt;br /&gt;
* it is query-local and is neither persisted nor a stable public record-ID format;&lt;br /&gt;
* it can be an exact set of TRUE rows or a safe candidate superset followed by a residual predicate.&lt;br /&gt;
&lt;br /&gt;
The essential implementation is deliberately small:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
type recSet struct {&lt;br /&gt;
	tx     *TxContext&lt;br /&gt;
	table  *table&lt;br /&gt;
	shards []recSetShard&lt;br /&gt;
	count  int64&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
type recSetShard struct {&lt;br /&gt;
	shard    *storageShard&lt;br /&gt;
	kind     recSetRepresentation&lt;br /&gt;
	universe uint32&lt;br /&gt;
	data     []uint32&lt;br /&gt;
	used     uint32&lt;br /&gt;
	count    int64&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each shard owns its own record-ID universe. This mirrors MemCP&#039;s storage layout and makes construction and set algebra naturally parallel without sharing a global bitmap or exposing record IDs across shards.&lt;br /&gt;
&lt;br /&gt;
== Adaptive representation ==&lt;br /&gt;
&lt;br /&gt;
One fixed representation would waste memory for either sparse or dense sets. Every RecSet shard therefore chooses among three forms:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Representation !! Layout !! Best fit !! Membership and combination&lt;br /&gt;
|-&lt;br /&gt;
| Ranges || Sorted &amp;lt;code&amp;gt;(base, count)&amp;lt;/code&amp;gt; pairs || Long runs, full/empty shards, or a nearly full set with a few holes || Range lookup; linear range sweeps&lt;br /&gt;
|-&lt;br /&gt;
| Positive IDs || Sorted, deduplicated &amp;lt;code&amp;gt;uint32&amp;lt;/code&amp;gt; record IDs || A small, scattered result || Sorted membership lookup; linear list merge/intersection&lt;br /&gt;
|-&lt;br /&gt;
| Bitmap || One bit per record-ID position || Dense or highly fragmented membership || Direct bit test and word-wise Boolean operations&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
There is intentionally no separate “full”, “empty”, or negative representation. An empty shard is zero ranges; a full shard is one range; “everything except a few holes” is a small number of ranges. A fragmented set eventually becomes a bitmap.&lt;br /&gt;
&lt;br /&gt;
For orientation, an uncompressed bitmap for a one-million-position shard needs approximately 125&amp;amp;nbsp;kB. A positive-ID result uses four bytes per hit before slice overhead, and a range uses eight bytes per run. The builder chooses according to the observed shape rather than a SQL selectivity guess. Immutable search-index RecSets have an additional compressed form: their positive IDs and ranges can themselves use MemCP&#039;s packed integer storage, and their small interface can intersect a mutable query-local RecSet in place.&lt;br /&gt;
&lt;br /&gt;
=== One-pass adaptive construction ===&lt;br /&gt;
&lt;br /&gt;
The builder starts with ranges. More than three isolated singleton runs indicate sparse, non-clustered data and trigger conversion to a positive list. If the compact representation exceeds the bitmap budget, it escalates to a bitmap.&lt;br /&gt;
&lt;br /&gt;
The filter predicate is evaluated &#039;&#039;&#039;exactly once per candidate record ID&#039;&#039;&#039;. A representation change copies already collected IDs or ranges; it never repeats the scan or replays Scheme predicates. This matters because a predicate may include decoded column values, JIT/interpreter work, search-index checks, or an expensive correlated condition. After construction, range and positive results are copied into right-sized slices so a small result does not keep the worst-case bitmap allocation alive.&lt;br /&gt;
&lt;br /&gt;
Ranges are also split at the immutable-main/delta boundary. Consumers can then bulk-read a main-storage run without accidentally spanning into transaction deltas.&lt;br /&gt;
&lt;br /&gt;
== Building a RecSet in the scan/filter path ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;scan_recset&amp;lt;/code&amp;gt; uses the normal MemCP scan machinery rather than walking every row blindly:&lt;br /&gt;
&lt;br /&gt;
# extract equality, range, LIKE/search, computed, and RecSet boundaries from the filter;&lt;br /&gt;
# order useful boundaries and derive index limits;&lt;br /&gt;
# schedule eligible shards in parallel;&lt;br /&gt;
# prepare only the columns named by the filter and optimize its Scheme procedure;&lt;br /&gt;
# read index candidates in batches of up to 1,024 record IDs;&lt;br /&gt;
# apply transaction/deletion visibility and the residual predicate once;&lt;br /&gt;
# feed qualifying IDs to the adaptive shard builder.&lt;br /&gt;
&lt;br /&gt;
This keeps late materialization intact. Creating &amp;lt;code&amp;gt;WHERE tenant_id = 7 AND state = &#039;open&#039;&amp;lt;/code&amp;gt; as a RecSet needs the filter columns, but it does not have to decode payload, JSON, or text columns that are only required by a later projection.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(begin&lt;br /&gt;
	(define tx ((context &amp;quot;session&amp;quot;) &amp;quot;__memcp_tx&amp;quot;))&lt;br /&gt;
	(define orders (table &amp;quot;shop&amp;quot; &amp;quot;orders&amp;quot;))&lt;br /&gt;
	(define open_orders&lt;br /&gt;
		(scan_recset tx orders&lt;br /&gt;
			&#039;(&amp;quot;tenant_id&amp;quot; &amp;quot;state&amp;quot;)&lt;br /&gt;
			(lambda (tenant state)&lt;br /&gt;
				(and (equal? tenant 7) (equal? state &amp;quot;open&amp;quot;)))))&lt;br /&gt;
	(recset_count open_orders))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The low-level example illustrates the operator contract. SQL users should normally write the predicate in SQL and inspect the optimizer&#039;s decision with &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Narrowing an existing RecSet ===&lt;br /&gt;
&lt;br /&gt;
Passing a RecSet as the input of &amp;lt;code&amp;gt;scan_recset&amp;lt;/code&amp;gt; adds another condition without revisiting rows outside the existing membership:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(define recent_open&lt;br /&gt;
	(scan_recset tx open_orders&lt;br /&gt;
		&#039;(&amp;quot;created_at&amp;quot;)&lt;br /&gt;
		(lambda (created_at) (&amp;gt;= created_at cutoff))))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For a very sparse input, MemCP walks its IDs directly. For a broader input, it combines the exact RecSet boundary with other index/search boundaries before reading residual columns. This is the intended pattern for “cheap selective predicate first, expensive predicate second”, including ACL or search conditions with their own subscans.&lt;br /&gt;
&lt;br /&gt;
When scanning a RecSet, consecutive visible main-storage IDs are coalesced into runs. Each required column is fetched for the whole run with &amp;lt;code&amp;gt;GetValueRange&amp;lt;/code&amp;gt;; visibility remains row-specific, while column decoding becomes batched and cache-friendly. Delta rows use their transaction-aware delta path.&lt;br /&gt;
&lt;br /&gt;
== Membership inside another scan ==&lt;br /&gt;
&lt;br /&gt;
The pseudo-column &amp;lt;code&amp;gt;$recset_contains&amp;lt;/code&amp;gt; supplies a closure bound to the current row. It tests one or more same-table RecSets without exposing physical record IDs:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(scan tx orders&lt;br /&gt;
	&#039;(&amp;quot;$recset_contains&amp;quot; &amp;quot;total&amp;quot;)&lt;br /&gt;
	(lambda (contains total)&lt;br /&gt;
		(and (contains open_orders) (&amp;gt; total 1000)))&lt;br /&gt;
	&#039;(&amp;quot;id&amp;quot;)&lt;br /&gt;
	(lambda (id) id)&lt;br /&gt;
	(lambda (sum id) (+ sum id))&lt;br /&gt;
	0)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The closure caches the current RecSet and its shard entry, avoiding a repeated shard search for successive membership calls. If an exact RecSet boundary already proves the membership condition, the scan can provide an always-true closure instead of probing it again. Multiple &amp;lt;code&amp;gt;$recset_contains&amp;lt;/code&amp;gt; parameters are supported when a filter needs independent sets.&lt;br /&gt;
&lt;br /&gt;
== Set algebra, in parallel ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(define visible (recset_intersect (list tenant_rows active_rows)))&lt;br /&gt;
(define either  (recset_union (list starred_rows recent_rows)))&lt;br /&gt;
(define allowed (recset_difference (list visible blocked_rows muted_rows)))&lt;br /&gt;
(define other_visible_rows (recset_not visible))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Union, intersection, and difference require operands from the same table. Sorted range/list invariants allow linear two-pointer or N-way sweeps; bitmap pairs use word operations. Mixed representation pairs have specialized implementations instead of expanding everything into one common row list.&lt;br /&gt;
&lt;br /&gt;
Each shard combination is independent and runs through MemCP&#039;s bounded fan-out scheduler. Results are sorted back into deterministic shard order after parallel completion. This lets Boolean work over millions of record positions use available cores while keeping synchronization out of the inner membership loop.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;recset_not&amp;lt;/code&amp;gt; deserves special attention: it constructs the currently visible table universe and subtracts the input. It does not merely invert raw bits, because that could resurrect deleted rows or rows invisible to the transaction. At SQL level, a RecSet complement is also not automatically equivalent to &amp;lt;code&amp;gt;NOT predicate&amp;lt;/code&amp;gt; when NULL/UNKNOWN is possible.&lt;br /&gt;
&lt;br /&gt;
== Projecting membership through a join ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;recset_project_join&amp;lt;/code&amp;gt; reads distinct source keys from one RecSet and creates a RecSet over matching rows of another table. This is useful for EXISTS/IN carriers, ACL links, tags, and search-result relations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(define permitted_links&lt;br /&gt;
	(scan_recset tx access_links&lt;br /&gt;
		&#039;(&amp;quot;user_id&amp;quot;)&lt;br /&gt;
		(lambda (user_id) (equal? user_id current_user))))&lt;br /&gt;
&lt;br /&gt;
(define permitted_documents&lt;br /&gt;
	(recset_project_join tx permitted_links&lt;br /&gt;
		&#039;(&amp;quot;document_id&amp;quot;) documents &#039;(&amp;quot;id&amp;quot;)))&lt;br /&gt;
&lt;br /&gt;
(scan_order tx permitted_documents&lt;br /&gt;
	&#039;() (lambda () true)&lt;br /&gt;
	&#039;(&amp;quot;created_at&amp;quot; &amp;quot;id&amp;quot;) &#039;(&amp;lt; &amp;lt;)&lt;br /&gt;
	0 0 50&lt;br /&gt;
	&#039;(&amp;quot;id&amp;quot; &amp;quot;title&amp;quot;)&lt;br /&gt;
	(lambda (id title) (list id title))&lt;br /&gt;
	(lambda (rows row) (append rows (list row)))&lt;br /&gt;
	&#039;() false)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Composite source/target keys are supported. At execution time the operator knows the actual number of distinct source keys and target rows per shard. It chooses between indexed point probes and a dense target scan. A single integral key can use an O(1) hash membership test during the dense scan; generic composite keys use sorted tuples and binary lookup.&lt;br /&gt;
&lt;br /&gt;
The current cost constants were calibrated with production-shaped A/B fixtures. One recorded case projected about 80,000 integral keys through 1.84 million target rows in roughly 8&amp;amp;nbsp;ms on the calibration machine, while another case with 105 keys and 22 indexed target shards favored point probes. These are decision-model observations, &#039;&#039;&#039;not portable latency guarantees&#039;&#039;&#039;; hardware, encodings, shard layout, visibility state, and surrounding query work matter.&lt;br /&gt;
&lt;br /&gt;
For repeated scalar membership checks, &amp;lt;code&amp;gt;recset_key_index&amp;lt;/code&amp;gt; builds an immutable lookup closure over one or more columns:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(define contains_document&lt;br /&gt;
	(recset_key_index tx permitted_documents &#039;(&amp;quot;id&amp;quot;)))&lt;br /&gt;
&lt;br /&gt;
(contains_document 12345)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Ordering, LIMIT, and adaptive batches ==&lt;br /&gt;
&lt;br /&gt;
A RecSet itself is unordered. &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt; applies an index/order from the base table and intersects it with RecSet membership. Depending on cardinality, index span, and LIMIT, the execution kernel can:&lt;br /&gt;
&lt;br /&gt;
* drive the base ordered index and test RecSet membership;&lt;br /&gt;
* translate sparse RecSet IDs into ordered index positions and sort those positions;&lt;br /&gt;
* iterate the RecSet directly when no useful ordering is required.&lt;br /&gt;
&lt;br /&gt;
The crossover is calibrated by a benchmark with 800,000 rows, RecSet cardinalities from 16 to 720,000, bounded and unbounded scans, and both distributed and adversarial late hits. &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt; can report the adaptive RecSet boundary and runtime alternatives such as &amp;lt;code&amp;gt;ordered_inverse_recset&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;ordered_base_membership&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
For an ORDER BY/LIMIT query whose expensive acceptance condition lives on another relation, &amp;lt;code&amp;gt;scan_order_batch_accept&amp;lt;/code&amp;gt; preserves order without evaluating the whole candidate domain. It draws an initial ordered RecSet of &amp;lt;code&amp;gt;OFFSET + LIMIT&amp;lt;/code&amp;gt; candidates, asks a batch function to return an exact accepted subset, and doubles subsequent disjoint batches until enough rows are accepted or the source is exhausted. The accepted RecSet is used as a mask against the already ordered vector, so it is not rescanned in physical-ID order.&lt;br /&gt;
&lt;br /&gt;
This is especially useful for ordered document/search/ACL queries: project a candidate batch to the access relation, filter it in parallel, project accepted membership back, and stop once the requested page is complete.&lt;br /&gt;
&lt;br /&gt;
== How the optimizer uses RecSets ==&lt;br /&gt;
&lt;br /&gt;
RecSets appear only during physical lowering. The logical planner first establishes joins, domains, SQL truth semantics, grouping, ordering, and multiplicity. The physical cost model can then compare:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Choice !! Often attractive when&lt;br /&gt;
|-&lt;br /&gt;
| Direct indexed probe || The driving side is small and each lookup is selective.&lt;br /&gt;
|-&lt;br /&gt;
| RecSet carrier || A filtered domain is reused, projected, combined, or much narrower than the base relation.&lt;br /&gt;
|-&lt;br /&gt;
| Prepared key/group table || Keys or aggregate results need relational reuse and more than membership.&lt;br /&gt;
|-&lt;br /&gt;
| Dense fused scan || Most rows are visited once and building a reusable carrier would add work.&lt;br /&gt;
|-&lt;br /&gt;
| Ordered RecSet iterator || An existing membership domain must be consumed in base-table order or with a small LIMIT.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Candidate RecSets do not permit the optimizer to drop correctness checks. Approximate LIKE/full-text boundaries and other safe supersets retain their residual SQL predicate. Nullable &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; and general three-valued logic are handled before truth-only Boolean set identities are applied.&lt;br /&gt;
&lt;br /&gt;
Use these views when investigating a plan:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EXPLAIN IR SELECT ...;&lt;br /&gt;
EXPLAIN REORDER SELECT ...;&lt;br /&gt;
EXPLAIN PHYSICAL SELECT ...;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt; exposes membership-carrier choices and runtime access alternatives for projected and ordered RecSets. A remaining roadmap item is richer tracing for why the same RecSet domain was built or reused and for the exact ordered-iterator mode chosen at runtime.&lt;br /&gt;
&lt;br /&gt;
== Operational and correctness limits ==&lt;br /&gt;
&lt;br /&gt;
* Do not retain a RecSet as application state or persist its physical IDs.&lt;br /&gt;
* Algebra operands must refer to the same table; projected joins deliberately return a new target-table RecSet.&lt;br /&gt;
* A RecSet is tied to its transaction/visibility context. Batch-accept callbacks must return a same-table, same-transaction subset.&lt;br /&gt;
* Scanning a RecSet for reads is supported; mutation callbacks such as &amp;lt;code&amp;gt;$update&amp;lt;/code&amp;gt; are rejected on a RecSet source.&lt;br /&gt;
* Cancellation is checked before shard work is scheduled. Once entered, one shard&#039;s RecSet build runs atomically.&lt;br /&gt;
* Set cardinality is not SQL row cardinality after a one-to-many join, and membership does not retain duplicate keys.&lt;br /&gt;
* Ordered output needs &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt;; include a unique tie-breaker when stable pagination matters.&lt;br /&gt;
&lt;br /&gt;
== Low-level operator map ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Operator !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scan_recset&amp;lt;/code&amp;gt; || Build from a table or narrow an existing RecSet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;recset_count&amp;lt;/code&amp;gt; || Return stored membership cardinality.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;recset_union&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;recset_intersect&amp;lt;/code&amp;gt; || Combine same-table memberships.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;recset_difference&amp;lt;/code&amp;gt; / &amp;lt;code&amp;gt;recset_not&amp;lt;/code&amp;gt; || Subtract sets or complement against visible rows.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;recset_project_join&amp;lt;/code&amp;gt; || Project distinct keys into a target-table RecSet.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;recset_key_index&amp;lt;/code&amp;gt; || Build an immutable scalar/composite-key membership closure.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;$recset_contains&amp;lt;/code&amp;gt; || Test current-row membership inside a scan predicate.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scan_order_batch_accept&amp;lt;/code&amp;gt; || Filter progressively larger ordered candidate RecSets before LIMIT.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The generated [[Storage]] reference is authoritative for exact signatures. For the surrounding execution architecture see [[Scan]], [[Query Planner and Physical Lowering]], [[Columnar Storage]], [[Data Auto Sharding and Auto Indexing]], and [[Parallel Computing]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Query_Planner_and_Physical_Lowering&amp;diff=373</id>
		<title>Query Planner and Physical Lowering</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Query_Planner_and_Physical_Lowering&amp;diff=373"/>
		<updated>2026-08-28T10:13:52Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Query Planner and Physical Lowering =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Verified against commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026.&#039;&#039;&#039; Planner details can change between releases.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MemCP compiles SQL into executable Scheme code. It first establishes the relational meaning of a query, decorrelates supported subqueries, and selects a join order. Only then does physical lowering choose scans, indexes, RecSets, caches, computed columns, and storage representations. Keeping those phases separate prevents a storage shortcut from silently changing SQL semantics.&lt;br /&gt;
&lt;br /&gt;
== Planner pipeline ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SQL text&lt;br /&gt;
  -&amp;gt; MySQL or PostgreSQL parser AST&lt;br /&gt;
  -&amp;gt; normalize_sql_syntax&lt;br /&gt;
  -&amp;gt; decorrelate_logical_query / untangle_query&lt;br /&gt;
  -&amp;gt; predicate placement and join_reorder / optimize&lt;br /&gt;
  -&amp;gt; build_queryplan&lt;br /&gt;
  -&amp;gt; Scheme optimizer and optional native JIT&lt;br /&gt;
  -&amp;gt; storage-engine scans&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Phase !! Responsibility&lt;br /&gt;
|-&lt;br /&gt;
| Parser || Preserve SQL structure and produce neutral query terms.&lt;br /&gt;
|-&lt;br /&gt;
| Normalization || Remove frontend spelling differences and safe syntactic sugar while preserving three-valued logic.&lt;br /&gt;
|-&lt;br /&gt;
| Decorrelation || Replace dependent subqueries with explicit domains, stages, keys, and joins.&lt;br /&gt;
|-&lt;br /&gt;
| Logical optimization || Place predicates across proven-safe boundaries, estimate selectivity/cardinality, and choose the join tree.&lt;br /&gt;
|-&lt;br /&gt;
| Physical lowering || Select concrete scan sources and operators and emit Scheme code.&lt;br /&gt;
|-&lt;br /&gt;
| Scheme optimization/JIT || Optimize the functional program and compile supported hot procedures to native x86-64 code.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Physical artifacts such as &amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt;, RecSets, keytables, ORC columns, and temporary tables must not leak into logical planning. Conversely, physical lowering consumes the selected join tree; it must not flatten it and choose a second join order.&lt;br /&gt;
&lt;br /&gt;
== Logical operator model ==&lt;br /&gt;
&lt;br /&gt;
MemCP deliberately uses three broad logical shapes instead of splitting every clause into a long chain of tiny relational operators:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;query-block&amp;lt;/code&amp;gt; represents SELECT, JOIN, filtering, projection, ordering, LIMIT, and OFFSET;&lt;br /&gt;
* &amp;lt;code&amp;gt;group-stage&amp;lt;/code&amp;gt; represents grouping, aggregates, correlated domains, EXISTS/IN/scalar helpers, HAVING, and window partitions;&lt;br /&gt;
* &amp;lt;code&amp;gt;union-block&amp;lt;/code&amp;gt; represents &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UNION ALL&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
A &amp;lt;code&amp;gt;stage-output&amp;lt;/code&amp;gt; is a logical relation, not a physical table. This combined model lets the physical engine fuse filter, projection, and aggregation into one scan when their semantics and order requirements allow it.&lt;br /&gt;
&lt;br /&gt;
== Subquery decorrelation ==&lt;br /&gt;
&lt;br /&gt;
MemCP does not use “run the correlated subquery once per outer row” as a fallback. Supported correlated forms are transformed into relational stages; unsupported shapes fail explicitly.&lt;br /&gt;
&lt;br /&gt;
The simple path collects equality classes, chooses safe representatives, pulls expressions across valid boundaries, and turns trivial dependent joins into ordinary joins. If dependencies remain, the planner constructs Neumann&#039;s &#039;&#039;&#039;Domain D&#039;&#039;&#039;: the duplicate-free projection of the outer values actually read by the inner query. Domain keys pass through inner stages and join back to the outer result.&lt;br /&gt;
&lt;br /&gt;
Decorrelation must retain:&lt;br /&gt;
&lt;br /&gt;
* scalar-subquery cardinality, including an error when a single-row subquery returns a second row;&lt;br /&gt;
* SQL NULL behavior for &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt;;&lt;br /&gt;
* empty correlated aggregate groups, such as &amp;lt;code&amp;gt;COUNT = 0&amp;lt;/code&amp;gt; versus a nullable aggregate;&lt;br /&gt;
* outer-join null extension;&lt;br /&gt;
* ordering, LIMIT, and window requirements.&lt;br /&gt;
&lt;br /&gt;
== Join ordering ==&lt;br /&gt;
&lt;br /&gt;
After decorrelation exposes the complete join graph, &amp;lt;code&amp;gt;join_reorder&amp;lt;/code&amp;gt; uses relation cardinalities and predicate selectivities to select a tree. Exact DPHyp-style enumeration is available within a configurable budget; larger graphs use bounded strategies. Bushy trees are possible, and independent subtrees may execute in parallel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(settings &amp;quot;JoinReorderDPBudget&amp;quot;)&lt;br /&gt;
(settings &amp;quot;JoinReorderDPBudget&amp;quot; 256)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The physical engine may decide how to execute each selected join edge, but not which logical relation order the query means.&lt;br /&gt;
&lt;br /&gt;
== Cost-based physical lowering ==&lt;br /&gt;
&lt;br /&gt;
Physical lowering compares concrete ways to execute the already selected logical plan. Inputs include cardinality and distinct-count estimates, selectivity, scan and probe work, order compatibility, offset and LIMIT, available/adaptive indexes, group-cache state, expected reuse, build cost, memory, compilation cost, and collected telemetry.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Physical choice !! Typical purpose&lt;br /&gt;
|-&lt;br /&gt;
| Fused &amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt; || Unordered filtering, projection, and aggregation in one pass.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt; || Ordered access, top-k, offset/LIMIT ownership, or a bounded scalar probe.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scan_order_multi&amp;lt;/code&amp;gt; || Merge already ordered inputs, especially streamable &amp;lt;code&amp;gt;UNION ALL&amp;lt;/code&amp;gt; branches.&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;code&amp;gt;scan_exists&amp;lt;/code&amp;gt; || Stop after proving that a matching row exists.&lt;br /&gt;
|-&lt;br /&gt;
| Direct nested scan || Cheap selective probe driven by bound join keys.&lt;br /&gt;
|-&lt;br /&gt;
| RecSet || Query-local exact or candidate set of record IDs.&lt;br /&gt;
|-&lt;br /&gt;
| Group keytable/cache || Reusable grouped key domain and computed aggregate columns.&lt;br /&gt;
|-&lt;br /&gt;
| FK-backed computed column || Reuse a lookup or aggregate shaped by a foreign key.&lt;br /&gt;
|-&lt;br /&gt;
| ORC || Reusable order-dependent computation, including window dependencies.&lt;br /&gt;
|-&lt;br /&gt;
| Query-local temporary relation || Relational barrier when streaming and reusable representations do not fit.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Intermediate results remain storage-engine scan sources instead of becoming Scheme row lists. That preserves batch reads, indexing, statistics, range braking, late materialization, visibility, and bounded memory behavior.&lt;br /&gt;
&lt;br /&gt;
== RecSets and residual predicates ==&lt;br /&gt;
&lt;br /&gt;
A RecSet belongs to one base relation and visibility snapshot. It can contain the exact TRUE rows of a predicate or only a safe candidate superset. Candidate sets retain the original predicate as a residual filter. The storage engine supports sparse IDs and ranges plus union, intersection, complement, difference, and projection through join keys.&lt;br /&gt;
&lt;br /&gt;
The representation is adaptive per shard (ranges, sorted positive IDs, or bitmap), and construction, algebra, and join projection can run shard-parallel without materializing complete rows. See [[RecSets]] for the data structure, scan/filter pipeline, ordered iterators, join projection, cost decisions, and low-level examples.&lt;br /&gt;
&lt;br /&gt;
For truth-filtering contexts the planner can exploit &amp;lt;code&amp;gt;T(p OR q) = T(p) union T(q)&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;T(p AND q) = T(p) intersect T(q)&amp;lt;/code&amp;gt;. SQL three-valued logic remains authoritative: complementing TRUE rows is not generally SQL &amp;lt;code&amp;gt;NOT&amp;lt;/code&amp;gt;, and nullable &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; needs special handling.&lt;br /&gt;
&lt;br /&gt;
== LIMIT, UNION, and windows ==&lt;br /&gt;
&lt;br /&gt;
LIMIT belongs to a physical scan boundary, allowing scans to stop early instead of always materializing all matches. Ordered scans can use top-k thresholds and range braking when the next keys cannot improve the result.&lt;br /&gt;
&lt;br /&gt;
Unordered &amp;lt;code&amp;gt;UNION ALL&amp;lt;/code&amp;gt; can emit branches successively; &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; needs deduplication. Ordered streamable inputs can merge through &amp;lt;code&amp;gt;scan_order_multi&amp;lt;/code&amp;gt;; incompatible orders materialize only the narrow relation required by the barrier.&lt;br /&gt;
&lt;br /&gt;
A window expression does not automatically require a temporary table. If one order satisfies the base query and all partitions/orders, MemCP can fuse window work into that scan. Conflicting orders or shared order-dependent values can use a stage or ORC computed column.&lt;br /&gt;
&lt;br /&gt;
== Plan cache and guarded specialization ==&lt;br /&gt;
&lt;br /&gt;
The query-plan cache stores compiled Scheme formulas for normalized SQL shapes. A group cache is different: it is a reusable storage-engine relation. When parameters or statistics move the cost-model optimum, one cached SELECT can contain several guarded physical variants. A guard repeats cost comparisons; it does not scan data, build an index, or redo logical planning.&lt;br /&gt;
&lt;br /&gt;
== Inspecting optimizer decisions ==&lt;br /&gt;
&lt;br /&gt;
Both SQL frontends expose complementary views:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
EXPLAIN SELECT ...;&lt;br /&gt;
EXPLAIN IR SELECT ...;&lt;br /&gt;
EXPLAIN REORDER SELECT ...;&lt;br /&gt;
EXPLAIN PHYSICAL SELECT ...;&lt;br /&gt;
EXPLAIN COMPILE SELECT ...;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN&amp;lt;/code&amp;gt; shows the optimized executable Scheme plan;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN IR&amp;lt;/code&amp;gt; shows logical operators before physical emission;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN REORDER&amp;lt;/code&amp;gt; exposes join-order and selectivity information;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt; summarizes concrete access paths and reusable structures;&lt;br /&gt;
* &amp;lt;code&amp;gt;EXPLAIN COMPILE&amp;lt;/code&amp;gt; reports time spent parsing, planning, preparing, emitting, and optimizing.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(settings &amp;quot;ExplainWidth&amp;quot; 80)&lt;br /&gt;
(settings &amp;quot;ScanDebugging&amp;quot; true)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Correctness boundaries ==&lt;br /&gt;
&lt;br /&gt;
An unsupported planner shape should report a limitation. It must not silently discard residual predicates, turn an equijoin into a cross product, collapse SQL NULL semantics, replace scalar cardinality checks with &amp;lt;code&amp;gt;LIMIT 1&amp;lt;/code&amp;gt;, materialize an unbounded relation as a Scheme list, or introduce per-outer-row correlated execution.&lt;br /&gt;
&lt;br /&gt;
For practical query patterns see [[Advanced SQL Tutorial]]. Related internals are covered by [[RecSets]], [[Data Auto Sharding and Auto Indexing]], [[Temporary Computed Columns]], [[Columnar Storage]], [[Scan]], and [[Parallel Computing]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=JSON&amp;diff=372</id>
		<title>JSON</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=JSON&amp;diff=372"/>
		<updated>2026-08-28T10:13:52Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= JSON and SQL/JSON =&lt;br /&gt;
&lt;br /&gt;
MemCP supports native JSON values through a typed BSON-backed runtime representation. Both the MySQL and PostgreSQL syntax frontends expose constructors, path access, mutation, containment, aggregation, and relational expansion. JSON is useful for attributes whose shape genuinely varies; stable fields used for joins, constraints, or frequent filtering are often clearer as ordinary typed columns.&lt;br /&gt;
&lt;br /&gt;
== Creating and reading JSON ==&lt;br /&gt;
&lt;br /&gt;
MySQL-style constructors and paths include &amp;lt;code&amp;gt;JSON_OBJECT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JSON_ARRAY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JSON_EXTRACT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JSON_VALUE&amp;lt;/code&amp;gt;, and the &amp;lt;code&amp;gt;-&amp;amp;gt;&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;-&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt; operators.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT JSON_OBJECT(&#039;name&#039;, &#039;Ada&#039;, &#039;roles&#039;, JSON_ARRAY(&#039;admin&#039;, &#039;author&#039;));&lt;br /&gt;
SELECT profile-&amp;gt;&amp;gt;&#039;$.name&#039; AS name&lt;br /&gt;
FROM users&lt;br /&gt;
WHERE JSON_EXTRACT(profile, &#039;$.active&#039;) = true;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
PostgreSQL syntax supports &amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;jsonb&amp;lt;/code&amp;gt; casts and operators such as &amp;lt;code&amp;gt;-&amp;amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;-&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;#&amp;amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;#&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;@&amp;amp;gt;&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;&amp;amp;lt;@&amp;lt;/code&amp;gt;, together with PostgreSQL-style build and path functions.&lt;br /&gt;
&lt;br /&gt;
== Updating and aggregating ==&lt;br /&gt;
&lt;br /&gt;
Use &amp;lt;code&amp;gt;JSON_SET&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JSON_INSERT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JSON_REPLACE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;JSON_REMOVE&amp;lt;/code&amp;gt;, array mutation, or merge functions to produce an updated document. JSON values are immutable expressions: an UPDATE assigns the returned value back to the column.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UPDATE users&lt;br /&gt;
SET profile = JSON_SET(profile, &#039;$.last_login&#039;, CURRENT_TIMESTAMP)&lt;br /&gt;
WHERE id = 42;&lt;br /&gt;
&lt;br /&gt;
SELECT team_id, JSON_ARRAYAGG(name)&lt;br /&gt;
FROM users&lt;br /&gt;
GROUP BY team_id;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Object aggregates, &amp;lt;code&amp;gt;JSON_TABLE&amp;lt;/code&amp;gt;, PostgreSQL &amp;lt;code&amp;gt;json_array_elements&amp;lt;/code&amp;gt;, and object-key expansion turn documents into relational rows or collect rows into documents. Their exact accepted syntax differs between the MySQL and PostgreSQL endpoints; test queries against the selected frontend.&lt;br /&gt;
&lt;br /&gt;
== Indexing and compatibility ==&lt;br /&gt;
&lt;br /&gt;
Frequently used path expressions can participate in computed-expression optimization and adaptive indexing. Keep the path expression stable and inspect the physical plan with &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt;; an accepted JSON predicate does not by itself guarantee an index.&lt;br /&gt;
&lt;br /&gt;
JSON numbers, NULL, SQL NULL, missing paths, duplicate object keys, and scalar-versus-container results have compatibility-sensitive semantics. Validate them when migrating from MySQL or PostgreSQL. The executable regression suites &amp;lt;code&amp;gt;tests/sql/expressions/json-functions.yaml&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;postgresql-json-functions.yaml&amp;lt;/code&amp;gt; are the most precise inventory for the current commit.&lt;br /&gt;
&lt;br /&gt;
See [[Supported SQL]], [[Migration from MySQL and PostgreSQL]], [[SQL over REST]], and [[Data Auto Sharding and Auto Indexing]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Main_Page&amp;diff=370</id>
		<title>Main Page</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Main_Page&amp;diff=370"/>
		<updated>2026-08-28T09:59:42Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= MemCP Database – Fast, Compressed SQL for OLTP and OLAP =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:2.5rem 2rem; margin:0 0 1.5rem; border-radius:14px; background:linear-gradient(135deg,#3d6208 0%,#64910c 52%,#76b512 100%); color:#fff; text-align:center;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:2.6rem; line-height:1.1; font-weight:700; margin-bottom:.7rem;&amp;quot;&amp;gt;MemCP&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.45rem; line-height:1.35; font-weight:600; margin:0 auto .9rem; max-width:56rem;&amp;quot;&amp;gt;A fast, compressed, MySQL-protocol-compatible columnar database for modern OLTP and OLAP workloads&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.05rem; line-height:1.6; margin:0 auto 1.4rem; max-width:54rem;&amp;quot;&amp;gt;MemCP is an open-source SQL database written in Go. It combines persistent in-memory operation, adaptive column compression, parallel query execution and direct application APIs so operational data can be queried and analyzed without maintaining a separate analytical copy.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;margin-bottom:1.5rem;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block; padding:.2rem .65rem; margin:.15rem; border:1px solid #ffffff88; border-radius:1rem;&amp;quot;&amp;gt;Beta&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; padding:.2rem .65rem; margin:.15rem; border:1px solid #ffffff88; border-radius:1rem;&amp;quot;&amp;gt;Open Source&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; padding:.2rem .65rem; margin:.15rem; border:1px solid #ffffff88; border-radius:1rem;&amp;quot;&amp;gt;MySQL Protocol + HTTP APIs&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;plainlinks&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;display:inline-block; margin:.25rem;&amp;quot;&amp;gt;[[Install MemCP with Docker|&amp;lt;span style=&amp;quot;display:inline-block; padding:.65rem 1rem; border-radius:6px; background:#fff; color:#496f0c; font-weight:700;&amp;quot;&amp;gt;Get started with Docker&amp;lt;/span&amp;gt;]]&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; margin:.25rem;&amp;quot;&amp;gt;[[Supported SQL|&amp;lt;span style=&amp;quot;display:inline-block; padding:.65rem 1rem; border:1px solid #fff; border-radius:6px; color:#fff; font-weight:700;&amp;quot;&amp;gt;Explore SQL support&amp;lt;/span&amp;gt;]]&amp;lt;/span&amp;gt; &amp;lt;span style=&amp;quot;display:inline-block; margin:.25rem;&amp;quot;&amp;gt;[https://github.com/launix-de/memcp &amp;lt;span style=&amp;quot;display:inline-block; padding:.65rem 1rem; border:1px solid #fff; border-radius:6px; color:#fff; font-weight:700;&amp;quot;&amp;gt;View on GitHub&amp;lt;/span&amp;gt;]&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[File:Memcp-Load.png|center|frameless|1000px|alt=MemCP database dashboard and workload overview]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.85rem 1rem; margin:1rem 0 2rem; border-left:5px solid #d99b00; background:#fff7d6; color:#332600;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Development status: Beta.&#039;&#039;&#039; MemCP is under active development. Check [[Supported SQL]], [[Current Status and Open Issues]] and the durability requirements of your workload before migrating production data.&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.15rem; margin:1rem 0 2rem; border-left:5px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Your MySQL queries are too slow?&#039;&#039;&#039; Run the same representative workload on MemCP instead of assuming another index or a larger MySQL server is the only answer. Compare results, durability and authenticated end-to-end latency; if the migration gates pass, move the performance-critical workload to MemCP. [[MySQL is too slow|Start the MemCP performance evaluation →]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.15rem; margin:1rem 0 2rem; border:1px solid #b7c99a; border-radius:9px; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Observed performance profile:&#039;&#039;&#039; MemCP has achieved &#039;&#039;&#039;up to 10× the performance of MariaDB/PostgreSQL&#039;&#039;&#039; in OLAP and search-oriented workflows, where RecSets and compressed column scans avoid wide row materialization. Isolated OLTP paths currently take about &#039;&#039;&#039;1.3–2.0× as long&#039;&#039;&#039;, but in complete WordPress- and wiki-style page builds this has made &#039;&#039;&#039;no significant difference to overall page-loading time&#039;&#039;&#039; in the measured application workflows. Filtered-list queries over roughly one million documents, by contrast, have taken around &#039;&#039;&#039;30 seconds on PostgreSQL&#039;&#039;&#039;. These are workload observations, not universal guarantees; [[Performance Measurement|reproduce them on your data]].&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== What is MemCP? ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MemCP Database&#039;&#039;&#039; is a persistent, compressed, column-oriented SQL database for mixed OLTP and OLAP workloads. It speaks the MySQL client protocol, also exposes SQL over HTTP, and executes supported queries through a functional compiler and a parallel column-storage engine.&lt;br /&gt;
&lt;br /&gt;
The name on this site refers to the database project. MemCP Database is &#039;&#039;&#039;not&#039;&#039;&#039; a Model Context Protocol (MCP) memory server and is unrelated to the C/C++ &amp;lt;code&amp;gt;memcpy()&amp;lt;/code&amp;gt; memory-copy function. When writing about or linking to the project, the unambiguous name is &#039;&#039;&#039;MemCP Database&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== Problems MemCP solves ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:1rem; margin:1rem 0 2rem;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Slow filtered lists on millions of rows&amp;lt;/div&amp;gt;&lt;br /&gt;
Complex &amp;lt;code&amp;gt;WHERE&amp;lt;/code&amp;gt;, joins, membership tests, &amp;lt;code&amp;gt;ORDER BY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;LIMIT&amp;lt;/code&amp;gt; can make a row store inspect or materialize far more data than the page returns. MemCP uses RecSets, late materialization, adaptive indexes and ordered braking to keep the working domain compact.&amp;lt;br /&amp;gt;[[MySQL is too slow|Evaluate the query]] · [[RecSets|How RecSets work]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Slow GROUP BY, COUNT and dashboards&amp;lt;/div&amp;gt;&lt;br /&gt;
Column scans read only referenced compressed values. Parallel shard-local aggregation, group caches and computed structures target repeated analytical queries over fresh operational data.&amp;lt;br /&amp;gt;[[Columnar Storage]] · [[Temporary Computed Columns]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Slow database writes caused by fsync&amp;lt;/div&amp;gt;&lt;br /&gt;
Durability is selectable per table. &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; protects commits through power loss; &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; has measured about 10× its write throughput when process-crash recovery is sufficient.&amp;lt;br /&amp;gt;[[Persistency and Performance Guarantees|Choose a write strategy]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.1rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Database writes wear out an SD card&amp;lt;/div&amp;gt;&lt;br /&gt;
For reconstructible edge data, &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; avoids a continuous WAL and normally publishes one compressed generation every 15 minutes, reducing constant flash writes while making the loss window explicit.&amp;lt;br /&amp;gt;[[Hardware Requirements]] · [[Persistency and Performance Guarantees]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Choose your path ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:grid; grid-template-columns:repeat(auto-fit,minmax(220px,1fr)); gap:1rem; margin:1rem 0 2rem;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Evaluate MemCP&amp;lt;/div&amp;gt;&lt;br /&gt;
Understand the workload model, current status, hardware needs and differences from MySQL.&lt;br /&gt;
&lt;br /&gt;
[[What is OLTP and OLAP|OLTP and OLAP]] · [[Comparison: MemCP vs. MySQL|Compare with MySQL]] · [[Hardware Requirements|Hardware requirements]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Build an application&amp;lt;/div&amp;gt;&lt;br /&gt;
Use the MySQL protocol, SQL over HTTP, RDF or application-specific endpoints inside MemCP.&lt;br /&gt;
&lt;br /&gt;
[[Advanced SQL Tutorial|SQL tutorial]] · [[SQL over REST|SQL over HTTP]] · [[Database Tools compatibility with MemCP|Client tooling]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Operate MemCP&amp;lt;/div&amp;gt;&lt;br /&gt;
Plan deployment, migration, persistence, storage backends, settings and performance measurement.&lt;br /&gt;
&lt;br /&gt;
[[Deployment]] · [[Persistency and Performance Guarantees|Durability]] · [[Migration from MySQL and PostgreSQL|Migration]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:1rem 1.1rem; border:1px solid #b7c99a; border-radius:9px;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;font-size:1.15rem; font-weight:700; margin-bottom:.4rem;&amp;quot;&amp;gt;Understand and contribute&amp;lt;/div&amp;gt;&lt;br /&gt;
Explore the storage engine, optimizer, embedded Scheme runtime and project internals.&lt;br /&gt;
&lt;br /&gt;
[[Query Planner and Physical Lowering|Query planner]] · [[RecSets]] · [[Columnar Storage]] · [[Contributing]]&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Quickstart ==&lt;br /&gt;
&lt;br /&gt;
=== Run with Docker ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
docker run --name memcp \&lt;br /&gt;
  -e ROOT_PASSWORD=&#039;choose-a-password&#039; \&lt;br /&gt;
  -p 4321:4321 -p 3307:3307 \&lt;br /&gt;
  -v memcp-data:/data \&lt;br /&gt;
  carli2/memcp:latest&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then open &amp;lt;code&amp;gt;http://localhost:4321&amp;lt;/code&amp;gt; and connect a MySQL application to &amp;lt;code&amp;gt;127.0.0.1&amp;lt;/code&amp;gt; on port &#039;&#039;&#039;3307&#039;&#039;&#039;. The volume mounted at &amp;lt;code&amp;gt;/data&amp;lt;/code&amp;gt; retains persistent table data across container replacement. See [[Install MemCP with Docker|the complete Docker guide]] before deploying it as a service.&lt;br /&gt;
&lt;br /&gt;
=== Build from source ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone https://github.com/launix-de/memcp&lt;br /&gt;
cd memcp&lt;br /&gt;
go mod download&lt;br /&gt;
make&lt;br /&gt;
./memcp --api-port=4321 --mysql-port=3307 lib/main.scm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Connect with MySQL tooling:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
mysql -h 127.0.0.1 -u root -p -P 3307&lt;br /&gt;
# Enter the password selected for this data directory.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The development default for a fresh data directory is &amp;lt;code&amp;gt;admin&amp;lt;/code&amp;gt;. Change it before exposing MemCP to another machine. MemCP can also be supervised with PM2:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
pm2 start ./memcp --name memcp -- \&lt;br /&gt;
  --no-repl -data ./data --api-port=4321 --mysql-port=3307 lib/main.scm&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Background deployments must use &amp;lt;code&amp;gt;--no-repl&amp;lt;/code&amp;gt; so that closing standard input does not terminate the interactive console and stop the server. See [[Compile MemCP from Source|Build from Source]], [[Deployment]] and [[MemCP Console]].&lt;br /&gt;
&lt;br /&gt;
== Key features ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;display:grid; grid-template-columns:repeat(auto-fit,minmax(260px,1fr)); gap:.8rem; margin:1rem 0;&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;High performance&#039;&#039;&#039;&amp;lt;br /&amp;gt;Parallel, batch-oriented query execution is designed for multicore CPUs, compact working sets and fast persistent storage, serving both OLTP and OLAP workloads.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Columnar storage&#039;&#039;&#039;&amp;lt;br /&amp;gt;Data is stored by column for improved compression, a smaller memory footprint and fast analytical access.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Persistent in-memory operation&#039;&#039;&#039;&amp;lt;br /&amp;gt;MemCP is designed to keep active data in memory while offering configurable per-table durability and persistence backends.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Fast configurable writes&#039;&#039;&#039;&amp;lt;br /&amp;gt;Choose durability per table: &amp;lt;code&amp;gt;safe&amp;lt;/code&amp;gt; protects committed data through power loss, while measured &amp;lt;code&amp;gt;logged&amp;lt;/code&amp;gt; paths have reached about 10× its write throughput; &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; batches reconstructible data into the normal 15-minute rebuild cycle.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Built-in APIs&#039;&#039;&#039;&amp;lt;br /&amp;gt;SQL over HTTP and in-database services can remove an extra middleware hop for suitable applications.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Adaptive compression&#039;&#039;&#039;&amp;lt;br /&amp;gt;Bit-packing, dictionary encoding and sequence compression reduce the bytes read for suitable data. Historical imports have reached reductions around 80% versus their MySQL/MariaDB representation; measure your own schema.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Simple deployment&#039;&#039;&#039;&amp;lt;br /&amp;gt;Start with Docker, PM2 or the native binary. The compact application has historically had an installation footprint of approximately 10 MB.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #76b512; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Extensible frontends&#039;&#039;&#039;&amp;lt;br /&amp;gt;The Go storage engine and embedded Scheme environment support SQL, RDF, REST and custom application interfaces.&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div style=&amp;quot;padding:.9rem 1rem; border-top:4px solid #9ad32d; background:#f5f8f0; color:#17202a;&amp;quot;&amp;gt;&#039;&#039;&#039;Cost-based query execution&#039;&#039;&#039;&amp;lt;br /&amp;gt;Logical decorrelation and join optimization are separated from cost-based physical selection of scans, indexes, RecSets, reusable caches and execution pipelines.&amp;lt;br /&amp;gt;[[Query Planner and Physical Lowering|How MemCP plans and lowers queries →]] · [[RecSets|How compact record sets process large domains →]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Why MemCP? ==&lt;br /&gt;
&lt;br /&gt;
Traditional relational databases were designed around spinning disks and comparatively small numbers of CPU cores. MemCP rethinks storage and query execution for modern multicore systems, large caches, fast storage and mixed workloads.&lt;br /&gt;
&lt;br /&gt;
Typical use cases include:&lt;br /&gt;
&lt;br /&gt;
* real-time dashboards and analytics;&lt;br /&gt;
* data-heavy SaaS platforms;&lt;br /&gt;
* embedded systems with limited resources;&lt;br /&gt;
* high-throughput OLTP/OLAP hybrids.&lt;br /&gt;
&lt;br /&gt;
Whether MemCP is a good fit depends on the required SQL compatibility, durability, query mix, data size and operational environment. Review [[Supported SQL]], [[Persistency and Performance Guarantees]] and [[Performance Measurement]] rather than treating benchmark figures as universal guarantees.&lt;br /&gt;
&lt;br /&gt;
== MemCP vs. MySQL ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;width:100%;&amp;quot;&lt;br /&gt;
! Feature&lt;br /&gt;
! MySQL&lt;br /&gt;
! MemCP&lt;br /&gt;
|-&lt;br /&gt;
| Storage model&lt;br /&gt;
| Primarily row-based&lt;br /&gt;
| Column-based and compressed&lt;br /&gt;
|-&lt;br /&gt;
| Performance focus&lt;br /&gt;
| General-purpose relational workloads&lt;br /&gt;
| Parallel, in-memory-oriented execution for mixed operational and analytical workloads&lt;br /&gt;
|-&lt;br /&gt;
| In-memory capability&lt;br /&gt;
| Available through selected engines and caching&lt;br /&gt;
| Central design goal and default operating model&lt;br /&gt;
|-&lt;br /&gt;
| REST API integration&lt;br /&gt;
| Normally external&lt;br /&gt;
| Built in&lt;br /&gt;
|-&lt;br /&gt;
| Installation footprint&lt;br /&gt;
| Common server installations are approximately 150 MB or larger&lt;br /&gt;
| The native application has historically been approximately 10 MB&lt;br /&gt;
|-&lt;br /&gt;
| Open source&lt;br /&gt;
| ✅&lt;br /&gt;
| ✅&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MemCP provides MySQL protocol compatibility but does not claim to implement every MySQL feature. See [[Comparison: MemCP vs. MySQL]] for a detailed comparison and [[Database Tools compatibility with MemCP]] for client compatibility.&lt;br /&gt;
&lt;br /&gt;
== Architecture overview ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Tables, schemas and columns&#039;&#039;&#039;: Familiar SQL structures use a compressed columnar physical layout. See [[Databases, Tables and Columns]] and [[Columnar Storage]].&lt;br /&gt;
* &#039;&#039;&#039;Transaction model&#039;&#039;&#039;: Delta and main storage support mixed OLTP and OLAP semantics. See [[Transactions and Isolation]] and [[Shards, RecordIDs, Main Storage, Delta Storage]].&lt;br /&gt;
* &#039;&#039;&#039;Query planning&#039;&#039;&#039;: Logical optimization is separated from physical execution decisions. See [[Query Planner and Physical Lowering]].&lt;br /&gt;
* &#039;&#039;&#039;Persistence&#039;&#039;&#039;: Per-table durability can use filesystem, S3 or Ceph/RADOS storage. See [[Persistency and Performance Guarantees]] and [[Storage Backends]].&lt;br /&gt;
* &#039;&#039;&#039;Operations&#039;&#039;&#039;: The dashboard, metrics, process inspection and memory controls support day-to-day operation. See [[Dashboard and Operations]] and [[Memory Management and Eviction]].&lt;br /&gt;
* &#039;&#039;&#039;Scale-out roadmap&#039;&#039;&#039;: MemCP is single-node today. A leaderless CRUSH/RADOS and MOESI-inspired cluster design is planned, but must not be treated as an available production feature. See [[Cluster Monitor]].&lt;br /&gt;
* &#039;&#039;&#039;Frontends&#039;&#039;&#039;: MemCP provides multiple query and application interfaces:&lt;br /&gt;
** SQL through the MySQL wire protocol and SQL over HTTP;&lt;br /&gt;
** an RDF/graph query frontend;&lt;br /&gt;
** custom APIs through in-database web applications.&lt;br /&gt;
&lt;br /&gt;
== Documentation ==&lt;br /&gt;
&lt;br /&gt;
The following navigation remains on the start page so users and search engines can reach every major documentation area directly.&lt;br /&gt;
&lt;br /&gt;
=== Introduction and evaluation ===&lt;br /&gt;
&lt;br /&gt;
* [[What is OLTP and OLAP]]&lt;br /&gt;
* [[History of the MemCP project]]&lt;br /&gt;
* [[Hardware Requirements]]&lt;br /&gt;
* [[Persistency and Performance Guarantees]]&lt;br /&gt;
* [[Current Status and Open Issues]]&lt;br /&gt;
* [[MySQL is too slow|SQL performance problems MemCP solves]]&lt;br /&gt;
* [[Comparison: MemCP vs. MySQL]]&lt;br /&gt;
&lt;br /&gt;
=== Getting started ===&lt;br /&gt;
&lt;br /&gt;
* [[Install MemCP with Docker|Install with Docker]]&lt;br /&gt;
* [[With Singularity|Install with Singularity/Apptainer]]&lt;br /&gt;
* [[Compile MemCP from Source|Build from Source]]&lt;br /&gt;
* [[Contributing]]&lt;br /&gt;
* [[Introduction to Scheme]]&lt;br /&gt;
* [[Full SCM API documentation]]&lt;br /&gt;
&lt;br /&gt;
=== Administration ===&lt;br /&gt;
&lt;br /&gt;
* [[Deployment]]&lt;br /&gt;
* [[Migration from MySQL and PostgreSQL]]&lt;br /&gt;
* [[Settings]]&lt;br /&gt;
* [[Security and Authentication]]&lt;br /&gt;
* [[Dashboard and Operations]]&lt;br /&gt;
* [[Memory Management and Eviction]]&lt;br /&gt;
* [[Process Hibernation]]&lt;br /&gt;
* [[Performance Measurement]]&lt;br /&gt;
* [[MemCP Console]]&lt;br /&gt;
&lt;br /&gt;
=== Frontends ===&lt;br /&gt;
&lt;br /&gt;
==== SQL frontend ====&lt;br /&gt;
&lt;br /&gt;
* [[Supported SQL]]&lt;br /&gt;
* [[Advanced SQL Tutorial]]&lt;br /&gt;
* [[JSON|JSON and SQL/JSON]]&lt;br /&gt;
* [[Triggers]]&lt;br /&gt;
* [[SQL over REST]]&lt;br /&gt;
* [[Database Tools compatibility with MemCP|Supported Tooling]]&lt;br /&gt;
* [[Query Planner and Physical Lowering|How SQL operators are implemented]]&lt;br /&gt;
* [[Add custom SQL operators to MemCP]]&lt;br /&gt;
&lt;br /&gt;
==== RDF frontend ====&lt;br /&gt;
&lt;br /&gt;
* [[Introduction to RDF]]&lt;br /&gt;
* [[Advanced Graph Querying]]&lt;br /&gt;
* [https://github.com/launix-de/rdfop RDF browser and templating example]&lt;br /&gt;
&lt;br /&gt;
==== Custom frontends ====&lt;br /&gt;
&lt;br /&gt;
* [[In-Database WebApps and REST Services]]&lt;br /&gt;
* [[MemCP for Microservices]]&lt;br /&gt;
* [[Websockets in MemCP]]&lt;br /&gt;
&lt;br /&gt;
=== Persistence backends and storage ===&lt;br /&gt;
&lt;br /&gt;
* [[File System]]&lt;br /&gt;
* [[Storage Backends|S3-compatible and Ceph/RADOS storage]]&lt;br /&gt;
* [[Cluster Monitor]]&lt;br /&gt;
&lt;br /&gt;
=== Internals ===&lt;br /&gt;
&lt;br /&gt;
==== How MemCP works ====&lt;br /&gt;
&lt;br /&gt;
* [[Databases, Tables and Columns]]&lt;br /&gt;
* [[Shards, RecordIDs, Main Storage, Delta Storage]]&lt;br /&gt;
* [[Columnar Storage]]&lt;br /&gt;
* [[Transactions and Isolation]]&lt;br /&gt;
* [[Query Planner and Physical Lowering]]&lt;br /&gt;
* [[Full SCM API documentation]]&lt;br /&gt;
&lt;br /&gt;
==== Scheme documentation ====&lt;br /&gt;
&lt;br /&gt;
* [[SCM Builtins]]&lt;br /&gt;
* [[Arithmetic / Logic]]&lt;br /&gt;
* [[Strings]]&lt;br /&gt;
* [[Streams]]&lt;br /&gt;
* [[Lists]]&lt;br /&gt;
* [[Associative Lists / Dictionaries]]&lt;br /&gt;
* [[Date]]&lt;br /&gt;
* [[Vectors]]&lt;br /&gt;
* [[Parsers]]&lt;br /&gt;
* [[Sync]]&lt;br /&gt;
* [[IO]]&lt;br /&gt;
* [[Storage]]&lt;br /&gt;
&lt;br /&gt;
==== Optimizations ====&lt;br /&gt;
&lt;br /&gt;
* [[Query Planner and Physical Lowering]]&lt;br /&gt;
* [[In-Memory Compression, Columnar Compression Techniques]]&lt;br /&gt;
* [[Temporary Computed Columns]]&lt;br /&gt;
* [[Data Auto Sharding and Auto Indexing]]&lt;br /&gt;
* [[Parallel Computing]]&lt;br /&gt;
&lt;br /&gt;
== Further reading ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/launix-de/memcp MemCP on GitHub]&lt;br /&gt;
* [https://www.vldb.org/pvldb/vol13/p2649-boncz.pdf VLDB Research Paper]&lt;br /&gt;
* [https://cs.emis.de/LNI/Proceedings/Proceedings241/383.pdf LNI Proceedings Paper]&lt;br /&gt;
* [https://www.dcs.bbk.ac.uk/~dell/teaching/cc/paper/sigmod10/p135-malewicz.pdf Large Graph Algorithms]&lt;br /&gt;
&lt;br /&gt;
Additional blog posts on design decisions, compression techniques and performance optimization are available on the [https://launix.de/launix/ Launix blog].&lt;br /&gt;
&lt;br /&gt;
== Community ==&lt;br /&gt;
&lt;br /&gt;
MemCP is an open-source project maintained by developers for developers. Contributions are welcome in the form of bug reports, feature requests and pull requests.&lt;br /&gt;
&lt;br /&gt;
See [[Contributing]] and the [https://github.com/launix-de/memcp GitHub repository].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Auto_Sharding&amp;diff=369</id>
		<title>Auto Sharding</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Auto_Sharding&amp;diff=369"/>
		<updated>2026-08-28T09:59:41Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Data Auto Sharding and Auto Indexing]]&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=With_Singularity&amp;diff=368</id>
		<title>With Singularity</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=With_Singularity&amp;diff=368"/>
		<updated>2026-08-28T09:59:41Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Run MemCP with Singularity/Apptainer =&lt;br /&gt;
&lt;br /&gt;
Build the repository-provided image target:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;bash&amp;quot;&amp;gt;&lt;br /&gt;
git clone https://github.com/launix-de/memcp&lt;br /&gt;
cd memcp&lt;br /&gt;
make memcp.sif&lt;br /&gt;
apptainer run memcp.sif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bind a persistent host directory to the container data path and expose or forward the HTTP/MySQL ports according to the local Apptainer installation. Set a strong initial root password for a fresh data directory and keep the image, application modules, and data directory versions together during upgrades.&lt;br /&gt;
&lt;br /&gt;
Singularity installations can use the corresponding &amp;lt;code&amp;gt;singularity&amp;lt;/code&amp;gt; command. See [[Deployment]], [[Persistency and Performance Guarantees]], and [[Security and Authentication]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=What_is_OLTP_and_OLAP&amp;diff=367</id>
		<title>What is OLTP and OLAP</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=What_is_OLTP_and_OLAP&amp;diff=367"/>
		<updated>2026-08-28T09:59:41Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= What is OLTP and OLAP? =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OLTP&#039;&#039;&#039; describes operational workloads with frequent inserts, updates, deletes, point lookups, constraints, and short transactions. &#039;&#039;&#039;OLAP&#039;&#039;&#039; describes analytical workloads that scan, group, join, and aggregate larger portions of a dataset. Real applications commonly mix both.&lt;br /&gt;
&lt;br /&gt;
Row storage can favor whole-record access; column storage can reduce memory traffic when a query uses only a few attributes. Neither layout alone determines whether a system can provide transactions, durability, or good point lookup performance.&lt;br /&gt;
&lt;br /&gt;
MemCP targets mixed workloads. Delta structures, indexes, constraints, and transaction machinery serve operational writes, while compressed columns, batch/parallel scans, and reusable computed relations serve analytical queries. Persistent cold columns may be evicted and reloaded, so workload behavior also depends on memory budget and storage backend.&lt;br /&gt;
&lt;br /&gt;
== Typical query shapes ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Workload !! Typical operations !! Important properties&lt;br /&gt;
|-&lt;br /&gt;
| OLTP || create an order, update inventory, look up one account, enforce unique/foreign keys || short latency, concurrency, atomicity, durability, selective indexes&lt;br /&gt;
|-&lt;br /&gt;
| OLAP || revenue by month/region, cohort analysis, wide joins, windows, top-k reports || batch scans, compression, parallelism, grouping, ordering, memory bandwidth&lt;br /&gt;
|-&lt;br /&gt;
| Hybrid/HTAP || ingest events while dashboards aggregate the latest state || consistent visibility between writes and scans, predictable maintenance, no stale export pipeline&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Combining both in MemCP ==&lt;br /&gt;
&lt;br /&gt;
New writes land in delta state suited to change, while rebuilt main columns use an encoding chosen from their values. Scans combine both under transaction visibility. The planner can use selective indexes for point access and compressed batch pipelines for analytical work, and table ENGINE choice separates durability requirements from physical query layout.&lt;br /&gt;
&lt;br /&gt;
That does not make every mixed workload free of trade-offs. High-contention writes, a hot set larger than RAM budget, long-running snapshots, frequent rebuilds, or analytical queries touching nearly every column can interfere with operational latency. Measure them concurrently, not as isolated best cases.&lt;br /&gt;
&lt;br /&gt;
Whether one MemCP instance is suitable depends on isolation, durability, SQL compatibility, query mix, hot-set size, recovery needs, and measured performance. See [[Transactions and Isolation]], [[Persistency and Performance Guarantees]], and [[Performance Measurement]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Websockets_in_MemCP&amp;diff=366</id>
		<title>Websockets in MemCP</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Websockets_in_MemCP&amp;diff=366"/>
		<updated>2026-08-28T09:59:40Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Websockets in MemCP =&lt;br /&gt;
&lt;br /&gt;
An embedded HTTP handler can upgrade a request through the response object&#039;s WebSocket facility and receive messages through a callback. The &amp;lt;code&amp;gt;apps/minigame.scm&amp;lt;/code&amp;gt; example in the repository demonstrates the current API and routing pattern.&lt;br /&gt;
&lt;br /&gt;
WebSockets keep one bidirectional connection open for live dashboards, notifications, collaborative state, games, or change feeds. They are a delivery channel, not a durable message queue: reconnect, replay, acknowledgement, ordering, and missed-message semantics belong to the application.&lt;br /&gt;
&lt;br /&gt;
== Server-side upgrade ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;scheme&amp;quot;&amp;gt;&lt;br /&gt;
(set send ((res &amp;quot;websocket&amp;quot;)&lt;br /&gt;
	(lambda (message) (print &amp;quot;message: &amp;quot; message))&lt;br /&gt;
	(lambda () (print &amp;quot;connection closed&amp;quot;))))&lt;br /&gt;
(send 1 &amp;quot;Hello from MemCP&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The numeric first argument is the WebSocket frame opcode used by the current response API. Keep the sending function only for the connection lifetime.&lt;br /&gt;
&lt;br /&gt;
A browser client can connect to the routed endpoint with the standard API:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const socket = new WebSocket(&amp;quot;wss://example.test/minigame/ws&amp;quot;);&lt;br /&gt;
socket.addEventListener(&amp;quot;open&amp;quot;, () =&amp;gt; socket.send(JSON.stringify({type: &amp;quot;hello&amp;quot;})));&lt;br /&gt;
socket.addEventListener(&amp;quot;message&amp;quot;, event =&amp;gt; console.log(JSON.parse(event.data)));&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Complete routed example ==&lt;br /&gt;
&lt;br /&gt;
The repository&#039;s &amp;lt;code&amp;gt;apps/minigame.scm&amp;lt;/code&amp;gt; shows the complete routing pattern: preserve the previous handler, serve an HTML/JavaScript client below one prefix, and upgrade only the WebSocket path.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;scheme&amp;quot;&amp;gt;&lt;br /&gt;
(define http_handler (begin&lt;br /&gt;
	(set old_handler http_handler)&lt;br /&gt;
	(lambda (req res) (begin&lt;br /&gt;
		(match (req &amp;quot;path&amp;quot;)&lt;br /&gt;
			&amp;quot;/minigame/ws&amp;quot; (begin&lt;br /&gt;
				(set send ((res &amp;quot;websocket&amp;quot;)&lt;br /&gt;
					(lambda (message) (begin&lt;br /&gt;
						(print &amp;quot;message: &amp;quot; message)&lt;br /&gt;
						(send 1 (concat &amp;quot;echo: &amp;quot; message))))))&lt;br /&gt;
				(send 1 &amp;quot;Hello from MemCP&amp;quot;))&lt;br /&gt;
			(regex &amp;quot;^/minigame/(.*)$&amp;quot; path asset) (begin&lt;br /&gt;
				((res &amp;quot;header&amp;quot;) &amp;quot;Content-Type&amp;quot; &amp;quot;text/plain&amp;quot;)&lt;br /&gt;
				((res &amp;quot;status&amp;quot;) 200)&lt;br /&gt;
				((res &amp;quot;print&amp;quot;) &amp;quot;WebSocket client assets belong here&amp;quot;))&lt;br /&gt;
			(old_handler req res))))))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When this module is imported by &amp;lt;code&amp;gt;lib/main.scm&amp;lt;/code&amp;gt;, the existing server uses the wrapped handler. A standalone application can call &amp;lt;code&amp;gt;serve&amp;lt;/code&amp;gt; explicitly. Keep the receive callback and its connection-local &amp;lt;code&amp;gt;send&amp;lt;/code&amp;gt; closure together; never store that closure after close.&lt;br /&gt;
&lt;br /&gt;
Prefer JSON messages with an explicit type and version. Validate the decoded shape before reading fields, cap message size, and define how the client resubscribes or resumes after reconnect.&lt;br /&gt;
&lt;br /&gt;
== Database-backed publish/subscribe ==&lt;br /&gt;
&lt;br /&gt;
Prepare fixed queries during module startup, create a session per connection, and bind authenticated identity and subscription state there. A receive callback can update state atomically; query results can be emitted through &amp;lt;code&amp;gt;send&amp;lt;/code&amp;gt;. On close, release subscriptions and other references so they do not keep sessions or sending functions alive.&lt;br /&gt;
&lt;br /&gt;
For fan-out, use bounded per-client queues and a policy for slow consumers (drop/coalesce messages or disconnect). A database table can persist events for replay, but a &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; table cannot provide durable delivery after restart.&lt;br /&gt;
&lt;br /&gt;
The earlier hardlife.io example used this structure at larger scale: prepare position-update, listener-membership and dirty-list queries once; authenticate a player handle with a message authentication code; keep the connection&#039;s player/location state in a session; mark affected listeners dirty after a position change; send only changed avatars; and remove listener state on disconnect. The complete historical listing coupled credentials, global &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; defaults and application-specific tables, so reproducing it as a copy-and-paste server would be unsafe. The pipeline remains a useful design example.&lt;br /&gt;
&lt;br /&gt;
Hosting the handler beside the database removes an application/database socket hop and repeated parsing for prepared shapes. That is a performance opportunity, not proof that every embedded WebSocket service is faster than a separate Node.js or Go service; benchmark the authenticated end-to-end path and account for the shared failure domain.&lt;br /&gt;
&lt;br /&gt;
== Production considerations ==&lt;br /&gt;
&lt;br /&gt;
Authenticate the upgrade, validate browser Origin, limit message and queue sizes, apply backpressure, and remove subscriptions when the connection closes. A slow client must not create an unbounded in-memory backlog. Long database operations should observe cancellation. Use TLS at a trusted proxy or transport layer and do not expose default credentials.&lt;br /&gt;
&lt;br /&gt;
Storage ENGINE choice is independent of WebSocket delivery: &amp;lt;code&amp;gt;sloppy&amp;lt;/code&amp;gt; can lose recent writes, and &amp;lt;code&amp;gt;memory&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;cache&amp;lt;/code&amp;gt; are not durable. See [[In-Database WebApps and REST Services]] and [[Persistency and Performance Guarantees]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Vectors&amp;diff=365</id>
		<title>Vectors</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Vectors&amp;diff=365"/>
		<updated>2026-08-28T09:59:40Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;vectors&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Vectors =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Generated from MemCP c42e19eba on 2026-08-27; do not edit manually. --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&amp;gt;Generated from MemCP commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. See [[Full SCM API documentation]].&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Vectors&#039;&#039;&#039; module treats numeric lists as vectors. Its current public primitive, &amp;lt;code&amp;gt;dot&amp;lt;/code&amp;gt;, supports a normal dot product plus modes named &amp;lt;code&amp;gt;COSINE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;EUCLIDEAN&amp;lt;/code&amp;gt;. Vector functions are useful for scoring and mathematical expressions but do not by themselves provide storage, dimensional validation, or an approximate-nearest-neighbor index.&lt;br /&gt;
&lt;br /&gt;
The implementation processes only positions present in both input lists. Callers must therefore validate equal dimensions when that is part of the data contract. In commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;EUCLIDEAN&amp;lt;/code&amp;gt; returns the square root of the accumulated pairwise products; this is &#039;&#039;&#039;not&#039;&#039;&#039; the standard Euclidean distance &amp;lt;code&amp;gt;sqrt(sum((a-b)^2))&amp;lt;/code&amp;gt;. Do not use that mode as a distance metric without accounting for this compatibility behavior.&lt;br /&gt;
&lt;br /&gt;
== dot ==&lt;br /&gt;
&lt;br /&gt;
produced the dot product&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;v1&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): vector1&lt;br /&gt;
* &#039;&#039;&#039;v2&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): vector2&lt;br /&gt;
* &#039;&#039;&#039;mode&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): DOT, COSINE, EUCLIDEAN, default is DOT &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Triggers&amp;diff=364</id>
		<title>Triggers</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Triggers&amp;diff=364"/>
		<updated>2026-08-28T09:59:40Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
= Triggers =&lt;br /&gt;
&lt;br /&gt;
MemCP supports persistent BEFORE and AFTER triggers for INSERT, UPDATE, and DELETE. Trigger bodies can read &amp;lt;code&amp;gt;OLD&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NEW&amp;lt;/code&amp;gt;, assign permitted &amp;lt;code&amp;gt;NEW&amp;lt;/code&amp;gt; values, run conditional BEGIN/END bodies, and execute supported DML including &amp;lt;code&amp;gt;INSERT … SELECT&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Multiple triggers execute by registered priority. AFTER work may be configured as asynchronous, in which case its completion and failure are not identical to the originating statement&#039;s synchronous path. Trigger changes participate in transaction/savepoint recovery.&lt;br /&gt;
&lt;br /&gt;
MemCP also uses hidden system triggers to enforce constraints and maintain computed columns, group caches, prejoins, and invalidation dependencies. [[Temporary Computed Columns]] explains how the storage engine analyzes generated Scheme computors and derives incremental, selective, or complete invalidation triggers automatically. User DROP/CASCADE behavior must not delete unrelated data; lifecycle callbacks are not general garbage collectors.&lt;br /&gt;
&lt;br /&gt;
Test trigger persistence across restart, multi-row statements, NULL/default handling, errors, ordering, cross-table writes, and rollback. Recursive trigger graphs should be treated with particular care.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Temporary_Computed_Columns&amp;diff=363</id>
		<title>Temporary Computed Columns</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Temporary_Computed_Columns&amp;diff=363"/>
		<updated>2026-08-28T09:59:39Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;computed-columns-group-caches-and-orc&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Computed Columns, Group Caches, and ORC =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;&#039;&#039;&#039;Verified against commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 28 August 2026.&#039;&#039;&#039; These are optimizer-managed physical structures. Applications normally write SQL; MemCP analyzes the plan, creates suitable caches, and maintains their validity automatically.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MemCP reuses expensive expressions and relational stages without copying complete result rows into a generic temporary table. It can attach one computed value to an existing base row, keep a narrow table of grouping keys and aggregates, or maintain an order-dependent column. The surrounding base columns remain where they already are.&lt;br /&gt;
&lt;br /&gt;
This matters for queries that join or filter a million rows, sort by one derived value, and finally return only 100 rows. A conventional wide temporary result may copy every projected column before &amp;lt;code&amp;gt;ORDER BY ... LIMIT&amp;lt;/code&amp;gt;. MemCP instead tries to materialize only the value, key domain, [[RecSets|record set]], or ordering dependency needed by the next physical stage.&lt;br /&gt;
&lt;br /&gt;
== The three reusable structures ==&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Structure !! Logical meaning !! Stored shape !! Typical use&lt;br /&gt;
|-&lt;br /&gt;
| Ordinary computed column || One derived value per live row of an existing table || A lazy &amp;lt;code&amp;gt;StorageComputeProxy&amp;lt;/code&amp;gt; backed by compressed main values, sparse repaired values, and a validity mask || Repeated scalar expressions, lookup results, JSON paths, correlated scalar probes, computed ordering&lt;br /&gt;
|-&lt;br /&gt;
| Group cache/keytable || One row per distinct grouping/domain key plus computed aggregate columns || A narrow internal &amp;lt;code&amp;gt;ENGINE=cache&amp;lt;/code&amp;gt; table with a unique key || Reused &amp;lt;code&amp;gt;GROUP BY&amp;lt;/code&amp;gt;, correlated aggregates, prepared membership/group domains&lt;br /&gt;
|-&lt;br /&gt;
| ORC (ordered-reduce column) || One value whose computation depends on partition/order predecessors || An ordered computed proxy with per-row validity and dependency-range repair || Running totals, rank/row-number-like work, reusable window/order calculations&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The SQL plan cache is different: it stores compiled plan formulas, not computed rows. A query may reuse a compiled formula without having a warm group cache, or reuse a computed cache after a newly compiled query recognizes the same canonical definition.&lt;br /&gt;
&lt;br /&gt;
== From SQL expression to canonical cache ==&lt;br /&gt;
&lt;br /&gt;
MemCP does not name reusable structures after a query&#039;s disposable aliases. During logical planning and physical lowering it analyzes the expression and constructs a canonical identity from the data the structure represents:&lt;br /&gt;
&lt;br /&gt;
* table aliases are rewritten to stable source roles, while two roles in a self-join remain distinct;&lt;br /&gt;
* column references include physical schema, relation, and column identity;&lt;br /&gt;
* grouping keys, source graph, filters, aggregate recipe, partition/order definition, and relevant bounds become part of the identity;&lt;br /&gt;
* SELECT aliases, formatting, and unrelated output columns do not create a second cache;&lt;br /&gt;
* stable structural hashes produce names such as internal &amp;lt;code&amp;gt;.grp:...&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;agg_...&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;__orc_...&amp;lt;/code&amp;gt; objects.&lt;br /&gt;
&lt;br /&gt;
Consequently, two queries can share a computed aggregate even when their SQL aliases or final projections differ. A second aggregate over the same group domain can add another narrow computed column to the existing keytable instead of cloning the entire intermediate relation. Conversely, a different filter, join role, ordering recipe, or semantic dependency receives a different identity rather than incorrectly sharing values.&lt;br /&gt;
&lt;br /&gt;
Preparation filters are deliberately absent from a computed column&#039;s logical identity. They only say which values are likely to be consumed soon and should be warmed eagerly. Every other live row still has a well-defined value that can be computed later.&lt;br /&gt;
&lt;br /&gt;
== Automatic analysis of the generated Scheme code ==&lt;br /&gt;
&lt;br /&gt;
The planner emits a &amp;lt;code&amp;gt;createcolumn&amp;lt;/code&amp;gt; call containing the computation lambda and its direct input columns. This is not the end of dependency discovery. The storage engine walks the resulting Scheme AST/procedure to determine what the computation reads and how source changes can reach the cached value.&lt;br /&gt;
&lt;br /&gt;
The analyzer:&lt;br /&gt;
&lt;br /&gt;
# removes source-location wrappers and accepts both unresolved symbols and already-resolved builtin procedures;&lt;br /&gt;
# descends through lambdas and nested physical expressions;&lt;br /&gt;
# recognizes &amp;lt;code&amp;gt;scan&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scan_order&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;scalar_scan&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;scalar_scan_order&amp;lt;/code&amp;gt; calls;&lt;br /&gt;
# also examines a scan&#039;s table expression, because a dynamic physical source can itself contain dependency-producing scans;&lt;br /&gt;
# resolves literal table handles or canonical table expressions to schema and relation;&lt;br /&gt;
# reads filter and map column lists from both quoted and constructed-list forms;&lt;br /&gt;
# records every source column used by the filter or mapper;&lt;br /&gt;
# inspects conjunctions of equality predicates and maps a source scan parameter back to the outer computed-column input it equals;&lt;br /&gt;
# follows source columns that are themselves computed and expands them transitively to their physical input, map, partition, and sort columns;&lt;br /&gt;
# extracts session-variable dependencies and creates session-specific cache variants where a value must not leak between users or sessions.&lt;br /&gt;
&lt;br /&gt;
For example, a generated lookup conceptually shaped like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;scheme&amp;quot;&amp;gt;&lt;br /&gt;
(lambda (customer_id)&lt;br /&gt;
	(scan tx (table &amp;quot;shop&amp;quot; &amp;quot;payments&amp;quot;)&lt;br /&gt;
		&#039;(&amp;quot;customer_id&amp;quot;)&lt;br /&gt;
		(lambda (payment_customer)&lt;br /&gt;
			(equal? payment_customer (outer customer_id)))&lt;br /&gt;
		&#039;(&amp;quot;amount&amp;quot;)&lt;br /&gt;
		(lambda (amount) amount)&lt;br /&gt;
		+&lt;br /&gt;
		0))&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
tells the storage analyzer that &amp;lt;code&amp;gt;payments.customer_id&amp;lt;/code&amp;gt; is the reverse lookup key for the target row&#039;s &amp;lt;code&amp;gt;customer_id&amp;lt;/code&amp;gt;, and that &amp;lt;code&amp;gt;payments.amount&amp;lt;/code&amp;gt; is relevant to the value. An UPDATE of an unrelated &amp;lt;code&amp;gt;payments.note&amp;lt;/code&amp;gt; column therefore need not invalidate the cache.&lt;br /&gt;
&lt;br /&gt;
The analysis is deliberately conservative. If a scan or reverse key relationship cannot be proven from the generated code, MemCP does not guess. It generates complete-column invalidation so the next read recomputes correct values. More analyzable code improves maintenance precision; opaque code must remain correct.&lt;br /&gt;
&lt;br /&gt;
== Automatic generation of maintenance triggers ==&lt;br /&gt;
&lt;br /&gt;
When the computed-column signature is installed or changes, &amp;lt;code&amp;gt;createcolumn&amp;lt;/code&amp;gt; calls the storage engine&#039;s trigger generator. It registers hidden system triggers on every discovered source table. Registration is idempotent, so preparing the same canonical cache again updates/reuses its metadata instead of accumulating duplicate triggers.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Analyzed shape !! Generated reaction to source INSERT/UPDATE/DELETE&lt;br /&gt;
|-&lt;br /&gt;
| Direct row-local inputs || The corresponding row value is marked stale or repaired through the computed proxy.&lt;br /&gt;
|-&lt;br /&gt;
| Lookup with proven equality key || Scan only target cache rows whose key equals the source row&#039;s &amp;lt;code&amp;gt;OLD&amp;lt;/code&amp;gt; and/or &amp;lt;code&amp;gt;NEW&amp;lt;/code&amp;gt; key, then invalidate that exact subset.&lt;br /&gt;
|-&lt;br /&gt;
| Additive aggregate (&amp;lt;code&amp;gt;+&amp;lt;/code&amp;gt;, neutral zero, analyzable map without nested scans) || Apply the mapped delta with &amp;lt;code&amp;gt;$increment:&amp;amp;lt;column&amp;amp;gt;&amp;lt;/code&amp;gt;; UPDATE subtracts OLD and adds NEW when the group key stays stable.&lt;br /&gt;
|-&lt;br /&gt;
| Additive UPDATE whose group key changes || Invalidate safely because old and new keytable membership may differ.&lt;br /&gt;
|-&lt;br /&gt;
| COUNT-style constant-one helper || Prefer robust invalidation, because the value also controls empty/non-empty group visibility.&lt;br /&gt;
|-&lt;br /&gt;
| ORC with known partition and sort key || Invalidate the affected partition from the OLD/NEW sort position onward.&lt;br /&gt;
|-&lt;br /&gt;
| Opaque or unsupported dependency || Invalidate the complete computed column.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The generated triggers run after INSERT, UPDATE, and DELETE. UPDATE triggers compare only columns proven relevant by the analysis and skip maintenance if none changed. They use the trigger row dictionaries &amp;lt;code&amp;gt;OLD&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;NEW&amp;lt;/code&amp;gt; to find both sides of a key-changing update.&lt;br /&gt;
&lt;br /&gt;
Selective invalidation is itself batched. The internal &amp;lt;code&amp;gt;$invalidate:&amp;amp;lt;column&amp;amp;gt;&amp;lt;/code&amp;gt; callback collects matching record IDs during the maintenance scan; invalidation is applied after scan locks are released. Incremental changes are similarly accumulated per proxy and record ID before &amp;lt;code&amp;gt;$increment:&amp;amp;lt;column&amp;amp;gt;&amp;lt;/code&amp;gt; updates cached values. This avoids nested lock acquisition in the inner scan loop.&lt;br /&gt;
&lt;br /&gt;
System maintenance triggers are hidden from ordinary &amp;lt;code&amp;gt;SHOW TRIGGERS&amp;lt;/code&amp;gt;; they are implementation-owned rather than user DDL. User triggers and the computed-cache trigger graph still share the storage engine&#039;s defined timing and locking machinery.&lt;br /&gt;
&lt;br /&gt;
=== Dependency chains and invalidation waves ===&lt;br /&gt;
&lt;br /&gt;
A cached column can depend on another computed cache. The storage engine registers &amp;lt;code&amp;gt;AfterInvalidate&amp;lt;/code&amp;gt; edges in addition to source DML triggers. Invalidating the lower cache synchronously propagates to its dependants.&lt;br /&gt;
&lt;br /&gt;
One invalidation wave carries a query/goroutine-local visited set keyed by target table and column. This makes repeated edges idempotent and prevents a malformed cycle from recursing forever without introducing a global invalidation lock. Selective invalidation is currently propagated conservatively at column level when a downstream reverse mapping cannot be preserved safely.&lt;br /&gt;
&lt;br /&gt;
=== Lifecycle cleanup ===&lt;br /&gt;
&lt;br /&gt;
The generator also owns cleanup:&lt;br /&gt;
&lt;br /&gt;
* dropping an internal target cache removes the triggers it installed on source tables;&lt;br /&gt;
* dropping a source table can drop dependent dot-prefixed helper tables so a later table with the same name cannot inherit stale data;&lt;br /&gt;
* group-key maintenance reacts to source INSERT, UPDATE, and DELETE;&lt;br /&gt;
* dropping the base table or a grouping column removes its dependent keytable;&lt;br /&gt;
* trigger target leases pin a cache while maintenance is using it, preventing concurrent eviction from invalidating a live pointer.&lt;br /&gt;
&lt;br /&gt;
These lifecycle triggers must only remove the helper objects they explicitly own. They are not general garbage collection and must never delete unrelated user data.&lt;br /&gt;
&lt;br /&gt;
== Race-free initial construction ==&lt;br /&gt;
&lt;br /&gt;
Installing triggers after filling a cache would leave a lost-update window: a source write between the snapshot and trigger registration would never invalidate the new value. &amp;lt;code&amp;gt;initialize_cache_table&amp;lt;/code&amp;gt; closes that race.&lt;br /&gt;
&lt;br /&gt;
It resolves and sorts all source tables into a deterministic lock order, blocks source mutations, registers maintenance, fills the canonical cache from a consistent source view, optionally finalizes/rebuilds it, and only then releases the locks. Concurrent attempts to initialize the same generation wait for the shared result rather than performing duplicate fills.&lt;br /&gt;
&lt;br /&gt;
Internal keytables use &amp;lt;code&amp;gt;ENGINE=cache&amp;lt;/code&amp;gt; and can store this initializer as a closed &amp;lt;code&amp;gt;oninit&amp;lt;/code&amp;gt; procedure. After restart or eviction, the first idempotent creation guard rebuilds the empty generation before exposing it to consumers. See [[Persistency and Performance Guarantees]] for why cache data is reconstructible rather than durable.&lt;br /&gt;
&lt;br /&gt;
== Lazy values, eager warming, and repair ==&lt;br /&gt;
&lt;br /&gt;
An ordinary computed column is a complete logical column even when few physical values exist:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;Compress&amp;lt;/code&amp;gt; can eagerly calculate all rows when the plan expects broad consumption;&lt;br /&gt;
* &amp;lt;code&amp;gt;CompressFiltered&amp;lt;/code&amp;gt; warms only rows selected by a preparation filter;&lt;br /&gt;
* reading a missing or invalid ordinary value calculates that row from its current inputs and stores the result;&lt;br /&gt;
* valid compressed main values use the normal bulk column-reader fast path;&lt;br /&gt;
* repeated &amp;lt;code&amp;gt;createcolumn&amp;lt;/code&amp;gt; calls for the same signature preserve valid cached values and repair only missing/dirty state;&lt;br /&gt;
* a materially different semantic formula receives a different canonical identity; reissuing the same signature preserves its valid cache. ORC metadata changes explicitly invalidate the affected ordered proxies.&lt;br /&gt;
&lt;br /&gt;
For broad selective invalidations, each proxy compares a short measured repair sample with its last full recomputation cost. If point repair is predicted to cost more, it marks the whole column dirty and lets the next consumer perform one coherent rebuild. This adapts to the actual computor rather than relying on one global row-count threshold.&lt;br /&gt;
&lt;br /&gt;
The historical documentation said computations become parallel above 60,000 rows. That threshold is no longer the public execution contract. Current preparation fans work out over active shards, while planner cost, shard count, input size, and the maintenance/recompute path determine useful parallelism. Large independent shards can compute concurrently; a tiny table or a single ordered dependency cannot gain speed merely from crossing a fixed row number.&lt;br /&gt;
&lt;br /&gt;
== GROUP BY through narrow computed relations ==&lt;br /&gt;
&lt;br /&gt;
A reusable group cache conceptually follows four steps:&lt;br /&gt;
&lt;br /&gt;
# create a canonical internal table containing a UNIQUE key over all grouping columns;&lt;br /&gt;
# populate the distinct grouping keys;&lt;br /&gt;
# add one computed column for each aggregate or derived ordering value;&lt;br /&gt;
# scan the narrow group relation and join/project base values only where the final result needs them.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;&lt;br /&gt;
CREATE TABLE t (a TEXT, b INT);&lt;br /&gt;
INSERT INTO t VALUES (&#039;foo&#039;, 1), (&#039;bar&#039;, 2), (&#039;foo&#039;, 3);&lt;br /&gt;
&lt;br /&gt;
SELECT a, SUM(b) AS total&lt;br /&gt;
FROM t&lt;br /&gt;
GROUP BY a;&lt;br /&gt;
-- bar | 2&lt;br /&gt;
-- foo | 4&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The keytable cleanup trigger inserts a missing key idempotently, removes a key after the last source row leaves the group, and handles OLD and NEW keys on UPDATE. It runs at priority 90, before aggregate invalidation at priority 100, so key membership is current when a value is repaired.&lt;br /&gt;
&lt;br /&gt;
GROUP BY syntax does not force a cache. The physical lowerer compares a one-pass fused aggregation with keytable construction, expected probes/reuse, maintenance cost, memory, and available alternative carriers. Query-local or UNION-shaped groups may instead be filled in one batch, while reusable base-table groups can use storage-managed computed columns.&lt;br /&gt;
&lt;br /&gt;
Different surrounding WHERE ranges can reuse the same row-local computed expression because the preparation predicate does not define the column. A group cache, however, includes the grouping domain and semantic source filter in its canonical identity: two genuinely different group populations must not share one aggregate value.&lt;br /&gt;
&lt;br /&gt;
== Order-dependent computed columns (ORC) ==&lt;br /&gt;
&lt;br /&gt;
An ORC is not pointwise. A running total at row 500 depends on preceding rows in its partition, so changing row 100 may invalidate a suffix rather than just row 100.&lt;br /&gt;
&lt;br /&gt;
The ORC definition records sort columns/directions, the number of leading partition columns, map columns/function, reducer, and neutral value. Generated triggers:&lt;br /&gt;
&lt;br /&gt;
* use equality bounds for the partition prefix;&lt;br /&gt;
* invalidate a range beginning at the changed OLD or NEW sort key;&lt;br /&gt;
* leave unrelated partitions valid;&lt;br /&gt;
* fall back to complete invalidation when a cross-table dependency cannot be mapped selectively;&lt;br /&gt;
* compare cumulative selective-invalidation cost with the last suffix/full recomputation and choose complete invalidation when that is cheaper.&lt;br /&gt;
&lt;br /&gt;
On the next read, the ordered proxy repairs the dependency range under the table&#039;s ORC recomputation guard. Concurrent readers do not observe the internal “invalid” sentinel used by the reducer. If one ordered scan can compute a window directly, the planner may fuse it instead of creating an ORC at all.&lt;br /&gt;
&lt;br /&gt;
== Cost, eviction, and observability ==&lt;br /&gt;
&lt;br /&gt;
The physical lowerer compares:&lt;br /&gt;
&lt;br /&gt;
* direct scalar/index probes;&lt;br /&gt;
* a fused one-pass scan or aggregate;&lt;br /&gt;
* a [[RecSets|RecSet]] carrier;&lt;br /&gt;
* a canonical computed column;&lt;br /&gt;
* an FK-backed/group cache;&lt;br /&gt;
* an ORC;&lt;br /&gt;
* a narrow temporary relation.&lt;br /&gt;
&lt;br /&gt;
Inputs include build work, expected reuse, source and target cardinality, maintenance/invalidation work, memory, ordering, LIMIT, and available indexes. &amp;lt;code&amp;gt;EXPLAIN PHYSICAL&amp;lt;/code&amp;gt; shows the selected physical family for supported decisions; it is better evidence than assuming repeated SQL text always builds a cache.&lt;br /&gt;
&lt;br /&gt;
Temporary computed columns and keytables are accounted by the global memory manager. Access refreshes their lease/last-used state. Because they are reconstructible, the manager can evict them under pressure; a later query recreates or lazily repairs them. Base data remains authoritative throughout.&lt;br /&gt;
&lt;br /&gt;
== Correctness boundaries ==&lt;br /&gt;
&lt;br /&gt;
* A preparation filter changes warming, never the logical domain or NULL value of a computed column.&lt;br /&gt;
* A cached value must never outlive a source change without an invalidation/maintenance edge.&lt;br /&gt;
* Opaque code requires conservative invalidation; absence of a recognized equality is not evidence of independence.&lt;br /&gt;
* Session-dependent formulas require isolated variants and must not reuse one user&#039;s value for another session.&lt;br /&gt;
* ORC invalidation follows ordering dependencies and cannot be replaced by unrelated point repair.&lt;br /&gt;
* Internal trigger generation must be complete before source mutations are unblocked.&lt;br /&gt;
* Cache eviction and source-table DDL must remove their owned trigger graph without touching user data.&lt;br /&gt;
&lt;br /&gt;
For exact low-level signatures see [[Storage]]. Related architecture is documented in [[Query Planner and Physical Lowering]], [[Triggers]], [[Columnar Storage]], [[Memory Management and Eviction]], [[RecSets]], and [[Parallel Computing]].&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Sync&amp;diff=362</id>
		<title>Sync</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Sync&amp;diff=362"/>
		<updated>2026-08-28T09:59:39Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;sync&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Sync =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Generated from MemCP c42e19eba on 2026-08-27; do not edit manually. --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&amp;gt;Generated from MemCP commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. See [[Full SCM API documentation]].&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Sync&#039;&#039;&#039; module provides explicit coordination for state that must cross functional scopes or concurrent tasks. It includes:&lt;br /&gt;
&lt;br /&gt;
* thread-safe sessions and contextual values;&lt;br /&gt;
* promises and one-time publication;&lt;br /&gt;
* mutex and serialized execution helpers;&lt;br /&gt;
* shared computation and cache maps;&lt;br /&gt;
* timing, waiting, and lifecycle coordination.&lt;br /&gt;
&lt;br /&gt;
Prefer ordinary immutable values when no sharing is required. Use these primitives to make ownership, failure, and publication explicit rather than relying on outer-scope mutation, which this Scheme dialect does not provide.&lt;br /&gt;
&lt;br /&gt;
== newpromise ==&lt;br /&gt;
&lt;br /&gt;
Creates a thread-safe promise that lets parallel work publish one result for other code to inspect. Use it for shared initialization, asynchronous results, or ensuring that only the first successful producer resolves a value. Read with (promise &amp;amp;quot;value&amp;amp;quot;), inspect completion with (promise &amp;amp;quot;state&amp;amp;quot;), resolve with (promise &amp;amp;quot;value&amp;amp;quot; value), resolve exactly once with (promise &amp;amp;quot;once&amp;amp;quot; value), and mark failure with (promise &amp;amp;quot;fail&amp;amp;quot; error).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;storage&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;any&amp;amp;gt;&amp;lt;/code&amp;gt;): optional existing two-item list used to hold the promise state; most callers omit this &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;slot&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): promise state or value slot&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;promise&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): operation-based accessor for reading, resolving, or failing the promise&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): one of: value, state, fail, once&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value to store (for value/once/fail) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;message&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): optional error message used when once finds an already completed promise &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): stored value, state flag, or operation result&lt;br /&gt;
&lt;br /&gt;
== newsession ==&lt;br /&gt;
&lt;br /&gt;
Creates a thread-safe key-value session. Call it without arguments to list values, with a key to read, with a key and value to store, or with get_or_compute_scoped, a scope, a key, and a producer to share one concurrent computation.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;session&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): session accessor accepting exactly zero, one, two, or four arguments&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;key_or_operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): key, or get_or_compute_scoped &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value_or_scope&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value to store, or scope for get_or_compute_scoped &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;scoped_key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): cache key used by get_or_compute_scoped &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;scoped_producer&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): producer used only by the four-argument get_or_compute_scoped form &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): computed value cached for the scope and key&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value list, stored value, retrieved value, or shared computed value&lt;br /&gt;
&lt;br /&gt;
== with_session ==&lt;br /&gt;
&lt;br /&gt;
Executes a function with the given session installed in the execution context, so storage operations can access the session&#039;s transaction state.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;session&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): the session to install&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;fn&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): the function to execute&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== context ==&lt;br /&gt;
&lt;br /&gt;
Context helper function. Each context also contains a session. (context func args) creates a new context and runs func in that context, (context &amp;amp;quot;session&amp;amp;quot;) reads the session variable, (context &amp;amp;quot;check&amp;amp;quot;) will check the liveliness of the context and otherwise throw an error&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;args...&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): depends on the usage &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sleep ==&lt;br /&gt;
&lt;br /&gt;
sleeps the amount of seconds&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;duration&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of seconds to sleep&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== once ==&lt;br /&gt;
&lt;br /&gt;
Creates a function wrapper that you can call multiple times but only gets executed once. The result value is cached and returned on a second call. You can add parameters to that resulting function that will be passed to the first run of the wrapped function.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;f&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): function that produces the result value&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;argument&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;once_wrapper&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): calls the wrapped function once and returns its cached result thereafter&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;args&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): arguments forwarded to the wrapped function on first call &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): result cached from the first call&lt;br /&gt;
&lt;br /&gt;
== mutex ==&lt;br /&gt;
&lt;br /&gt;
Creates a context-aware mutex. The return value serializes calls to parameterless functions and stops waiting when the current request is cancelled.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;locked&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): executes one parameterless function while holding the mutex&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;fn&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): parameterless function to execute under the lock&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): result returned by the protected function&lt;br /&gt;
&lt;br /&gt;
== numcpu ==&lt;br /&gt;
&lt;br /&gt;
Returns the number of logical CPUs available for parallel execution&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== memstats ==&lt;br /&gt;
&lt;br /&gt;
Returns memory statistics as a dict with keys: alloc, total_alloc, sys, heap_alloc, heap_sys (all in bytes)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;dict&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;settimeout&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== setTimeout ==&lt;br /&gt;
&lt;br /&gt;
Schedules a callback to run after the given delay in milliseconds (fractional values allowed for sub-millisecond precision).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;callback&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): function to execute once the timeout expires&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;args&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;milliseconds&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): milliseconds until execution&lt;br /&gt;
* &#039;&#039;&#039;args...&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): optional arguments forwarded to the callback &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;cleartimeout&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== clearTimeout ==&lt;br /&gt;
&lt;br /&gt;
Cancels a timeout created with setTimeout.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;id&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): identifier returned by setTimeout&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Supported_SQL&amp;diff=361</id>
		<title>Supported SQL</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Supported_SQL&amp;diff=361"/>
		<updated>2026-08-28T09:59:39Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;supported-sql&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Supported SQL =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Verified against development commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. MemCP is Beta and does not claim complete MySQL or PostgreSQL compatibility. Unsupported shapes should fail explicitly; test a required workload before migration.&lt;br /&gt;
&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
This page is a capability map for application evaluation. MemCP accepts a broad MySQL-oriented dialect through its MySQL protocol and HTTP endpoint, plus PostgreSQL-oriented syntax through a separate HTTP endpoint. Both compile into the same logical planner and storage runtime, but accepted surface syntax and returned metadata can differ by frontend.&lt;br /&gt;
&lt;br /&gt;
Support is defined by tested semantics, not merely by whether the parser accepts a statement. Compatibility-only clauses may intentionally be no-ops, and uncommon combinations can remain unsupported even when their individual operators are available. Use this overview to select candidates, then verify every required query, constraint, transaction, prepared statement, and client behavior against the deployed release.&lt;br /&gt;
&amp;lt;span id=&amp;quot;query-language&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Query language ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;SELECT&amp;lt;/code&amp;gt;, aliases, &amp;lt;code&amp;gt;WHERE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DISTINCT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;GROUP BY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;HAVING&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ORDER BY&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LIMIT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;OFFSET&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;INNER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LEFT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RIGHT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;CROSS JOIN&amp;lt;/code&amp;gt;;&lt;br /&gt;
* &amp;lt;code&amp;gt;UNION&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;UNION ALL&amp;lt;/code&amp;gt;, including ordered/limited set results;&lt;br /&gt;
* derived tables and logical SQL views;&lt;br /&gt;
* scalar, &amp;lt;code&amp;gt;EXISTS&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;NOT EXISTS&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;IN&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;NOT IN&amp;lt;/code&amp;gt; subqueries, including many correlated and grouped forms;&lt;br /&gt;
* aggregates &amp;lt;code&amp;gt;COUNT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;SUM&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;AVG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;MAX&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;GROUP_CONCAT&amp;lt;/code&amp;gt;;&lt;br /&gt;
* window functions including &amp;lt;code&amp;gt;ROW_NUMBER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RANK&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;DENSE_RANK&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LEAD&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;LAG&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;FIRST_VALUE&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;LAST_VALUE&amp;lt;/code&amp;gt; with partition/order clauses.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;data-modification-and-schema&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Data modification and schema ==&lt;br /&gt;
&lt;br /&gt;
* single- and multi-row &amp;lt;code&amp;gt;INSERT&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INSERT IGNORE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;INSERT … SELECT&amp;lt;/code&amp;gt;, and MySQL or PostgreSQL upsert syntax;&lt;br /&gt;
* &amp;lt;code&amp;gt;UPDATE&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;DELETE&amp;lt;/code&amp;gt;, including qualified and supported multi-table forms;&lt;br /&gt;
* &amp;lt;code&amp;gt;CREATE&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;ALTER&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;RENAME&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TRUNCATE&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;DROP&amp;lt;/code&amp;gt; for databases and tables;&lt;br /&gt;
* &amp;lt;code&amp;gt;CREATE VIEW&amp;lt;/code&amp;gt;, indexes, primary/unique keys, foreign keys, defaults, &amp;lt;code&amp;gt;AUTO_INCREMENT&amp;lt;/code&amp;gt;, computed expressions, types, collations, and per-table ENGINE;&lt;br /&gt;
* persistent BEFORE/AFTER triggers for INSERT, UPDATE, and DELETE.&lt;br /&gt;
&lt;br /&gt;
Foreign keys are enforced for the tested RESTRICT, CASCADE, and SET NULL paths. Some compatibility DDL is intentionally accepted as a no-op; for example, a client accepting &amp;lt;code&amp;gt;ADD FULLTEXT&amp;lt;/code&amp;gt; does not imply a MySQL-compatible full-text index implementation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;transactions-security-and-metadata&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Transactions, security, and metadata ==&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;BEGIN&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;COMMIT&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;ROLLBACK&amp;lt;/code&amp;gt;;&lt;br /&gt;
* users, passwords, grants, revokes, and database access policies;&lt;br /&gt;
* &amp;lt;code&amp;gt;SHOW DATABASES&amp;lt;/code&amp;gt;, tables, columns, indexes, create-table metadata, variables, engines, processlist, and selected &amp;lt;code&amp;gt;INFORMATION_SCHEMA&amp;lt;/code&amp;gt; relations;&lt;br /&gt;
* prepared statements over the MySQL protocol;&lt;br /&gt;
* &amp;lt;code&amp;gt;KILL QUERY&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;KILL CONNECTION&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
See [[Transactions_and_Isolation|Transactions and Isolation]] and [[Security_and_Authentication|Security and Authentication]] for the operational contract.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;expressions&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Expressions ==&lt;br /&gt;
&lt;br /&gt;
MemCP implements SQL NULL/three-valued logic, CASE, COALESCE/NULLIF/IFNULL, arithmetic and bitwise operators, comparisons, BETWEEN, IN lists, LIKE/ILIKE, REGEXP/RLIKE, MATCH…AGAINST compatibility, casts, string functions, mathematical functions, hashes, date/time functions, intervals, and timezone conversion.&lt;br /&gt;
&lt;br /&gt;
The exact parser and function catalog changes more often than this overview. Use the generated API reference and the SQL test taxonomy for detailed coverage.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;json&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== JSON ==&lt;br /&gt;
&lt;br /&gt;
MemCP stores declared &amp;lt;code&amp;gt;JSON&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;JSONB&amp;lt;/code&amp;gt; values in a native tagged BSON representation. The MySQL dialect implements JSON validation, type inspection, path extraction, constructors, aggregates, mutation functions, containment/search operations, &amp;lt;code&amp;gt;JSON_TABLE&amp;lt;/code&amp;gt;, and the &amp;lt;code&amp;gt;-&amp;gt;&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;-&amp;gt;&amp;gt;&amp;lt;/code&amp;gt; operators. The PostgreSQL dialect provides its corresponding &amp;lt;code&amp;gt;json&amp;lt;/code&amp;gt;/&amp;lt;code&amp;gt;jsonb&amp;lt;/code&amp;gt; operators, constructors, aggregates, path functions, and set-returning expansion forms. Deterministic path expressions can be materialized and indexed through the ordinary computed-column/index machinery. See [[JSON]] for the detailed compatibility contract and deviations.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;planner-inspection&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Planner inspection ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;sql&amp;quot;&amp;gt;EXPLAIN SELECT ...;&lt;br /&gt;
EXPLAIN IR SELECT ...;&lt;br /&gt;
EXPLAIN REORDER SELECT ...;&lt;br /&gt;
EXPLAIN PHYSICAL SELECT ...;&lt;br /&gt;
EXPLAIN COMPILE SELECT ...;&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
See [[Query_Planner_and_Physical_Lowering|Query Planner and Physical Lowering]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;known-limitations&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== Known limitations ==&lt;br /&gt;
&lt;br /&gt;
MemCP is not a byte-for-byte MySQL server implementation. Metadata details, administrative commands, uncommon syntax, advanced locking modes, XA, stored procedures, and untested SQL-standard edge cases may be absent. Consult the [https://github.com/launix-de/memcp/issues current issue tracker] and add a must-pass and must-fail test for every application-critical construct.&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Strings&amp;diff=360</id>
		<title>Strings</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Strings&amp;diff=360"/>
		<updated>2026-08-28T09:59:38Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;strings&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Strings =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Generated from MemCP c42e19eba on 2026-08-27; do not edit manually. --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&amp;gt;Generated from MemCP commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. See [[Full SCM API documentation]].&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Strings&#039;&#039;&#039; module provides text and binary-string processing for Scheme and SQL compatibility. It includes:&lt;br /&gt;
&lt;br /&gt;
* validation, length, concatenation, slicing, padding, trimming, and case conversion;&lt;br /&gt;
* splitting, searching, replacement, wildcard/regular-expression matching, and simplification;&lt;br /&gt;
* locale-aware collation and natural ordering;&lt;br /&gt;
* URL, HTML, Base64, hexadecimal, JSON, BSON, and SQL-string conversion;&lt;br /&gt;
* hashes, checksums, random data, and SQL-dialect compatibility functions.&lt;br /&gt;
&lt;br /&gt;
Indexing and length semantics can differ between bytes and Unicode characters; consult each function&#039;s parameter description rather than assuming one unit for every operation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;string&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== string? ==&lt;br /&gt;
&lt;br /&gt;
tells if the value is a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== concat ==&lt;br /&gt;
&lt;br /&gt;
concatenates stringable values and returns a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): first value to concat&lt;br /&gt;
* &#039;&#039;&#039;more...&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): additional values to concat &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sql_concat ==&lt;br /&gt;
&lt;br /&gt;
SQL CONCAT semantics: returns NULL if any argument is NULL&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): first value to concat&lt;br /&gt;
* &#039;&#039;&#039;more...&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): additional values to concat &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== substr ==&lt;br /&gt;
&lt;br /&gt;
returns a substring (0-based index)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to cut&lt;br /&gt;
* &#039;&#039;&#039;start&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): first character index (0-based)&lt;br /&gt;
* &#039;&#039;&#039;len&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): optional length &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sql_substr ==&lt;br /&gt;
&lt;br /&gt;
SQL SUBSTR/SUBSTRING with 1-based index and bounds checking&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to cut&lt;br /&gt;
* &#039;&#039;&#039;start&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): first character position (1-based)&lt;br /&gt;
* &#039;&#039;&#039;len&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): optional length &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== simplify ==&lt;br /&gt;
&lt;br /&gt;
Converts numeric text to a number. Text beginning with { or [ becomes a native JSON value when it is valid JSON; other input remains a string.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value to interpret as a number or JSON value&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== strlen ==&lt;br /&gt;
&lt;br /&gt;
returns the length of a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== strlike ==&lt;br /&gt;
&lt;br /&gt;
matches the string against a wildcard pattern using SQL NULL semantics&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
* &#039;&#039;&#039;pattern&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): pattern with % and _ in them&lt;br /&gt;
* &#039;&#039;&#039;collation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): collation in which to compare them &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== strlike_cs ==&lt;br /&gt;
&lt;br /&gt;
matches the string against a wildcard pattern case-sensitively using SQL NULL semantics&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
* &#039;&#039;&#039;pattern&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): pattern with % and _ in them&lt;br /&gt;
* &#039;&#039;&#039;collation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): ignored (present for parser compatibility) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;tolower&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== toLower ==&lt;br /&gt;
&lt;br /&gt;
turns a string into lower case&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;toupper&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== toUpper ==&lt;br /&gt;
&lt;br /&gt;
turns a string into upper case&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== replace ==&lt;br /&gt;
&lt;br /&gt;
replaces all occurances in a string with another string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-11&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;s&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
* &#039;&#039;&#039;find&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): search string&lt;br /&gt;
* &#039;&#039;&#039;replace&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): replace string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-11&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== strtrim ==&lt;br /&gt;
&lt;br /&gt;
trims whitespace from both ends of a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-12&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-12&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== strltrim ==&lt;br /&gt;
&lt;br /&gt;
trims whitespace from the left of a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-13&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-13&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== strrtrim ==&lt;br /&gt;
&lt;br /&gt;
trims whitespace from the right of a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-14&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-14&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sql_trim ==&lt;br /&gt;
&lt;br /&gt;
SQL TRIM(): NULL-safe trim of whitespace from both ends&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-15&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-15&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sql_ltrim ==&lt;br /&gt;
&lt;br /&gt;
SQL LTRIM(): NULL-safe trim of whitespace from left&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-16&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-16&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sql_rtrim ==&lt;br /&gt;
&lt;br /&gt;
SQL RTRIM(): NULL-safe trim of whitespace from right&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-17&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-17&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== split ==&lt;br /&gt;
&lt;br /&gt;
splits a string using a separator or space&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-18&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
* &#039;&#039;&#039;separator&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) parameter, defaults to &amp;amp;quot; &amp;amp;quot; &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-18&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== string_repeat ==&lt;br /&gt;
&lt;br /&gt;
repeats a string n times&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-19&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to repeat&lt;br /&gt;
* &#039;&#039;&#039;count&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of repetitions&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-19&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== collate ==&lt;br /&gt;
&lt;br /&gt;
returns a canonical order relation for a collation and direction. MemCP allows natural sorting of numeric literals.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-20&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;collation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): collation string of the form LANG or LANG_cs or LANG_ci where LANG is a BCP 47 code, for compatibility to MySQL, a CHARSET_ prefix is allowed and ignored as well as the aliases bin, danish, general, german1, german2, spanish and swedish are allowed for language codes&lt;br /&gt;
* &#039;&#039;&#039;reverse&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether to reverse the order like in ORDER BY DESC &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-20&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;relation&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): compares two values using the selected collation and direction&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;a&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left operand&lt;br /&gt;
*** &#039;&#039;&#039;b&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right operand&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether a sorts before b&lt;br /&gt;
&lt;br /&gt;
== htmlentities ==&lt;br /&gt;
&lt;br /&gt;
escapes the string for use in HTML&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-21&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-21&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== urlencode ==&lt;br /&gt;
&lt;br /&gt;
encodes a string according to URI coding schema&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-22&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to encode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-22&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== urldecode ==&lt;br /&gt;
&lt;br /&gt;
decodes a string according to URI coding schema&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-23&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to decode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-23&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_encode ==&lt;br /&gt;
&lt;br /&gt;
encodes a value in JSON, treats lists as lists&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-24&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value to encode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-24&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_quote ==&lt;br /&gt;
&lt;br /&gt;
quotes a string as JSON&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-25&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-25&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_encode_assoc ==&lt;br /&gt;
&lt;br /&gt;
encodes a value in JSON, treats lists as associative arrays&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-26&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value to encode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-26&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_decode ==&lt;br /&gt;
&lt;br /&gt;
parses JSON into a map&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-27&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to decode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-27&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_decode_scmer ==&lt;br /&gt;
&lt;br /&gt;
parses JSON produced by json_encode and preserves Scheme symbols and lists&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-28&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): Scmer JSON to decode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-28&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== base64_encode ==&lt;br /&gt;
&lt;br /&gt;
encodes a string as Base64 (standard encoding)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-29&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): binary string to encode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-29&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== base64_decode ==&lt;br /&gt;
&lt;br /&gt;
decodes a Base64 string (standard encoding)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-30&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): base64-encoded string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-30&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sql_unescape ==&lt;br /&gt;
&lt;br /&gt;
unescapes the inner part of a sql string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-31&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to decode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-31&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== bin2hex ==&lt;br /&gt;
&lt;br /&gt;
turns binary data into hex with lowercase letters&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-32&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to encode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-32&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;bin2hex-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== bin2hex ==&lt;br /&gt;
&lt;br /&gt;
turns binary data into hex with lowercase letters&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-33&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): string to encode&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-33&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== hex2bin ==&lt;br /&gt;
&lt;br /&gt;
decodes a hex string into binary data&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-34&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): hex string (even length)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-34&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== uuid ==&lt;br /&gt;
&lt;br /&gt;
generates a new random UUID v4 string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-35&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-35&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;randombytes&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== randomBytes ==&lt;br /&gt;
&lt;br /&gt;
returns a string with numBytes cryptographically secure random bytes&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-36&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;numBytes&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of random bytes&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-36&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== regexp_replace ==&lt;br /&gt;
&lt;br /&gt;
replaces matches of a regex pattern in a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-37&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;str&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
* &#039;&#039;&#039;pattern&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): regex pattern&lt;br /&gt;
* &#039;&#039;&#039;replacement&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): replacement string&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-37&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== fnv_hash ==&lt;br /&gt;
&lt;br /&gt;
computes a fast non-cryptographic 64-bit FNV-1a hash of a string, returns a 16-character hex string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-38&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;str&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string to hash&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-38&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== stable_structural_hash ==&lt;br /&gt;
&lt;br /&gt;
streams the string or serialized representation of a Scheme value into stable FNV-1a without constructing the complete representation&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-39&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value to hash&lt;br /&gt;
* &#039;&#039;&#039;serialize&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): use the Scheme serializer instead of string rendering &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-39&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sha1 ==&lt;br /&gt;
&lt;br /&gt;
computes the SHA-1 digest of a string, returns a 40-character lowercase hex string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-40&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;str&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string to hash&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-40&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== sha256 ==&lt;br /&gt;
&lt;br /&gt;
computes the SHA-256 digest of a string, returns a 64-character lowercase hex string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-41&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;str&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string to hash&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-41&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== regexp_test ==&lt;br /&gt;
&lt;br /&gt;
tests if a string matches a regex pattern, returns true/false&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-42&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;str&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): input string&lt;br /&gt;
* &#039;&#039;&#039;pattern&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): regex pattern&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-42&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_parse_bson ==&lt;br /&gt;
&lt;br /&gt;
validates JSON and returns a BSON-backed value&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-43&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-43&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_array ==&lt;br /&gt;
&lt;br /&gt;
creates a MySQL-compatible JSON array&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-44&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-44&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_object ==&lt;br /&gt;
&lt;br /&gt;
creates a MySQL-compatible JSON object&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-45&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-45&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;json_quote-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== json_quote ==&lt;br /&gt;
&lt;br /&gt;
quotes a string as JSON&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-46&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-46&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_unquote ==&lt;br /&gt;
&lt;br /&gt;
unquotes a JSON string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-47&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-47&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_valid ==&lt;br /&gt;
&lt;br /&gt;
tests whether a value contains valid JSON&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-48&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-48&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_type ==&lt;br /&gt;
&lt;br /&gt;
returns the MySQL JSON type name&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-49&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-49&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_depth ==&lt;br /&gt;
&lt;br /&gt;
returns maximum JSON document depth&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-50&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-50&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_length ==&lt;br /&gt;
&lt;br /&gt;
returns JSON object or array length&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-51&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-51&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_extract ==&lt;br /&gt;
&lt;br /&gt;
extracts one or more JSON paths&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-52&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-52&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_keys ==&lt;br /&gt;
&lt;br /&gt;
returns object member names&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-53&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-53&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_contains_path ==&lt;br /&gt;
&lt;br /&gt;
tests whether one or all JSON paths exist&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-54&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-54&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_contains ==&lt;br /&gt;
&lt;br /&gt;
tests JSON containment&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-55&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-55&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_overlaps ==&lt;br /&gt;
&lt;br /&gt;
tests whether JSON values overlap&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-56&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-56&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_member_of ==&lt;br /&gt;
&lt;br /&gt;
tests whether a JSON scalar is a member of an array&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-57&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-57&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_pretty ==&lt;br /&gt;
&lt;br /&gt;
pretty-prints JSON&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-58&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-58&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_storage_size ==&lt;br /&gt;
&lt;br /&gt;
returns BSON payload size&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-59&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-59&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_storage_free ==&lt;br /&gt;
&lt;br /&gt;
returns unused BSON storage space&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-60&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-60&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_schema_valid ==&lt;br /&gt;
&lt;br /&gt;
validates a document against a MySQL Draft 4 JSON schema&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-61&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-61&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_schema_validation_report ==&lt;br /&gt;
&lt;br /&gt;
reports MySQL Draft 4 JSON schema validation&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-62&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-62&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_set ==&lt;br /&gt;
&lt;br /&gt;
sets or inserts JSON path values&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-63&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-63&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_insert ==&lt;br /&gt;
&lt;br /&gt;
inserts missing JSON path values&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-64&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-64&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_replace ==&lt;br /&gt;
&lt;br /&gt;
replaces existing JSON path values&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-65&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-65&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_remove ==&lt;br /&gt;
&lt;br /&gt;
removes JSON path values&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-66&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-66&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_array_append ==&lt;br /&gt;
&lt;br /&gt;
appends values to JSON arrays&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-67&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-67&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_array_insert ==&lt;br /&gt;
&lt;br /&gt;
inserts values into JSON arrays&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-68&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-68&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_merge_patch ==&lt;br /&gt;
&lt;br /&gt;
merges documents using RFC 7396 semantics&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-69&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-69&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_merge_preserve ==&lt;br /&gt;
&lt;br /&gt;
merges documents while preserving values&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-70&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-70&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_search ==&lt;br /&gt;
&lt;br /&gt;
searches JSON string values&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-71&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-71&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_value ==&lt;br /&gt;
&lt;br /&gt;
extracts a scalar JSON value&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-72&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-72&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_to_json ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL to_json and to_jsonb&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-73&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-73&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_row_to_json ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL row_to_json&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-74&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-74&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_build_array ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL JSON array builders&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-75&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-75&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_array_absent ==&lt;br /&gt;
&lt;br /&gt;
implements SQL/JSON ARRAY ABSENT ON NULL&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-76&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-76&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_build_object ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL JSON object builders&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-77&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-77&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_object ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL json_object and jsonb_object array forms&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-78&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-78&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_serialize ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL json_serialize&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-79&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-79&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_array_length ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL json_array_length&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-80&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-80&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_extract_path ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL json_extract_path&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-81&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-81&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_extract_path_text ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL json_extract_path_text&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-82&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-82&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_set ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb_set&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-83&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-83&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_set_lax ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb_set_lax&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-84&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-84&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_insert ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb_insert&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-85&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-85&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_strip_nulls ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL json_strip_nulls&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-86&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-86&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_typeof ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL json_typeof&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-87&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-87&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_populate_record_valid ==&lt;br /&gt;
&lt;br /&gt;
validates PostgreSQL jsonb_populate_record input shape&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-88&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-88&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_concat ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb concatenation&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-89&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-89&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_delete ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb deletion&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-90&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-90&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_delete_path ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb path deletion&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-91&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-91&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_subtract ==&lt;br /&gt;
&lt;br /&gt;
dispatches PostgreSQL numeric and jsonb subtraction&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-92&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-92&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_exists ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb top-level existence&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-93&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-93&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_path_exists ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb_path_exists&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-94&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-94&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_path_match ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb_path_match&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-95&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-95&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_path_query_array ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb_path_query_array&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-96&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-96&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_jsonb_path_query_first ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL jsonb_path_query_first&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-97&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-97&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_value ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL SQL/JSON JSON_VALUE&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-98&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-98&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_get ==&lt;br /&gt;
&lt;br /&gt;
implements PostgreSQL JSON object and array extraction&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-99&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-99&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_arrayagg_entry ==&lt;br /&gt;
&lt;br /&gt;
wraps one JSON_ARRAYAGG input value&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-100&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-100&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_arrayagg_reduce ==&lt;br /&gt;
&lt;br /&gt;
JSON_ARRAYAGG reducer&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-101&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-101&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_arrayagg_finalize ==&lt;br /&gt;
&lt;br /&gt;
builds one BSON array from a collected JSON_ARRAYAGG value list&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-102&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-102&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_objectagg_entry ==&lt;br /&gt;
&lt;br /&gt;
constructs a JSON_OBJECTAGG key/value entry&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-103&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-103&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== json_objectagg_reduce ==&lt;br /&gt;
&lt;br /&gt;
JSON_OBJECTAGG reducer&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-104&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-104&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== pg_json_table_rows ==&lt;br /&gt;
&lt;br /&gt;
materializes a PostgreSQL JSON table function as rows&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–10000&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-105&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;arguments&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;) &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-105&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Streams&amp;diff=359</id>
		<title>Streams</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Streams&amp;diff=359"/>
		<updated>2026-08-28T09:59:38Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;streams&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Streams =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Generated from MemCP c42e19eba on 2026-08-27; do not edit manually. --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&amp;gt;Generated from MemCP commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. See [[Full SCM API documentation]].&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Streams&#039;&#039;&#039; module processes data incrementally instead of requiring one complete in-memory string. It includes string-backed streams plus gzip/xz compression and decompression adapters.&lt;br /&gt;
&lt;br /&gt;
Compression functions produce compressed output; &amp;lt;code&amp;gt;zcat&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;xzcat&amp;lt;/code&amp;gt; decode compressed input. Choose the direction explicitly when composing import and export pipelines, and close externally owned resources according to the caller&#039;s IO contract.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;streamstring&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== streamString ==&lt;br /&gt;
&lt;br /&gt;
creates a stream that contains a string&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;content&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): content to put into the stream&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== gzip ==&lt;br /&gt;
&lt;br /&gt;
compresses a stream with gzip. Create streams with (stream filename)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): input stream&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== xz ==&lt;br /&gt;
&lt;br /&gt;
compresses a stream with xz. Create streams with (stream filename)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): input stream&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== zcat ==&lt;br /&gt;
&lt;br /&gt;
turns a compressed gzip stream into a stream of uncompressed data. Create streams with (stream filename)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): input stream&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== xzcat ==&lt;br /&gt;
&lt;br /&gt;
turns a compressed xz stream into a stream of uncompressed data. Create streams with (stream filename)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): input stream&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
	<entry>
		<id>https://www.memcp.org/index.php?title=Storage&amp;diff=358</id>
		<title>Storage</title>
		<link rel="alternate" type="text/html" href="https://www.memcp.org/index.php?title=Storage&amp;diff=358"/>
		<updated>2026-08-28T09:59:37Z</updated>

		<summary type="html">&lt;p&gt;Wikiservice: Refresh MemCP documentation: accuracy, operational guidance, performance profile and maintained API reference&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt;&lt;br /&gt;
&amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;storage&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
= Storage =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Generated from MemCP c42e19eba on 2026-08-27; do not edit manually. --&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;mw-message-box mw-message-box-notice&amp;quot;&amp;gt;Generated from MemCP commit &amp;lt;code&amp;gt;c42e19eba&amp;lt;/code&amp;gt; on 27 August 2026. See [[Full SCM API documentation]].&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;Storage&#039;&#039;&#039; module is the low-level data interface used by generated SQL plans. It manages databases, tables, columns, constraints, scans, indexes, RecSets, computed data, persistence, and schema lifecycle operations.&lt;br /&gt;
&lt;br /&gt;
Most application code should use SQL instead of calling these functions directly. Planner-generated calls rely on exact transaction, locking, callback, ownership, and quoting contracts. Functions that accept table handles or transaction contexts must not be replaced with direct access to shard internals.&lt;br /&gt;
&lt;br /&gt;
For the physical model see [[Columnar Storage]], [[Shards, RecordIDs, Main Storage, Delta Storage]], and [[Persistency and Performance Guarantees]].&lt;br /&gt;
&lt;br /&gt;
== table ==&lt;br /&gt;
&lt;br /&gt;
resolves a schema+table name pair into a table handle&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_estimate ==&lt;br /&gt;
&lt;br /&gt;
estimate output row count for a table scan&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-1&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== table_planner_statistics ==&lt;br /&gt;
&lt;br /&gt;
return the immutable O(1) planner-statistics snapshot for a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-2&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_selectivity_estimate ==&lt;br /&gt;
&lt;br /&gt;
bounded estimate of visible rows matching a table filter; stops at max_rows and does not log scan telemetry&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;condition_cols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to the selectivity predicate&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;condition&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): predicate sampled to estimate matching rows&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the sampled row matches&lt;br /&gt;
* &#039;&#039;&#039;max_rows&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-3&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;table_empty&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== table_empty? ==&lt;br /&gt;
&lt;br /&gt;
returns true if a table currently has no rows&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-4&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_recset ==&lt;br /&gt;
&lt;br /&gt;
builds a query-local record-set handle from one table scan, or -- when given an existing recset instead of a table -- narrows that recset to the members which also satisfy filter, re-evaluating filter only over its existing membership. The latter is the cheap way to AND a further (possibly subscan-heavy) condition onto an already-narrowed recset without re-touching rows outside it (e.g. evaluating an expensive correlated check only over the rows a cheap selective filter already narrowed a table down to). The returned value is not persisted and can be scanned like a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): a table, or an existing recset to narrow further&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a row enters the recset&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row belongs in the recset&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-5&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_count ==&lt;br /&gt;
&lt;br /&gt;
returns the number of currently stored recids in a query-local recset&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-6&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_project_join ==&lt;br /&gt;
&lt;br /&gt;
projects a source recset through key columns into a query-local target-table recset&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;source_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;source_key_columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;target_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;target_key_columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-7&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_key_index ==&lt;br /&gt;
&lt;br /&gt;
builds an immutable lookup function for key columns of the rows contained in a query-local recset&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context used while reading source keys&lt;br /&gt;
* &#039;&#039;&#039;source_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;source_key_columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-8&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;lookup&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): tests whether the recset contains a row with the supplied composite key&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each source key column, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;present&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether the composite key occurs in the recset&lt;br /&gt;
&lt;br /&gt;
== recset_union ==&lt;br /&gt;
&lt;br /&gt;
combines query-local recsets from the same table and removes duplicate record IDs&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recsets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-9&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_intersect ==&lt;br /&gt;
&lt;br /&gt;
intersects query-local recsets from the same table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recsets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-10&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_difference ==&lt;br /&gt;
&lt;br /&gt;
returns the records from the first query-local recset which occur in none of the following same-table recsets&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-11&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recsets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-11&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== recset_not ==&lt;br /&gt;
&lt;br /&gt;
returns the complement of a query-local recset relative to the currently visible rows of its base table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-12&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-12&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_exists ==&lt;br /&gt;
&lt;br /&gt;
returns true if a table contains at least one visible row matching the given filter; uses scan boundary analysis without map/reduce setup&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-13&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a row exists&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row satisfies the existence test&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-13&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan ==&lt;br /&gt;
&lt;br /&gt;
does an unordered parallel filter-map-reduce pass on a single table and returns the reduced result&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 6–10&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-14&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility and mutations; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;): table handle, query-local recset, or a list for temporary data&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a dataset is passed to the map phase. Equality and range comparisons may be translated into indexed scans&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row proceeds to map&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to map after filtering; pseudo columns are $update (update/delete current row), $recset_contains (row-bound RecSet membership), $set:&amp;lt;column&amp;gt;, $increment:&amp;lt;column&amp;gt;, and $invalidate:&amp;lt;column&amp;gt; (computed-column maintenance), plus NEW.&amp;lt;column&amp;gt; in trigger plans&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that extracts or produces one value from the row; it may also use documented pseudo columns for mutations or result output&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce, or returned directly when no reducer is supplied&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional aggregation function used first within shards and then to combine shard results &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for the reduce phase, otherwise nil is assumed &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;reduce2&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional final reducer that combines the neutral value with the result produced by reduce &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, in case of no hits, call map once anyway with NULL values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-14&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_batch ==&lt;br /&gt;
&lt;br /&gt;
does an unordered parallel filter-map-reduce pass on a single table using batchdata-backed #N pseudo columns and returns the reduced result&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 8–12&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-15&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility and mutations; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;): table handle, query-local recset, or a list for temporary data&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to filter; #0, #1, ... address batchdata slots&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a dataset is passed to the map phase&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when this table row and batch row proceed to map&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to map; #0, #1, ... address batchdata slots&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that extracts data from the table row and batch row&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce or returned directly&lt;br /&gt;
* &#039;&#039;&#039;stride&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): number of batchdata entries per batch row&lt;br /&gt;
* &#039;&#039;&#039;batchdata&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;any&amp;amp;gt;&amp;lt;/code&amp;gt;): flat batch buffer accessed via #N pseudo columns&lt;br /&gt;
** &#039;&#039;&#039;slot&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one batch value; every stride consecutive slots form a batch row&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional lambda function that aggregates mapped values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for the reduce phase, otherwise nil is assumed &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;reduce2&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional final reducer that combines the neutral value with the result produced by reduce &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, in case of no hits, call map once anyway with NULL values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-15&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_order_batch_accept ==&lt;br /&gt;
&lt;br /&gt;
incrementally scans a table or existing RecSet in scan_order order and applies a RecSet batch filter before OFFSET/LIMIT and map/reduce. The first candidate RecSet contains offset+limit rows; if too few rows are accepted, subsequent disjoint batches contain twice as many candidates until the accepted limit is satisfied or the input is exhausted. batchFilter is called as (batchFilter input_recset) and must return an exact subset RecSet of the same base table and transaction. A simple batchFilter may call (scan_recset tx input_recset filterColumns realFilter); complex filters may project input_recset to another table, apply search/ACL scans and project the result back to the input table. The returned RecSet is used only as a membership mask against the already ordered candidate vector, so output order is preserved without scanning the unordered RecSet again. For non-unique ORDER BY values, include an explicit unique tie-breaker. sortcols/sortdirs may both be empty; that path greedily collects candidates without sorting. limitPartitionCols is present for scan_order signature compatibility and currently must be 0&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 10–14&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-16&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context used consistently by the candidate scan and every batch filter operation; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table_or_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|recset&amp;lt;/code&amp;gt;): base table or complete existing query-local RecSet from which ordered candidate batches are drawn&lt;br /&gt;
* &#039;&#039;&#039;batchFilter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): function (lambda (input_recset) accepted_recset). It may naively narrow input_recset with scan_recset, or run arbitrary RecSet projections/search/ACL operations and project back. It must return a same-table, same-transaction subset of input_recset&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;input_recset&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;recset&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): same as scan_order: columns or computed sort functions. Include a unique tie-breaker for a total repeatable order; use an empty list for greedy unsorted collection&lt;br /&gt;
** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
* &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): same as scan_order: one relation per sort column; must also be empty when sortcols is empty&lt;br /&gt;
** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
**** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
* &#039;&#039;&#039;limitPartitionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): reserved for scan_order signature compatibility; currently must be 0&lt;br /&gt;
* &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of batch-filter-accepted rows to skip; it is not the number of driver candidates already examined&lt;br /&gt;
* &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): finite maximum number of accepted rows passed to map; the initial candidate batch size is offset+limit and doubles for every subsequent batch&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to map after filtering; pseudo columns are $update (update/delete current row), $recset_contains (row-bound RecSet membership), $set:&amp;lt;column&amp;gt;, $increment:&amp;lt;column&amp;gt;, and $invalidate:&amp;lt;column&amp;gt; (computed-column maintenance), plus NEW.&amp;lt;column&amp;gt; in trigger plans; $break is reserved for internal ORC convergence and must not implement SQL OFFSET/LIMIT, which belong in the native offset and limit arguments&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): same map callback contract as scan_order; accepted record IDs are passed to its shard mapper in batches&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce or returned directly&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional serial reducer over mapped accepted rows, with the same accumulator contract as scan_order &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): optional neutral element for reduce; defaults to nil &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): optional scan_order-compatible outer behavior: map one NULL row when no accepted row reaches map &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;notFoundValue&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): optional result when no accepted row reaches map and isOuter is false; defaults to neutral &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-16&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_order ==&lt;br /&gt;
&lt;br /&gt;
does an ordered parallel filter and serial map-reduce pass on a single table and returns the reduced result&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 11–17&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-17&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context to use for visibility and mutations; usually ((context &amp;amp;quot;session&amp;amp;quot;) &amp;amp;quot;__memcp_tx&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|list|recset&amp;lt;/code&amp;gt;): table handle, query-local RecSet, or a list for temporary data&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to filter before map/reduce; $recset_contains supplies a row-bound RecSet membership closure&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that decides whether a dataset is passed to the map phase. Equality and range comparisons may be translated into indexed scans&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row proceeds to ordering and map&lt;br /&gt;
* &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): columns used for ordering; each entry corresponds to one relation in sortdirs&lt;br /&gt;
** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
* &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): one ordering relation per entry in sortcols; &amp;amp;lt; is ascending and &amp;amp;gt; is descending&lt;br /&gt;
** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
**** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
* &#039;&#039;&#039;limitPartitionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of leading sort columns that form the partition key for per-partition offset/limit. 0 (default) means global offset/limit.&lt;br /&gt;
* &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of globally ordered, filter-accepted items to skip before map; apply SQL OFFSET here rather than in map&lt;br /&gt;
* &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): maximum globally ordered, filter-accepted items passed to map; -1 means unlimited; apply SQL LIMIT here so shard-local Top-K and the global merge can brake early&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): physical columns passed to map after filtering; pseudo columns are $update (update/delete current row), $recset_contains (row-bound RecSet membership), $set:&amp;lt;column&amp;gt;, $increment:&amp;lt;column&amp;gt;, and $invalidate:&amp;lt;column&amp;gt; (computed-column maintenance), plus NEW.&amp;lt;column&amp;gt; in trigger plans; $break is reserved for internal ORC convergence and must not implement SQL OFFSET/LIMIT, which belong in the native offset and limit arguments&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda function that extracts or produces one value from each accepted row&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reduce or returned directly&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional serial aggregation function over mapped values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for the reduce phase, otherwise nil is assumed &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, in case of no hits, call map once anyway with NULL values &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;notFoundValue&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) result for no hits when isOuter is false; defaults to neutral &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;postOrderFilterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): optional columns for a predicate evaluated in global order before OFFSET/LIMIT are counted; use for expensive acceptance checks that cannot participate in index boundaries &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;postOrderFilter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional late acceptance predicate. Rejected rows do not count toward OFFSET/LIMIT and never reach map &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the ordered row counts toward OFFSET/LIMIT and reaches map&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-17&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== scan_order_multi ==&lt;br /&gt;
&lt;br /&gt;
does an ordered parallel filter and serial map-reduce pass across multiple tables simultaneously, merging results into a single sorted stream&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 13–17&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-18&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;tx&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): transaction context&lt;br /&gt;
* &#039;&#039;&#039;tables&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;table|recset&amp;amp;gt;&amp;lt;/code&amp;gt;): scan sources; all per-table lists must have this length&lt;br /&gt;
** &#039;&#039;&#039;source&#039;&#039;&#039; (&amp;lt;code&amp;gt;table|recset&amp;lt;/code&amp;gt;): base table or query-local record set for one input stream&lt;br /&gt;
* &#039;&#039;&#039;filterColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;lt;string&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;): filter column lists, one per table&lt;br /&gt;
** &#039;&#039;&#039;table filter columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to the matching filterFns entry&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name in the corresponding table&lt;br /&gt;
* &#039;&#039;&#039;filterFns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(columns:any...) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): filter lambdas, one per table&lt;br /&gt;
** &#039;&#039;&#039;table filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): predicate for the corresponding table and filterColumns entry&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row enters that table&#039;s ordered stream&lt;br /&gt;
* &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;): sort column lists, one per table; every inner list must match sortdirs in length and result domains&lt;br /&gt;
** &#039;&#039;&#039;table sort columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): sort expressions for the corresponding table&lt;br /&gt;
*** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
**** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
* &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): shared ordering relations used for every table stream and for the outer merge&lt;br /&gt;
** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
**** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
* &#039;&#039;&#039;perTableOffset&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;int&amp;amp;gt;|nil&amp;lt;/code&amp;gt;): optional per-table offsets; nil disables all per-table offsets&lt;br /&gt;
** &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): rows skipped in the corresponding table before the outer merge; -1 disables the offset&lt;br /&gt;
* &#039;&#039;&#039;perTableLimit&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;int&amp;amp;gt;|nil&amp;lt;/code&amp;gt;): optional per-table limits; nil disables all per-table limits&lt;br /&gt;
** &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): maximum rows retained from the corresponding table before the outer merge; -1 disables the limit&lt;br /&gt;
* &#039;&#039;&#039;limitPartitionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of leading sort columns forming partition key&lt;br /&gt;
* &#039;&#039;&#039;offset&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of items to skip (global)&lt;br /&gt;
* &#039;&#039;&#039;limit&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): max number of items to read (global; -1 = unlimited)&lt;br /&gt;
* &#039;&#039;&#039;mapColumns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;lt;string&amp;amp;gt;&amp;amp;gt;&amp;lt;/code&amp;gt;): map column lists, one per table&lt;br /&gt;
** &#039;&#039;&#039;table map columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to the matching mapFns entry&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name in the corresponding table&lt;br /&gt;
* &#039;&#039;&#039;mapFns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): map lambdas, one per table&lt;br /&gt;
** &#039;&#039;&#039;table map&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): mapper for the corresponding table and mapColumns entry&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value inserted into the merged stream and passed to reduce&lt;br /&gt;
* &#039;&#039;&#039;reduce&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional aggregation function over mapped values from the merged stream &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
* &#039;&#039;&#039;neutral&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) neutral element for reduce &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;isOuter&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if true, emit null row when no hits &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;notFoundValue&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): (optional) result for no hits when isOuter is false; defaults to neutral &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-18&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createdatabase ==&lt;br /&gt;
&lt;br /&gt;
creates a new database&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-19&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new database&lt;br /&gt;
* &#039;&#039;&#039;ignoreexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, return false instead of throwing an error &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-19&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropdatabase ==&lt;br /&gt;
&lt;br /&gt;
drops a database&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-20&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, don&#039;t throw an error if it doesn&#039;t exist &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-20&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== checktablemaintenance ==&lt;br /&gt;
&lt;br /&gt;
checks whether a user-initiated maintenance operation is allowed for a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-21&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-21&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== maintenance_capabilities ==&lt;br /&gt;
&lt;br /&gt;
returns the server-side maintenance capabilities for a database or table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-22&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-22&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createtable ==&lt;br /&gt;
&lt;br /&gt;
creates a table, runs its oninit option and registered after-create-table lifecycle triggers synchronously, and returns only after initialization completes; concurrent if-not-exists callers wait for that same completion&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-23&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the existing database that will contain the table&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table to create&lt;br /&gt;
* &#039;&#039;&#039;cols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;list&amp;amp;gt;&amp;lt;/code&amp;gt;): column and constraint definitions&lt;br /&gt;
** &#039;&#039;&#039;definition&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): one of (&amp;amp;quot;column&amp;amp;quot; name type dimensions typeparams), (&amp;amp;quot;unique&amp;amp;quot; name columns), or (&amp;amp;quot;foreign&amp;amp;quot; name local_columns referenced_table referenced_columns update_mode delete_mode). Column lists contain strings; foreign-key modes are restrict, cascade, or set null. A column definition&#039;s dimensions contains integers and its typeparams uses the same fields documented by createcolumn options&lt;br /&gt;
* &#039;&#039;&#039;options&#039;&#039;&#039; (&amp;lt;code&amp;gt;list|assoc&amp;lt;/code&amp;gt;): table options as an alternating key/value list&lt;br /&gt;
** &#039;&#039;&#039;auto_increment&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): first automatically assigned value; must be non-negative&lt;br /&gt;
** &#039;&#039;&#039;charset&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): default character set name&lt;br /&gt;
** &#039;&#039;&#039;collation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): default collation name&lt;br /&gt;
** &#039;&#039;&#039;comment&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): user-visible table comment&lt;br /&gt;
** &#039;&#039;&#039;engine&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): storage engine: safe, logged, sloppy, memory, or cache&lt;br /&gt;
** &#039;&#039;&#039;oninit&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): closed zero-argument initializer run synchronously once per data generation; concurrent if-not-exists callers wait for completion&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): ignored initializer result&lt;br /&gt;
* &#039;&#039;&#039;ifnotexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): when true, return false instead of failing if the table exists; if another caller is still creating it, wait for that caller&#039;s after-create-table initialization before returning false &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-23&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when this call created and initialized the table, false when ifnotexists reused an initialized table&lt;br /&gt;
&lt;br /&gt;
== createcolumn ==&lt;br /&gt;
&lt;br /&gt;
creates a new column in table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–7&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-24&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;colname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new column&lt;br /&gt;
* &#039;&#039;&#039;type&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the basetype&lt;br /&gt;
* &#039;&#039;&#039;dimensions&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;int&amp;amp;gt;&amp;lt;/code&amp;gt;): dimensions of the type, for example precision and scale for decimal&lt;br /&gt;
** &#039;&#039;&#039;dimension&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): one type-specific dimension&lt;br /&gt;
* &#039;&#039;&#039;options&#039;&#039;&#039; (&amp;lt;code&amp;gt;list|assoc&amp;lt;/code&amp;gt;): column properties and computed-column configuration as an alternating key/value list&lt;br /&gt;
** &#039;&#039;&#039;auto_increment&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): assign increasing values automatically&lt;br /&gt;
** &#039;&#039;&#039;collate&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): collation used for this column&lt;br /&gt;
** &#039;&#039;&#039;comment&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): user-visible column comment&lt;br /&gt;
** &#039;&#039;&#039;default&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): literal value used when an insert omits the column&lt;br /&gt;
** &#039;&#039;&#039;default_expression&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): expression evaluated when an insert omits the column&lt;br /&gt;
** &#039;&#039;&#039;filter&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): predicate limiting which rows are computed&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when the row should be computed&lt;br /&gt;
** &#039;&#039;&#039;filtercols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to filter before computing a value&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
** &#039;&#039;&#039;mapcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns supplied to mapfn for ordered-reduce computation&lt;br /&gt;
*** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
** &#039;&#039;&#039;mapfn&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): maps one source row into a value for reducefn&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value passed to reducefn&lt;br /&gt;
** &#039;&#039;&#039;null&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether the column accepts nil values&lt;br /&gt;
** &#039;&#039;&#039;partitioncount&#039;&#039;&#039; (&amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt;): number of leading sort columns that define independent reducer partitions&lt;br /&gt;
** &#039;&#039;&#039;primary&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether this column belongs to the primary key&lt;br /&gt;
** &#039;&#039;&#039;reducefn&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): combines ordered mapped values into the computed-column aggregate &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): current aggregate, initially the neutral value&lt;br /&gt;
**** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): next mapped or partially reduced value&lt;br /&gt;
*** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;accumulator&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): aggregate passed to the next reducer call or returned by the scan&lt;br /&gt;
** &#039;&#039;&#039;reduceinit&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): initial accumulator supplied to reducefn&lt;br /&gt;
** &#039;&#039;&#039;sortcols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string|func(columns:any...) -&amp;amp;gt; any&amp;amp;gt;&amp;lt;/code&amp;gt;): columns or expressions defining ordered-reduce input order&lt;br /&gt;
*** &#039;&#039;&#039;sort column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|func&amp;lt;/code&amp;gt;): a column name, or a function of row-column values that returns the sortable value&lt;br /&gt;
**** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): column values used to compute the sort key &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;sort key&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): value compared at this sort position&lt;br /&gt;
** &#039;&#039;&#039;sortdirs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;func(left:any, right:any) -&amp;amp;gt; bool&amp;amp;gt;&amp;lt;/code&amp;gt;): one ordering relation for every sortcols entry&lt;br /&gt;
*** &#039;&#039;&#039;direction&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): strict ordering relation such as &amp;amp;lt;, &amp;amp;gt;, or a collate relation&lt;br /&gt;
**** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;left&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): left sort value&lt;br /&gt;
***** &#039;&#039;&#039;right&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): right sort value&lt;br /&gt;
**** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
***** &#039;&#039;&#039;ordered&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true when left belongs before right&lt;br /&gt;
** &#039;&#039;&#039;temp&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether this is a query-local temporary computed column&lt;br /&gt;
** &#039;&#039;&#039;unique&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether values must be unique&lt;br /&gt;
** &#039;&#039;&#039;update&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): expression evaluated when a row is updated&lt;br /&gt;
* &#039;&#039;&#039;computorCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;amp;lt;string&amp;amp;gt;&amp;lt;/code&amp;gt;): columns passed to computor in this order &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name passed to the corresponding callback parameter&lt;br /&gt;
* &#039;&#039;&#039;computor&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): lambda expression that computes this column from the values selected by computorCols &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each entry in the matching column list, in the same order &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): computed column value&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-24&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createkey ==&lt;br /&gt;
&lt;br /&gt;
creates a new key on a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-25&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;keyname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new key&lt;br /&gt;
* &#039;&#039;&#039;unique&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether the key is unique&lt;br /&gt;
* &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns to include&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-25&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropkey ==&lt;br /&gt;
&lt;br /&gt;
drops a named unique key from a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-26&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;keyname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the unique key&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-26&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createforeignkey ==&lt;br /&gt;
&lt;br /&gt;
creates a new foreign key on a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 7–7&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-27&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table1&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;keyname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the new key&lt;br /&gt;
* &#039;&#039;&#039;columns1&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns to include&lt;br /&gt;
* &#039;&#039;&#039;table2&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;columns2&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns to include&lt;br /&gt;
* &#039;&#039;&#039;updatemode&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): restrict|cascade|set null&lt;br /&gt;
* &#039;&#039;&#039;deletemode&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): restrict|cascade|set null&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-27&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== shardcolumn ==&lt;br /&gt;
&lt;br /&gt;
tells us how it would partition a column according to their values. Returns a list of pivot elements.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-28&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;colname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the column&lt;br /&gt;
* &#039;&#039;&#039;numpartitions&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): number of partitions; optional. leave 0 if you want to detect the partiton number automatically or copy the partition schema of the table &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-28&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== partitiontable ==&lt;br /&gt;
&lt;br /&gt;
suggests a partition scheme for a table. If the table has no partition scheme yet, it will immediately apply that scheme and return true. If the table already has a partition scheme, it will alter the partitioning score such that the partitioning scheme is considered in the next repartitioning and return false.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-29&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): associative list of string -&amp;amp;gt; list representing column name -&amp;amp;gt; pivots. You can compute pivots by (shardcolumn ...)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-29&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== altertable ==&lt;br /&gt;
&lt;br /&gt;
alters a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-30&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): one of owner|drop|engine|collation|auto_increment&lt;br /&gt;
* &#039;&#039;&#039;parameter&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): name of the column to drop or value of the parameter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-30&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== altercolumn ==&lt;br /&gt;
&lt;br /&gt;
alters a column&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-31&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the column&lt;br /&gt;
* &#039;&#039;&#039;operation&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): one of drop|type|collation|auto_increment|comment&lt;br /&gt;
* &#039;&#039;&#039;parameter&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): name of the column to drop or value of the parameter&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-31&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== droptable ==&lt;br /&gt;
&lt;br /&gt;
removes a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-32&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, don&#039;t throw an error if it already exists &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-32&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropcolumn ==&lt;br /&gt;
&lt;br /&gt;
drops a column from a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-33&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the column to drop&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-33&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== migratedropcolumn ==&lt;br /&gt;
&lt;br /&gt;
drops a legacy system column during startup migration&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-34&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): legacy column name&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-34&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== invalidatecolumn ==&lt;br /&gt;
&lt;br /&gt;
marks all values of a computed column as stale&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-35&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the computed column&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-35&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== invalidateorc ==&lt;br /&gt;
&lt;br /&gt;
invalidates ORC column rows from a sort key onwards via validMask scan&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-36&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the ORC column&lt;br /&gt;
* &#039;&#039;&#039;sortkeys&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): composite sort key values from which to invalidate&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-36&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== register_keytable_cleanup ==&lt;br /&gt;
&lt;br /&gt;
registers triggers on a base table to maintain keytable entries (insert/delete group keys)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-37&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;base_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;kt_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;tblvar&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): table alias used in scan column prefixes&lt;br /&gt;
* &#039;&#039;&#039;key_pairs&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of (base_col kt_col) pairs&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-37&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== initialize_cache_table ==&lt;br /&gt;
&lt;br /&gt;
registers maintenance, locks source tables for a consistent snapshot, and runs a canonical planner-cache initializer exactly once&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 5–6&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-38&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;transaction&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): explicit transaction context carrying query-session ownership&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;source_tables&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;register_maintenance&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;initializer&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;)&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;finalizer&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): optional zero-argument finalizer run under the same source-table locks after initialization &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-38&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== touch_keytable ==&lt;br /&gt;
&lt;br /&gt;
extends the lease on a keytable so CacheManager defers eviction&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-39&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-39&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== locktables ==&lt;br /&gt;
&lt;br /&gt;
acquires WRITE or READ user-level locks on a list of tables (LOCK TABLES); implicitly releases any previously held locks&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–1&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-40&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;locks&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): flat list of schema, table, write? triples&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-40&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== unlocktables ==&lt;br /&gt;
&lt;br /&gt;
releases all user-level table locks held by this session&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-41&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-41&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== get_fk_target ==&lt;br /&gt;
&lt;br /&gt;
returns (ref_table ref_column) if a single-column FK exists for the given column, nil otherwise&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-42&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-42&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== renametable ==&lt;br /&gt;
&lt;br /&gt;
renames a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-43&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;oldname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): current name of the table&lt;br /&gt;
* &#039;&#039;&#039;newname&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): new name of the table&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-43&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== insert ==&lt;br /&gt;
&lt;br /&gt;
inserts a new dataset into table and returns the number of successful items&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–7&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-44&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;columns&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of column names, e.g. &#039;(&amp;amp;quot;ID&amp;amp;quot;, &amp;amp;quot;value&amp;amp;quot;)&lt;br /&gt;
* &#039;&#039;&#039;datasets&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of list of column values, e.g. &#039;(&#039;(1 10) &#039;(2 15))&lt;br /&gt;
* &#039;&#039;&#039;onCollisionCols&#039;&#039;&#039; (&amp;lt;code&amp;gt;list&amp;lt;/code&amp;gt;): list of columns of the old dataset that have to be passed to onCollision. Can also request $update, $set:&amp;lt;computed-column&amp;gt;, or NEW.&amp;lt;insert-column&amp;gt;. &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;onCollision&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): function called for each collision. Its positional parameters are the values requested by onCollisionCols, in the same order. If omitted, collisions raise an error. &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;column values&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): one value for each onCollisionCols entry &#039;&#039;(variadic)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;mergeNull&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): if true, it will handle NULL values as equal according to SQL 2003&#039;s definition of DISTINCT (https://en.wikipedia.org/wiki/Null_(SQL)#When_two_nulls_are_equal:_grouping,_sorting,_and_some_set_operations) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;onInsertid&#039;&#039;&#039; (&amp;lt;code&amp;gt;func&amp;lt;/code&amp;gt;): called once with the first auto_increment id assigned for this INSERT &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
** &#039;&#039;&#039;Parameters&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;id&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;): first assigned auto_increment id&lt;br /&gt;
** &#039;&#039;&#039;Returns&#039;&#039;&#039;&lt;br /&gt;
*** &#039;&#039;&#039;result&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): ignored callback result&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-44&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== stat ==&lt;br /&gt;
&lt;br /&gt;
return system statistics as assoc: mem_available, mem_total, process_memory, shard_memory, shard_budget, persisted_memory, persisted_budget, cache_entry_count, cache_entry_size. (stat schema) and (stat schema tbl) return a string with detailed memory usage.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-45&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) database name for detailed string output &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) table name for detailed string output &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-45&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== totalmem ==&lt;br /&gt;
&lt;br /&gt;
Returns total physical memory in bytes (from /proc/meminfo)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-46&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;This function has no parameters.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-46&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;number&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== resolve_column_name ==&lt;br /&gt;
&lt;br /&gt;
resolve a physical column name from immutable table metadata&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-47&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): database name&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): table name&lt;br /&gt;
* &#039;&#039;&#039;column&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): column name&lt;br /&gt;
* &#039;&#039;&#039;ignorecase&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): whether identifier case is ignored&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-47&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== show ==&lt;br /&gt;
&lt;br /&gt;
show databases/tables/columns/shards&lt;br /&gt;
&lt;br /&gt;
(show) lists database names (show schema) lists table names (show table_handle) lists the memoized column defs (show table_handle true) returns table metadata (show table_handle &amp;amp;quot;statistics&amp;amp;quot;) returns index statistics (show schema true) lists tables with full info: [{name,engine,row_count,size_bytes,collation,comment},...] (show schema tbl) lists column defs (show schema tbl true) returns assoc {columns,meta,shards} (show schema tbl N) returns shard N overview assoc {shard,state,main_count,delta,deletions,size_bytes} (show schema tbl N true) returns shard N full assoc adding columns and indexes (show schema tbl &amp;amp;quot;statistics&amp;amp;quot;) returns INFORMATION_SCHEMA index statistics (show schema tbl &amp;amp;quot;indexes&amp;amp;quot;) returns MySQL SHOW INDEX rows&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-48&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema_or_table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|table|recset&amp;lt;/code&amp;gt;): (optional) database name or resolved table/recset handle &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;table_or_property&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|bool&amp;lt;/code&amp;gt;): (optional) table name, true for full info, or &amp;amp;quot;statistics&amp;amp;quot; for a handle &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;property&#039;&#039;&#039; (&amp;lt;code&amp;gt;int|bool|string&amp;lt;/code&amp;gt;): (optional) shard index (int), true for full table info, or &amp;amp;quot;statistics&amp;amp;quot; &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;full&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) true to include columns and indexes in shard detail &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-48&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== show_triggers ==&lt;br /&gt;
&lt;br /&gt;
show triggers for a given table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 1–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-49&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): database name&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) table name, if omitted shows all triggers in schema &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-49&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== rebuild ==&lt;br /&gt;
&lt;br /&gt;
rebuilds main storages and returns the amount of time it took; with a table handle, rebuilds only that table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-50&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table_or_all&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool|table&amp;lt;/code&amp;gt;): table handle for a table-local rebuild; otherwise whether to rebuild unchanged shards globally (default: false) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;all_or_repartition&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): with a table: whether to rebuild unchanged shards; globally: whether to repartition (default: true) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;repartition&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): with a table handle, whether to repartition that table (default: true) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-50&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;loadcsv&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== loadCSV ==&lt;br /&gt;
&lt;br /&gt;
loads a CSV stream into a table and returns the amount of time it took. The first line of the file must be the headlines. The headlines must match the table&#039;s columns exactly.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–5&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-51&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): CSV file, load with: (stream filename)&lt;br /&gt;
* &#039;&#039;&#039;delimiter&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): (optional) delimiter defaults to &amp;amp;quot;;&amp;amp;quot; &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;firstline&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): (optional) if the first line contains the column names (otherwise, the tables column order is used) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-51&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;loadjson&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
== loadJSON ==&lt;br /&gt;
&lt;br /&gt;
loads a .jsonl file from stream into a database and returns the amount of time it took. JSONL is a linebreak separated file of JSON objects. Each JSON object is one dataset in the database. Before you add rows, you must declare the table in a line &#039;#table &amp;lt;tablename&amp;gt;&#039;. All other lines starting with # are comments. Columns are created dynamically as soon as they occur in a json object.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 2–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-52&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database where you want to put the tables in&lt;br /&gt;
* &#039;&#039;&#039;stream&#039;&#039;&#039; (&amp;lt;code&amp;gt;stream&amp;lt;/code&amp;gt;): stream of the .jsonl file, read with: (stream filename)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-52&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== settings ==&lt;br /&gt;
&lt;br /&gt;
reads or writes a global settings value. This modifies your data/settings.json.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 0–2&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-53&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;key&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the key to set or get (for reference, rts) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): new value of that setting &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-53&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createcreatetabletrigger ==&lt;br /&gt;
&lt;br /&gt;
registers a lifecycle trigger that fires synchronously after a future createtable for the given schema/table succeeds&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 6–6&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-54&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table to watch for creation&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;source_sql&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): original SQL body text (for diagnostics)&lt;br /&gt;
* &#039;&#039;&#039;body&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): trigger body (Scheme procedure or deferred trigger expression)&lt;br /&gt;
* &#039;&#039;&#039;visible&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true = user trigger, false = internal trigger&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-54&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== dropcreatetabletrigger ==&lt;br /&gt;
&lt;br /&gt;
removes a registered create-table lifecycle trigger&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–4&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-55&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the table watched for creation&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): don&#039;t throw error if trigger doesn&#039;t exist&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-55&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== createtrigger ==&lt;br /&gt;
&lt;br /&gt;
creates a new trigger on a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 6–6&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-56&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;table&#039;&#039;&#039; (&amp;lt;code&amp;gt;table&amp;lt;/code&amp;gt;)&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;timing&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): one of: before_insert, after_insert, before_update, after_update, before_delete, after_delete&lt;br /&gt;
* &#039;&#039;&#039;source_sql&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): original SQL body text (for SHOW TRIGGERS)&lt;br /&gt;
* &#039;&#039;&#039;body&#039;&#039;&#039; (&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt;): trigger body (parsed Scheme expression)&lt;br /&gt;
* &#039;&#039;&#039;visible&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): true = user trigger (shown in SHOW TRIGGERS), false = internal trigger (hidden)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-56&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== droptrigger ==&lt;br /&gt;
&lt;br /&gt;
removes a trigger from a table&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 3–3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-57&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;schema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the database&lt;br /&gt;
* &#039;&#039;&#039;name&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): name of the trigger&lt;br /&gt;
* &#039;&#039;&#039;ifexists&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;): don&#039;t throw error if trigger doesn&#039;t exist&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-57&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== mysql_import ==&lt;br /&gt;
&lt;br /&gt;
imports schema+data from a MySQL server into MemCP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–8&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-58&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;host&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): MySQL host (nil =&amp;amp;gt; 127.0.0.1)&lt;br /&gt;
* &#039;&#039;&#039;port&#039;&#039;&#039; (&amp;lt;code&amp;gt;int|nil&amp;lt;/code&amp;gt;): MySQL port (nil =&amp;amp;gt; 3306)&lt;br /&gt;
* &#039;&#039;&#039;username&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): MySQL username&lt;br /&gt;
* &#039;&#039;&#039;password&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): MySQL password&lt;br /&gt;
* &#039;&#039;&#039;sourcedb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source database (omit/nil =&amp;amp;gt; all non-system dbs) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targetdb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target database (omit/nil =&amp;amp;gt; sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sourcetable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source table (omit/nil =&amp;amp;gt; all tables in sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targettable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target table (omit/nil =&amp;amp;gt; sourcetable) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-58&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== psql_import ==&lt;br /&gt;
&lt;br /&gt;
imports schema+data from a PostgreSQL server into MemCP&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Allowed number of parameters:&#039;&#039;&#039; 4–9&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;parameters-59&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Parameters ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;host&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): PostgreSQL host (nil =&amp;amp;gt; 127.0.0.1)&lt;br /&gt;
* &#039;&#039;&#039;port&#039;&#039;&#039; (&amp;lt;code&amp;gt;int|nil&amp;lt;/code&amp;gt;): PostgreSQL port (nil =&amp;amp;gt; 5432)&lt;br /&gt;
* &#039;&#039;&#039;username&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): PostgreSQL username&lt;br /&gt;
* &#039;&#039;&#039;password&#039;&#039;&#039; (&amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;): PostgreSQL password&lt;br /&gt;
* &#039;&#039;&#039;sourcedb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source database (omit/nil =&amp;amp;gt; all non-system dbs) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sourceschema&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source schema (omit/nil =&amp;amp;gt; all non-system schemas in sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targetdb&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target database (omit/nil =&amp;amp;gt; sourcedb) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;sourcetable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): source table (omit/nil =&amp;amp;gt; all tables in sourceschema) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;targettable&#039;&#039;&#039; (&amp;lt;code&amp;gt;string|nil&amp;lt;/code&amp;gt;): target table (omit/nil =&amp;amp;gt; sourcetable) &#039;&#039;(optional)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;span id=&amp;quot;returns-59&amp;quot;&amp;gt;&amp;lt;/span&amp;gt;&lt;br /&gt;
=== Returns ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;value&#039;&#039;&#039; (&amp;lt;code&amp;gt;bool&amp;lt;/code&amp;gt;)&lt;/div&gt;</summary>
		<author><name>Wikiservice</name></author>
	</entry>
</feed>