<?xml version="1.0"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/">
	<channel>
		<title>MemCP  - Recent changes [en]</title>
		<link>https://www.memcp.org/wiki/Special:RecentChanges</link>
		<description>Track the most recent changes to the wiki in this feed.</description>
		<language>en</language>
		<generator>MediaWiki 1.39.1</generator>
		<lastBuildDate>Mon, 12 Oct 2026 01:43:11 GMT</lastBuildDate>
		<item>
			<title>T-SQL mode</title>
			<link>https://www.memcp.org/index.php?title=T-SQL_mode&amp;diff=425&amp;oldid=0</link>
			<guid isPermaLink="false">https://www.memcp.org/index.php?title=T-SQL_mode&amp;diff=425&amp;oldid=0</guid>
			<description>&lt;p&gt;Created page with &amp;quot;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Haensch --&amp;gt; &amp;lt;!-- SPDX-License-Identifier: GPL-3.0-or-later --&amp;gt; = T-SQL mode =  &amp;lt;blockquote&amp;gt;Development preview from [https://github.com/launix-de/memcp/pull/1057 PR #1057], inspected at commit &amp;lt;code&amp;gt;fed54d227ca73e7878be1186712bbfd0dc2c9038&amp;lt;/code&amp;gt;. This describes source capabilities, not a released or certified application installation. Use the eventual tested candidate and its matching libraries.&amp;lt;/blockquote&amp;gt;  MemCP&amp;#039;s t-sql mode adds a...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&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;
= T-SQL mode =&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Development preview from [https://github.com/launix-de/memcp/pull/1057 PR #1057], inspected at commit &amp;lt;code&amp;gt;fed54d227ca73e7878be1186712bbfd0dc2c9038&amp;lt;/code&amp;gt;. This describes source capabilities, not a released or certified application installation. Use the eventual tested candidate and its matching libraries.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
MemCP&amp;#039;s t-sql mode adds a SQL syntax frontend, an HTTP endpoint and an optional TDS 7.4 listener. It uses the same planner, columnar storage, transactions, user catalog and access policies as the existing interfaces. It is a compatibility subset for evaluating applications; SQL and client metadata must be checked against the application&amp;#039;s actual driver and workflows.&lt;br /&gt;
&lt;br /&gt;
== Start an isolated evaluation ==&lt;br /&gt;
&lt;br /&gt;
Keep the executable and &amp;lt;code&amp;gt;lib/&amp;lt;/code&amp;gt; from the same commit. Start in the candidate directory with a fresh data directory:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./memcp --no-repl -data ./evaluation-data   --api-port=4321 --disable-mysql   --tsql-port=1433 --tsql-database=evaluation   --root-password=&amp;#039;replace-with-a-strong-password&amp;#039;   lib/main.scm &amp;gt; evaluation-server.log 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The TDS listener is off by default. &amp;lt;code&amp;gt;--tsql-port&amp;lt;/code&amp;gt; enables it; &amp;lt;code&amp;gt;--tsql-database&amp;lt;/code&amp;gt; selects its default database, which is created at startup if needed. &amp;lt;code&amp;gt;TSQL_PORT&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TSQL_DATABASE&amp;lt;/code&amp;gt; provide environment settings. &amp;lt;code&amp;gt;--disable-tsql&amp;lt;/code&amp;gt; disables the listener even when a port is configured.&lt;br /&gt;
&lt;br /&gt;
Connect directly to the host and TCP port, select &amp;lt;code&amp;gt;evaluation&amp;lt;/code&amp;gt;, and use an existing MemCP username and password. Password storage and database access policies are shared; no separate TDS account migration is needed. The root password flag initializes a fresh directory only. Test with an application account that has the intended permissions.&lt;br /&gt;
&lt;br /&gt;
For TLS 1.2, supply both &amp;lt;code&amp;gt;--tsql-tls-cert=cert.pem&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;--tsql-tls-key=key.pem&amp;lt;/code&amp;gt;, and configure the client to trust the certificate. Without a certificate, select an unencrypted connection explicitly and restrict the network. Integrated authentication and instance discovery are unsupported.&lt;br /&gt;
&lt;br /&gt;
== Syntax and types ==&lt;br /&gt;
&lt;br /&gt;
* Bracket and double-quoted identifiers are supported. A closing bracket inside a bracketed identifier is doubled: &amp;lt;code&amp;gt;[a]]b]&amp;lt;/code&amp;gt;. Table, column and view lookup is case-independent while declared spelling is preserved. This does not imply complete text-collation equivalence.&lt;br /&gt;
* Unicode strings such as &amp;lt;code&amp;gt;N&amp;#039;Grüße&amp;#039;&amp;lt;/code&amp;gt;, raw hexadecimal bytes such as &amp;lt;code&amp;gt;0x0102&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;TOP&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;OFFSET … FETCH&amp;lt;/code&amp;gt;, DISTINCT, joins, supported subqueries, grouping and basic windows are available.&lt;br /&gt;
* INSERT/UPDATE/DELETE, CREATE TABLE/VIEW, alias types and &amp;lt;code&amp;gt;IDENTITY(1,1)&amp;lt;/code&amp;gt; use the common engine. Each database exposes &amp;lt;code&amp;gt;dbo&amp;lt;/code&amp;gt;; &amp;lt;code&amp;gt;database.dbo.table&amp;lt;/code&amp;gt; can address another MemCP database outside the import loader&amp;#039;s confined retargeting rules.&lt;br /&gt;
* DECIMAL/NUMERIC retain up to 38 digits. MONEY/SMALLMONEY retain fixed currency scale and range. Unary minus preserves precision, scale and currency type; negating TINYINT produces SMALLINT. Integer division and integer AVG follow declared t-sql types.&lt;br /&gt;
* DATETIME retains 1/300-second ticks; TIME and DATETIME2 retain fractional precision through results, storage and TDS. Supported casts, CONVERT styles, DATEADD/DATEDIFF/DATEPART and NCHAR cover common expressions. Unsupported types and conversion styles fail explicitly.&lt;br /&gt;
&lt;br /&gt;
== IDENTITY and ROWVERSION ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;@@IDENTITY&amp;lt;/code&amp;gt; returns the most recent generated value in the session. &amp;lt;code&amp;gt;SCOPE_IDENTITY()&amp;lt;/code&amp;gt; refers to the current batch or prepared RPC scope. Allocation checks the declared type and uses a signed 64-bit counter, including zero-scale decimal identities. Identity columns are non-nullable and cannot be updated. Rollback consumes allocated values; gaps are expected.&lt;br /&gt;
&lt;br /&gt;
ROWVERSION is an automatically generated eight-byte binary token, not a timestamp or a row address. Declare it explicitly in CREATE TABLE. Only that declared table column activates persisted synchronous insert/update hooks; ordinary tables gain no generated column or hooks. Every matched update, including a no-op update, changes the token. An update matching no rows consumes no token. Rollback restores the row while consuming the allocated token. The sequence&amp;#039;s high-water reservation is durable across restart.&lt;br /&gt;
&lt;br /&gt;
Applications can implement optimistic edits with a bound original token:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
UPDATE dbo.records&lt;br /&gt;
SET label = @new_label&lt;br /&gt;
WHERE id = @id AND rv = @original_rv&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Check the affected row count: zero means that the original version no longer matches or the row is absent. Bind the token as eight raw bytes. Do not infer a token from a physical shard ID and record ID: updates and rebuilds have different identity semantics.&lt;br /&gt;
&lt;br /&gt;
Adding ROWVERSION to an existing table is currently unsupported and fails explicitly. Existing rows and write hooks need atomic initialization/backfill before that operation can be offered.&lt;br /&gt;
&lt;br /&gt;
== Keys and constraints ==&lt;br /&gt;
&lt;br /&gt;
Primary and unique keys and named/composite foreign keys enforce real constraints. Primary-key constraint names normalize to &amp;lt;code&amp;gt;PRIMARY&amp;lt;/code&amp;gt;; DROP CONSTRAINT currently supports foreign keys only. CREATE requires an existing parent with a matching ordered candidate key. Adding a foreign key through ALTER requires a physically empty child table. NO ACTION, CASCADE and SET NULL are supported. Character foreign keys use byte-exact matching. Self/forward/cross-database references, unchecked constraints and SET DEFAULT are unsupported.&lt;br /&gt;
&lt;br /&gt;
== Client protocol and metadata ==&lt;br /&gt;
&lt;br /&gt;
The TDS adapter supports SQL logins, semicolon-separated batches, multiple results, transaction-manager requests, cancellation, connection reset, &amp;lt;code&amp;gt;sp_executesql&amp;lt;/code&amp;gt;, prepared execute/describe/unprepare RPCs and bounded read-only STATIC cursors. Input bindings cover supported numeric, exact decimal/currency, Unicode/text, binary and temporal types; values remain separate from SQL text.&lt;br /&gt;
&lt;br /&gt;
Read-only &amp;lt;code&amp;gt;sys.types&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sys.tables&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sys.objects&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;sys.columns&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;sys.schemas&amp;lt;/code&amp;gt;, plus OBJECT_ID/TYPE_ID/COL_LENGTH and ODBC discovery, expose actual declaration metadata. Declared result types survive empty and all-NULL results. Direct base columns retain nullability and editability. FOR BROWSE adds source/key metadata for a single base table when all primary-key columns are projected; derived results and static cursors remain read-only. A complete system catalog and view object identities remain outside this subset.&lt;br /&gt;
&lt;br /&gt;
== SQL over HTTP ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl --fail-with-body -u app_user:strong-password   -H &amp;#039;Content-Type: text/plain; charset=utf-8&amp;#039;   --data-binary &amp;#039;SELECT TOP (10) [id], [label] FROM [dbo].[records] ORDER BY [id]&amp;#039;   http://localhost:4321/tsql/evaluation&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Submit one statement per request. Row results are newline-delimited JSON. HTTP uses the existing Basic authentication and access policies. Keep tests of RPCs, cursor behavior, driver metadata and binary bindings on the actual TDS connection. See [[SQL over REST]].&lt;br /&gt;
&lt;br /&gt;
== Import an export script ==&lt;br /&gt;
&lt;br /&gt;
Create a schema-and-data SQL export containing supported DDL and INSERT statements. Invoke the loader in the Scheme console or the admin-only &amp;lt;code&amp;gt;/scm&amp;lt;/code&amp;gt; endpoint:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
(load_tsql &amp;quot;evaluation&amp;quot; &amp;quot;/path/to/export.sql&amp;quot; (sql_policy &amp;quot;root&amp;quot;))&lt;br /&gt;
(load_tsql &amp;quot;evaluation&amp;quot; &amp;quot;/path/to/export.sql.gz&amp;quot; (sql_policy &amp;quot;root&amp;quot;))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The loader accepts UTF-8, BOM-marked UTF-16 and gzip, recognizes GO separators outside quoted values, and supports line-start INSERT/SET/DDL boundaries in exports without semicolons. Statement buffers are limited to 16 MiB. GO belongs to the script loader, not the query endpoint.&lt;br /&gt;
&lt;br /&gt;
CREATE DATABASE/USE headers select a source alias; supported references are confined to the chosen destination without rewriting string values. References to another source database fail. Explicit identity values advance the counter; IDENTITY_INSERT export switches are accepted by the loader. Clustered/nonclustered key declarations enforce uniqueness without selecting a physical layout.&lt;br /&gt;
&lt;br /&gt;
Statements execute in order. An error stops further statements; prior commits remain. An unfinished explicit transaction is rolled back and reported. Existing tables are replaced only by an explicit DROP. Repeat a failed import into a fresh destination. Create parents first and declare supported foreign keys before inserting child rows; adding them to populated child tables is unsupported.&lt;br /&gt;
&lt;br /&gt;
Native backup/package files and bulk-copy formats have no reader. This mode has no live source importer analogous to the existing live importers. See [[Migration from MySQL and PostgreSQL]] for shared validation steps.&lt;br /&gt;
&lt;br /&gt;
== Known limits ==&lt;br /&gt;
&lt;br /&gt;
Integrated authentication, instance discovery, MARS, bulk copy, writable/dynamic/keyset cursors, arbitrary stored procedures, output parameters, named/nested transactions, extra schemas, CTE/APPLY, explicit window frames, ordered aggregate windows, TRUNCATE TABLE and TOP PERCENT/WITH TIES are unsupported. Explicit text-collation declarations and full session-option equivalence are not implemented. Unsupported forms should fail explicitly; accepting a connection or a simple SELECT does not prove an application&amp;#039;s full installer is compatible.&lt;br /&gt;
&lt;br /&gt;
== Plan an application test ==&lt;br /&gt;
&lt;br /&gt;
# Record the exact candidate commit, binary checksum, matching libraries, client version and connection settings.&lt;br /&gt;
# Verify login, SELECT 1, Unicode, parameter binding, empty-result metadata and catalog discovery using the actual client stack.&lt;br /&gt;
# Run installation first; retain the first failing statement, declared parameter types, bindings, session settings, transaction order, SQLSTATE and server log.&lt;br /&gt;
# Exercise read/create/edit/cancel and two concurrent edits of one record; compare decimal/currency and date results with the source.&lt;br /&gt;
# Commit and roll back, restart, and verify committed rows and generated counters. Compare import counts/checksums and constraints.&lt;br /&gt;
&lt;br /&gt;
Keep original traces private and publish only an anonymized minimal reproduction. The repository&amp;#039;s [https://github.com/launix-de/memcp/blob/fed54d227ca73e7878be1186712bbfd0dc2c9038/README-TSQL.md evaluation guide] gives the detailed capture procedure.&lt;/div&gt;</description>
			<pubDate>Fri, 09 Oct 2026 06:32:13 GMT</pubDate>
			<dc:creator>Carli</dc:creator>
			<comments>https://www.memcp.org/wiki/Talk:T-SQL_mode</comments>
		</item>
		<item>
			<title>User:ErikDuigan846</title>
			<link>https://www.memcp.org/wiki/User:ErikDuigan846</link>
			<guid isPermaLink="false">https://www.memcp.org/wiki/User:ErikDuigan846</guid>
			<description>&lt;p&gt;User account &lt;a href=&quot;/index.php?title=User:ErikDuigan846&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new mw-userlink&quot; title=&quot;User:ErikDuigan846 (page does not exist)&quot;&gt;&lt;bdi&gt;ErikDuigan846&lt;/bdi&gt;&lt;/a&gt; was created&lt;/p&gt;
</description>
			<pubDate>Mon, 05 Oct 2026 04:47:57 GMT</pubDate>
			<dc:creator>ErikDuigan846</dc:creator>
			<comments>https://www.memcp.org/wiki/User_talk:ErikDuigan846</comments>
		</item>
		<item>
			<title>User:LucianaHowland</title>
			<link>https://www.memcp.org/wiki/User:LucianaHowland</link>
			<guid isPermaLink="false">https://www.memcp.org/wiki/User:LucianaHowland</guid>
			<description>&lt;p&gt;User account &lt;a href=&quot;/index.php?title=User:LucianaHowland&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new mw-userlink&quot; title=&quot;User:LucianaHowland (page does not exist)&quot;&gt;&lt;bdi&gt;LucianaHowland&lt;/bdi&gt;&lt;/a&gt; was created&lt;/p&gt;
</description>
			<pubDate>Sun, 04 Oct 2026 21:12:22 GMT</pubDate>
			<dc:creator>LucianaHowland</dc:creator>
			<comments>https://www.memcp.org/wiki/User_talk:LucianaHowland</comments>
		</item>
		<item>
			<title>Group Caches</title>
			<link>https://www.memcp.org/index.php?title=Group_Caches&amp;diff=424&amp;oldid=420</link>
			<guid isPermaLink="false">https://www.memcp.org/index.php?title=Group_Caches&amp;diff=424&amp;oldid=420</guid>
			<description>&lt;p&gt;&lt;/p&gt;
&lt;a href=&quot;https://www.memcp.org/index.php?title=Group_Caches&amp;amp;diff=424&amp;amp;oldid=420&quot;&gt;Show changes&lt;/a&gt;</description>
			<pubDate>Fri, 25 Sep 2026 17:37:18 GMT</pubDate>
			<dc:creator>Carli</dc:creator>
			<comments>https://www.memcp.org/wiki/Talk:Group_Caches</comments>
		</item>
		<item>
			<title>Main Page</title>
			<link>https://www.memcp.org/index.php?title=Main_Page&amp;diff=421&amp;oldid=411</link>
			<guid isPermaLink="false">https://www.memcp.org/index.php?title=Main_Page&amp;diff=421&amp;oldid=411</guid>
			<description>&lt;p&gt;&lt;span dir=&quot;auto&quot;&gt;&lt;span class=&quot;autocomment&quot;&gt;Internals&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 12:41, 25 September 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l271&quot;&gt;Line 271:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 271:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Transactions and Isolation]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Transactions and Isolation]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Query Planner and Physical Lowering]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Query Planner and Physical Lowering]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-side-deleted&quot;&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;* [[Group Caches]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Full SCM API documentation]]&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;* [[Full SCM API documentation]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br/&gt;&lt;/td&gt;&lt;/tr&gt;

&lt;!-- diff cache key memcp_wiki-mediawiki-:diff::1.12:old-411:rev-421 --&gt;
&lt;/table&gt;</description>
			<pubDate>Fri, 25 Sep 2026 10:41:57 GMT</pubDate>
			<dc:creator>Carli</dc:creator>
			<comments>https://www.memcp.org/wiki/Talk:Main_Page</comments>
		</item>
		<item>
			<title>Group Caches</title>
			<link>https://www.memcp.org/index.php?title=Group_Caches&amp;diff=420&amp;oldid=0</link>
			<guid isPermaLink="false">https://www.memcp.org/index.php?title=Group_Caches&amp;diff=420&amp;oldid=0</guid>
			<description>&lt;p&gt;Created page with &amp;quot;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Hänsch --&amp;gt; = Group Cache Dimensions: Equality, Additive Ranges, and Snapshots =  Implementation reference: 25 September 2026, commit b22387664, [https://github.com/launix-de/memcp/pull/999 PR #999]. Examples describe query shapes; actual eligibility and plan selection depend on semantic proofs, estimated costs, and cache state.  A group cache retains reusable aggregate state across SQL requests. It is separate from the query-plan cach...&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;!-- Copyright (C) 2026 Carl-Philip Hänsch --&amp;gt;&lt;br /&gt;
= Group Cache Dimensions: Equality, Additive Ranges, and Snapshots =&lt;br /&gt;
&lt;br /&gt;
Implementation reference: 25 September 2026, commit b22387664, [https://github.com/launix-de/memcp/pull/999 PR #999]. Examples describe query shapes; actual eligibility and plan selection depend on semantic proofs, estimated costs, and cache state.&lt;br /&gt;
&lt;br /&gt;
A group cache retains reusable aggregate state across SQL requests. It is separate from the query-plan cache and from caching complete HTTP responses. Cache eviction or changes to source dependencies can require reconstruction.&lt;br /&gt;
&lt;br /&gt;
The three dimension modes describe &amp;#039;&amp;#039;&amp;#039;how aggregate results at different parameter values relate to each other&amp;#039;&amp;#039;&amp;#039;. They are not specific to time. Coordinates can represent numeric versions, positions, thresholds, or timestamps.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Dimension mode !! Meaning !! Reuse strategy !! Typical query shape&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Equality / point domain&amp;#039;&amp;#039;&amp;#039; || An exact key or key tuple || Look up the aggregate state for that key || Aggregate over an equality group&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Additive range domain&amp;#039;&amp;#039;&amp;#039; || An interval of an ordered source dimension || Combine states for disjoint input intervals || Aggregate over selected facts&lt;br /&gt;
|-&lt;br /&gt;
| &amp;#039;&amp;#039;&amp;#039;Snapshot domain&amp;#039;&amp;#039;&amp;#039; || A parameter point at which contributions were evaluated || Read an exact point, or correct an existing state for a new point || Aggregate over parameter-dependent selected states&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
The new shape is called &amp;#039;&amp;#039;&amp;#039;snapshot aggregation over a parameter domain&amp;#039;&amp;#039;&amp;#039;, or more precisely, &amp;#039;&amp;#039;&amp;#039;a snapshot domain with incremental contribution correction&amp;#039;&amp;#039;&amp;#039;. &amp;#039;&amp;#039;As-of state aggregation&amp;#039;&amp;#039; is a useful name for the ordered-state-selection subclass, but the abstraction is not restricted to temporal queries.&lt;br /&gt;
&lt;br /&gt;
== 1. Equality domains: One aggregate per exact key ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT COUNT(*) FROM orders WHERE customer_id = :customer;&lt;br /&gt;
SELECT SUM(amount) FROM orders WHERE customer_id = :customer;&lt;br /&gt;
SELECT COUNT(*) FROM orders;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The first two queries can reuse aggregate states indexed by customer ID. An aggregate without a correlated parameter, such as the final COUNT(*), is the limiting case with one group and an empty key tuple. Additional fixed filters belong to the computation and its cache identity.&lt;br /&gt;
&lt;br /&gt;
This is particularly useful for correlated aggregates: many outer rows may request the same group. Once its aggregate state is available, the group need not be aggregated again for each outer row. Several equality keys can form a partition, such as tenant and product class.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Work avoided:&amp;#039;&amp;#039;&amp;#039; Repeated processing of M records in a group becomes a lookup of existing aggregate state. Whether to prepare groups together or populate them on demand is a physical planning decision.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Potential speedup:&amp;#039;&amp;#039;&amp;#039; No isolated A/B measurement of this mode is claimed here. If an expensive group aggregate is requested 100 times, its work can conceptually drop from 100 aggregations to one build plus 100 lookups. The speedup of that part approaches at most 100×, while other query work limits the end-to-end gain. Against a cheap index probe or a tiny group, the benefit may be small.&lt;br /&gt;
&lt;br /&gt;
== 2. Additive range domains: Combine disjoint fact intervals ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT SUM(revenue)&lt;br /&gt;
FROM sales&lt;br /&gt;
WHERE coordinate &amp;gt;= :lo AND coordinate &amp;lt; :hi;&lt;br /&gt;
&lt;br /&gt;
SELECT SUM(revenue)&lt;br /&gt;
FROM sales&lt;br /&gt;
WHERE tenant_id = :tenant&lt;br /&gt;
  AND coordinate &amp;gt;= :lo AND coordinate &amp;lt; :hi;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Each fact has a contribution that does not depend on the requested interval within this computation. The bounds determine which facts participate. The second query combines an equality partition with a range dimension.&lt;br /&gt;
&lt;br /&gt;
For a sum over disjoint intervals:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
R([a,c)) = R([a,b)) + R([b,c))&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A cache can reuse and combine matching partial states. Missing coverage and boundary fragments still require work. Overlapping cells must not be counted twice. Inclusive/exclusive boundaries and SQL NULL semantics must be preserved.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Suitable query families:&amp;#039;&amp;#039;&amp;#039; Interval sums, interval counts, cumulative fact aggregates, and repeated overlapping reporting windows. SUM and COUNT are straightforward examples. More generally, each aggregate needs a valid state-combination rule. Conceptually, an average requires a sum and a count, rather than an unweighted average of averages. DISTINCT needs its own state semantics.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Work avoided:&amp;#039;&amp;#039;&amp;#039; Instead of reading M facts, a query may process K cached partial states and B uncovered facts.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Potential speedup:&amp;#039;&amp;#039;&amp;#039; No isolated measured factor for this mode is claimed here. If those operations have comparable costs, M/(K+B) approximates the reduction in aggregation work. For example, replacing 1,000,000 facts with 100 cached cells plus 9,900 remaining facts means roughly 100× fewer processing units. This is an illustrative work estimate, not a measured latency speedup. Cold construction, fragmentation, and little overlap between requests can consume much of the benefit.&lt;br /&gt;
&lt;br /&gt;
== 3. Snapshot domains: Aggregate state at a parameter point ==&lt;br /&gt;
&lt;br /&gt;
=== Why an additive range is insufficient ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
SELECT SUM((&lt;br /&gt;
  SELECT h.quantity&lt;br /&gt;
  FROM entity_history h&lt;br /&gt;
  WHERE h.entity_id = e.id AND h.coordinate &amp;lt;= :x&lt;br /&gt;
  ORDER BY h.coordinate DESC&lt;br /&gt;
  LIMIT 1&lt;br /&gt;
))&lt;br /&gt;
FROM entity e;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
This example requires an unambiguous ordered selection, for example UNIQUE(entity_id, coordinate).&lt;br /&gt;
&lt;br /&gt;
It does &amp;#039;&amp;#039;&amp;#039;not&amp;#039;&amp;#039;&amp;#039; sum all history entries up to x. Each entity contributes only its selected state. If an entity changes from quantity 3 to quantity 5, the aggregate must increase by 2. Simply adding the new quantity 5 would be incorrect.&lt;br /&gt;
&lt;br /&gt;
A snapshot retains aggregate state at an anchor point x₀, together with logical keys and contribution values needed for correction. &amp;#039;&amp;#039;&amp;#039;The snapshot itself is a point.&amp;#039;&amp;#039;&amp;#039; The interval between x₀ and x helps identify possible changes.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C(k,x) = contribution of entity k at parameter point x&lt;br /&gt;
S(x)   = sum of all C(k,x)&lt;br /&gt;
A      = a complete superset of potentially changed keys&lt;br /&gt;
&lt;br /&gt;
S(x) = S(x₀) - sum(C(k,x₀), k in A) + sum(C(k,x), k in A)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A key is corrected once even if several dependency paths identify it. For every key outside A, its contribution must be proven unchanged. Original residual predicates are still evaluated for candidates: a candidate may turn out not to change anything.&lt;br /&gt;
&lt;br /&gt;
=== Query structures recognized by the current implementation ===&lt;br /&gt;
&lt;br /&gt;
Subject to the corresponding proof conditions, the implementation handles these building blocks:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Ordered state selection per entity:&amp;#039;&amp;#039;&amp;#039; Select an unambiguous state using a moving bound. Several scalar values may depend on that selection.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Selected state plus threshold predicates:&amp;#039;&amp;#039;&amp;#039; A contribution also depends on a selected property being less than, greater than, or equal to a coordinate. Boundary crossings without a new history row must be included in the change cover.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Conditional SUM payloads:&amp;#039;&amp;#039;&amp;#039; CASE/IF chooses a contribution using provable conditions. Change coverage includes selection, predicate, and payload dependencies.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Fixed first/last properties:&amp;#039;&amp;#039;&amp;#039; A coordinate-independent first or last value can use the same property group cache in both full construction and correction.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Bounded EXISTS predicates:&amp;#039;&amp;#039;&amp;#039; Relevant child rows crossing a bound can identify affected contributions through projected parent keys.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Derived outer coordinates:&amp;#039;&amp;#039;&amp;#039; A pure outer expression such as x-5 can define a dimension. The selected states for x and x-5 must remain distinct.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Supported clamps and combinations:&amp;#039;&amp;#039;&amp;#039; Certain MIN/MAX clamps on selection bounds, including clamps involving selected properties, COALESCE, and Boolean combinations have complete change-cover proofs.&lt;br /&gt;
* &amp;#039;&amp;#039;&amp;#039;Repeated aggregate series:&amp;#039;&amp;#039;&amp;#039; Multiple parameter points of the same formula can use retained anchors, which later SQL requests can reuse as well.&lt;br /&gt;
&lt;br /&gt;
MIN/MAX in the clamp example means a &amp;#039;&amp;#039;&amp;#039;scalar bound expression&amp;#039;&amp;#039;&amp;#039;, not general support for retractable MIN/MAX aggregates.&lt;br /&gt;
&lt;br /&gt;
Applications include versioned inventory, quantities of qualifying contracts, valid configurations, and other aggregates of “the selected state at coordinate x”. Eligibility follows the relational formula, not the application&amp;#039;s business terminology.&lt;br /&gt;
&lt;br /&gt;
=== What happens on a subsequent request ===&lt;br /&gt;
&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Same point, matching fixed inputs, unchanged dependencies:&amp;#039;&amp;#039;&amp;#039; Read the retained aggregate state.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;New point:&amp;#039;&amp;#039;&amp;#039; Choose a valid anchor, identify potential changes, retract the old contributions, and add the new ones.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;No relevant change between selection bounds:&amp;#039;&amp;#039;&amp;#039; Proven equivalence of ordered selection cuts can permit reuse even when the numeric bound changes. A changed parameter value alone need not imply a fresh cache build.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Many changes:&amp;#039;&amp;#039;&amp;#039; Full reconstruction may be cheaper and can produce a new anchor.&lt;br /&gt;
# &amp;#039;&amp;#039;&amp;#039;Source mutation or eviction:&amp;#039;&amp;#039;&amp;#039; Reuse must be re-established. Moving an input parameter is distinct from modifying the underlying data.&lt;br /&gt;
&lt;br /&gt;
For monotone interval covers, the current anchor selection compares affected-key work at the nearest valid anchor on each side. Numeric distance alone is not a work estimate. A farther anchor can require fewer corrections.&lt;br /&gt;
&lt;br /&gt;
=== Current implementation limits ===&lt;br /&gt;
&lt;br /&gt;
* The new retraction path currently targets &amp;#039;&amp;#039;&amp;#039;SUM contributions&amp;#039;&amp;#039;&amp;#039;. Runtime admission permits NULL and integral numeric values within a conservative exactness budget; the sum of absolute magnitudes must not exceed 2^52. Other values retain the ordinary SQL reducer. Arbitrary floating-point sums are not silently reordered.&lt;br /&gt;
* A count can mathematically be represented as a sum of 0/1 contributions. This does not imply that every COUNT spelling currently selects the snapshot path. Nor does the new path provide general support for COUNT DISTINCT, AVG, MIN/MAX, or arbitrary user-defined aggregates.&lt;br /&gt;
* The contribution proof currently requires a suitable single base driver with a single-column primary key. Arbitrarily multiplying joins and composite contribution identities are not generally covered.&lt;br /&gt;
* Each contribution proof chooses one moving axis; other inputs partition the cache. This is not yet general incremental correction across freely moving multidimensional surfaces.&lt;br /&gt;
* The current snapshot runtime restricts coordinates to suitable integral numeric values. The abstraction is broader than this implementation; support for arbitrary ordered types is not implied.&lt;br /&gt;
* Not every algebraically related formula has a proof. For example, a scaled inner selection coordinate is not automatically treated as an identity change domain.&lt;br /&gt;
* INSERT/UPDATE/DELETE, changes to classification tables, and table replacement must participate in dependency handling. An invalid snapshot may be discarded and rebuilt. Fully incremental maintenance for every source mutation is not implemented.&lt;br /&gt;
* Cost selection and memory budgets may favor direct execution even when a formula is eligible. Small or empty inputs should not pay for unnecessary preparation.&lt;br /&gt;
&lt;br /&gt;
=== Potential speedup ===&lt;br /&gt;
&lt;br /&gt;
Let N be the number of contributions in a full build and D the number of potentially changed contributions. A follow-up replaces much of the work on N contributions with change-cover/index work and evaluation of D contributions. With comparable per-contribution costs, N/D is a rough estimate for the reduction in that part of execution, not the complete HTTP latency.&lt;br /&gt;
&lt;br /&gt;
For example, 100,000 entities with 100 change candidates mean roughly 1,000× fewer contributions to re-evaluate. Expensive candidate discovery, remaining scans elsewhere in the query, planning, and response handling reduce the actual speedup.&lt;br /&gt;
&lt;br /&gt;
Across P requested points, a favorable snapshot plan replaces P full evaluations with one build and P-1 corrections. An exact repeat can be cheaper still. Initial construction remains real work.&lt;br /&gt;
&lt;br /&gt;
== Performance expectations and reproducible evaluation ==&lt;br /&gt;
&lt;br /&gt;
There is no universal speedup factor for a dimension mode. The estimates above describe reductions in work under stated assumptions. They are not measured end-to-end latency guarantees.&lt;br /&gt;
&lt;br /&gt;
A reproducible comparison should identify the exact source revisions, hardware, generated fixture, query parameters, and cache preparation. Measure one cold request plus a fixed number of follow-ups, include all requests in the total, and report phase timings separately. Moving-bound tests should cover both empty and nonempty change sets. Repeating an identical query tests exact-point reuse; it does not establish the cost of snapshot correction.&lt;br /&gt;
&lt;br /&gt;
The public test suite provides neutral examples that can be inspected and executed without access to application or customer data:&lt;br /&gt;
&lt;br /&gt;
* &amp;#039;&amp;#039;tests/performance/domain-snapshot.yaml&amp;#039;&amp;#039;: generated entities and versioned values; ordered state selection, selected-property boundaries, moving parameters, retained snapshots, anchor selection, and source-change correctness.&lt;br /&gt;
* &amp;#039;&amp;#039;tests/performance/group-range-cache.yaml&amp;#039;&amp;#039;: generated range-aggregation workloads with performance configuration.&lt;br /&gt;
* &amp;#039;&amp;#039;tests/planner/aggregates/group-range-cache.yaml&amp;#039;&amp;#039;: correctness and plan regressions for group/range reuse.&lt;br /&gt;
&lt;br /&gt;
Use each test&amp;#039;s declared setup and sampling configuration when reproducing it. Small correctness fixtures establish semantics, not production-scale speedups. A comparison intended to isolate one cache mode must control the other planner and runtime changes as well.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;This page does not publish latency factors from private application workloads. It makes no independently measured speedup claim for an individual dimension mode.&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
== Combining dimensions and choosing a plan ==&lt;br /&gt;
&lt;br /&gt;
One report can use all three modes: equality partitions for tenants or categories, additive ranges for fact revenue, and snapshot domains for state-dependent quantities. Different metrics need not use the same mode. For example, the current implementation can keep categories as fixed partitions without computing every category together in one contribution vector.&lt;br /&gt;
&lt;br /&gt;
Logical IR exposes parameter dependencies, unique selection, contribution identity, and a complete superset of potentially changed keys. Physical planning then decides whether direct execution or cache reuse is cheaper. The logical IR does not introduce physical scans or cache tables prematurely.&lt;br /&gt;
&lt;br /&gt;
EXPLAIN IR and EXPLAIN REORDER help inspect the structure. EXPLAIN PHYSICAL exposes decisions such as &amp;#039;&amp;#039;contribution_domain&amp;#039;&amp;#039;, with &amp;#039;&amp;#039;domain_snapshot&amp;#039;&amp;#039; and &amp;#039;&amp;#039;direct_aggregate&amp;#039;&amp;#039; alternatives. EXPLAIN shows the generated Scheme plan. Actual latency and records visited still require execution measurements.&lt;br /&gt;
&lt;br /&gt;
A snapshot cache is distinct from RecMap. RecMap accelerates physical row mappings within a query. Retained snapshots use logical keys and values; query-local physical row identities must not survive arbitrary shard rebuilds.&lt;br /&gt;
&lt;br /&gt;
== Implementation and test references ==&lt;br /&gt;
&lt;br /&gt;
* [https://github.com/launix-de/memcp/pull/999 PR #999]: implementation changes.&lt;br /&gt;
* [https://github.com/launix-de/memcp/blob/b2238766400c2c5b20d155a328d0ed380a7414ff/INVARIANTS.md INVARIANTS.md]: planner and group-cache contracts.&lt;br /&gt;
* [https://github.com/launix-de/memcp/blob/b2238766400c2c5b20d155a328d0ed380a7414ff/lib/queryplan-optimize.scm queryplan-optimize.scm]: logical contribution and dependency proofs.&lt;br /&gt;
* [https://github.com/launix-de/memcp/blob/b2238766400c2c5b20d155a328d0ed380a7414ff/lib/queryplan-physical-expr.scm queryplan-physical-expr.scm]: physical selection, snapshot admission, and correction.&lt;br /&gt;
* [https://github.com/launix-de/memcp/blob/b2238766400c2c5b20d155a328d0ed380a7414ff/tests/performance/domain-snapshot.yaml domain-snapshot.yaml]: neutral correctness and performance cases.&lt;br /&gt;
* [https://github.com/launix-de/memcp/blob/b2238766400c2c5b20d155a328d0ed380a7414ff/tests/planner/aggregates/group-range-cache.yaml group-range-cache.yaml]: group/range regression cases.&lt;/div&gt;</description>
			<pubDate>Fri, 25 Sep 2026 10:39:33 GMT</pubDate>
			<dc:creator>Carli</dc:creator>
			<comments>https://www.memcp.org/wiki/Talk:Group_Caches</comments>
		</item>
		<item>
			<title>User:KellieDlh9638</title>
			<link>https://www.memcp.org/wiki/User:KellieDlh9638</link>
			<guid isPermaLink="false">https://www.memcp.org/wiki/User:KellieDlh9638</guid>
			<description>&lt;p&gt;User account &lt;a href=&quot;/index.php?title=User:KellieDlh9638&amp;amp;action=edit&amp;amp;redlink=1&quot; class=&quot;new mw-userlink&quot; title=&quot;User:KellieDlh9638 (page does not exist)&quot;&gt;&lt;bdi&gt;KellieDlh9638&lt;/bdi&gt;&lt;/a&gt; was created&lt;/p&gt;
</description>
			<pubDate>Tue, 15 Sep 2026 10:18:28 GMT</pubDate>
			<dc:creator>KellieDlh9638</dc:creator>
			<comments>https://www.memcp.org/wiki/User_talk:KellieDlh9638</comments>
		</item>
</channel></rss>