Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
743 changes: 524 additions & 219 deletions docs/ui/supplemental/css/arcadedb.css

Large diffs are not rendered by default.

71 changes: 71 additions & 0 deletions docs/ui/supplemental/js/theme-toggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Theme toggle and reduced-motion handling.
// The toggle cycles system -> light -> dark. "System" removes data-theme from <html>, so the CSS
// follows prefers-color-scheme; "light" and "dark" set it and are remembered in localStorage.
// The saved value is applied before first paint by the inline script in partials/head-styles.hbs
// (same key). localStorage can be blocked (private window, site data off): every access is guarded
// and the toggle then works for the current page only.
;(function () {
'use strict'

var KEY = 'arcadedb-docs-theme'
var ORDER = ['system', 'light', 'dark']
var NAMES = { system: 'follows the system', light: 'light', dark: 'dark' }
var root = document.documentElement

function current () {
var t = root.getAttribute('data-theme')
return t === 'light' || t === 'dark' ? t : 'system'
}

function apply (mode, save) {
if (mode === 'system') root.removeAttribute('data-theme')
else root.setAttribute('data-theme', mode)
if (save) {
try {
if (mode === 'system') localStorage.removeItem(KEY)
else localStorage.setItem(KEY, mode)
} catch (e) { /* storage unavailable: the choice lasts for this page only */ }
}
}

function label (btn, mode) {
var next = ORDER[(ORDER.indexOf(mode) + 1) % ORDER.length]
btn.setAttribute('data-mode', mode)
btn.setAttribute('title', 'Color theme: ' + NAMES[mode])
btn.setAttribute('aria-label', 'Color theme: ' + NAMES[mode] + '. Activate to switch to ' + NAMES[next] + '.')
}

function ready (fn) {
if (document.readyState !== 'loading') fn()
else document.addEventListener('DOMContentLoaded', fn)
}

ready(function () {
var btn = document.querySelector('.theme-toggle')
if (btn) {
label(btn, current())
btn.addEventListener('click', function () {
var mode = ORDER[(ORDER.indexOf(current()) + 1) % ORDER.length]
apply(mode, true)
label(btn, mode)
})
}

// The dots that travel along the lines of the inline SVG diagrams are SMIL animations, which CSS
// cannot switch off. Readers who ask for reduced motion get the still diagram.
var rm = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)')
function stillDiagrams () {
var svgs = document.querySelectorAll('svg')
for (var i = 0; i < svgs.length; i++) {
try {
if (rm.matches) svgs[i].pauseAnimations()
else svgs[i].unpauseAnimations()
} catch (e) {}
}
}
if (rm) {
stillDiagrams()
if (rm.addEventListener) rm.addEventListener('change', stillDiagrams)
}
})
})()
1 change: 1 addition & 0 deletions docs/ui/supplemental/partials/footer-scripts.hbs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script id="site-script" src="{{{uiRootPath}}}/js/site.js" data-ui-root-path="{{{uiRootPath}}}"></script>
<script async src="{{{uiRootPath}}}/js/vendor/highlight.js"></script>
<script src="{{{uiRootPath}}}/js/nav-tabs.js"></script>
<script src="{{{uiRootPath}}}/js/theme-toggle.js"></script>
<script src="{{{uiRootPath}}}/js/cookie-banner.js"></script>
<script src="{{{siteRootPath}}}/pagefind/pagefind-ui.js"></script>
<script>
Expand Down
8 changes: 8 additions & 0 deletions docs/ui/supplemental/partials/head-styles.hbs
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
<script>
/* Apply the saved theme before the first paint, so a dark reader never sees a white flash.
Keep the key in step with js/theme-toggle.js. No saved choice: the system setting decides (css). */
try {
var t = localStorage.getItem('arcadedb-docs-theme')
if (t === 'light' || t === 'dark') document.documentElement.setAttribute('data-theme', t)
} catch (e) {}
</script>
<link rel="stylesheet" href="{{uiRootPath}}/css/site.css">
<link rel="stylesheet" href="{{{siteRootPath}}}/pagefind/pagefind-ui.css">
<link rel="stylesheet" href="{{uiRootPath}}/css/arcadedb.css">
5 changes: 5 additions & 0 deletions docs/ui/supplemental/partials/header-content.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@
<div class="navbar-item search hide-for-print">
<div id="search"></div>
</div>
<button class="theme-toggle hide-for-print" type="button" data-mode="system" aria-label="Color theme: follows the system. Activate to switch to light." title="Color theme: follows the system">
<svg class="icon-system" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="8.5"/><path d="M12 3.5v17" /><path d="M12 3.5a8.5 8.5 0 0 1 0 17z" fill="currentColor"/></svg>
<svg class="icon-light" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><circle cx="12" cy="12" r="4"/><path d="M12 2.5v2.5M12 19v2.5M2.5 12H5M19 12h2.5M5.3 5.3l1.8 1.8M16.9 16.9l1.8 1.8M5.3 18.7l1.8-1.8M16.9 7.1l1.8-1.8"/></svg>
<svg class="icon-dark" viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M20 14.5A8.5 8.5 0 0 1 9.5 4a8.5 8.5 0 1 0 10.5 10.5z"/></svg>
</button>
<button class="navbar-burger" aria-controls="topbar-nav" aria-expanded="false" aria-label="Toggle main menu">
<span></span>
<span></span>
Expand Down
3 changes: 2 additions & 1 deletion src/main/asciidoc/concepts/transactions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,7 @@ flushing on its own (group commit, setting `arcadedb.txWalGroupCommit`, on by de
on disk, but it no longer holds the locks of the files it wrote while its WAL is written and flushed, so the commits that
arrive meanwhile are written and flushed together. On an Apple silicon laptop, 50 clients writing into the same type went
from about 230 to about 4,000 commits per second with `txWalFlush=2`. A single writer sees no difference. The
<<engine-gauges,engine metrics>> `wal.group.*` and `commit.lock.*` show how many commits each flush served and how long
<<engine-gauges,engine metrics>> `+wal.group.*+` and `+commit.lock.*+` show how many commits each flush served and how long
a commit holds its locks.

What changes compared to the previous versions:
Expand Down Expand Up @@ -364,6 +364,7 @@ A `ConcurrentModificationException` always means another transaction wrote the r
In particular, updating a record that the same transaction has already deleted is not a conflict, it simply has no effect - the delete wins, since the record will not exist once the transaction commits.
The order of the two operations does not matter.

[[statement-fails-halfway]]
==== A statement that fails halfway

A statement that fails inside a transaction you keep is taken back on its own, and the transaction goes on as if the statement had never run, the way SQLite undoes a failed statement.
Expand Down
3 changes: 2 additions & 1 deletion src/main/asciidoc/how-to/connectivity/postgres.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ dropping it, finds the views that depend on it. Dependencies are listed per type
_Since v26.10.1_, `pg_type` can also be queried on its own, and not only as part of a column list. Some
clients build a map of every type the server has before they run a single query, and refuse to connect if
that map comes back empty - the Apache Arrow ADBC PostgreSQL driver is one of them. Such a query is answered
with the types this protocol can actually produce (see <<Column type mapping,Column type mapping>> below),
with the types this protocol can actually produce (see <<postgres-column-type-mapping,Column type mapping>> below),
each described the way PostgreSQL describes it. A filter the server cannot interpret returns no rows rather
than every type, so a client asking whether an extension type such as `hstore` exists is correctly told it
does not.
Expand Down Expand Up @@ -407,6 +407,7 @@ PROGRAM`, which would let a wire client write files or run commands on the serve
without a binary encoding on this server (an array) is refused the same way; export it in text or CSV format, or
project it as a string.

[[postgres-column-type-mapping]]
===== Column type mapping

A column's advertised PostgreSQL type must not depend on whether the query happens to return any rows - a
Expand Down
5 changes: 3 additions & 2 deletions src/main/asciidoc/how-to/connectivity/python-embedded.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ The embedded bindings run the ArcadeDB engine inside your Python process, so the

Install one of them, not both. With both installed, `import arcadedb` raises an `ImportError` that names the two.

The bindings live in the https://github.com/ArcadeData/arcadedb-python[ArcadeData/arcadedb-python] repository. This page covers the first steps; the repository holds the full guides and the API reference.
The bindings live in the https://github.com/ArcadeData/arcadedb-python[ArcadeData/arcadedb-python] repository, and their guides are in the https://docs.arcadedb.com/arcadedb-python/[ArcadeDB Python] docs. This page covers the first steps.

===== Install

Expand Down Expand Up @@ -101,6 +101,7 @@ You can also combine the two. The bindings can start an in-process HTTP server (

===== Where to go next

* https://github.com/ArcadeData/arcadedb-python[Bindings repository]: guides for vectors, graphs, time series, import and server mode, plus the API reference and examples.
* https://docs.arcadedb.com/arcadedb-python/[ArcadeDB Python docs]: installation, which package to pick, databases and queries, concurrency, bulk loads and vectors.
* https://github.com/ArcadeData/arcadedb-python[Bindings repository]: the source, the examples and the issue tracker.
* xref:how-to/connectivity/drivers/native-drivers.adoc[Native drivers]: the HTTP and gRPC clients, if you would rather talk to a server.
* xref:tutorials/python-quickstart.adoc[Python quickstart]: the PostgreSQL wire protocol route.
12 changes: 6 additions & 6 deletions src/main/asciidoc/how-to/data-modeling/graph-olap.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -456,7 +456,7 @@ GraphAnalyticalView roads = GraphAnalyticalView.builder(database)
.build();
----

Queries go through <<algo-cch-shortest-path,algo.cch.shortestPath>> (Cypher) or <<cchShortestPath,cchShortestPath()>> (SQL). A query is answered by the hierarchy when its weight property and relationship types are exactly those of a hierarchy on a ready view; otherwise, and whenever the hierarchy cannot answer for the view's current state, it is answered by bidirectional Dijkstra. Answers are exact either way, and a transaction holding uncommitted changes always sees them.
Queries go through <<algo-cch-shortest-path,algo.cch.shortestPath>> (Cypher) or <<cch-shortest-path,cchShortestPath()>> (SQL). A query is answered by the hierarchy when its weight property and relationship types are exactly those of a hierarchy on a ready view; otherwise, and whenever the hierarchy cannot answer for the view's current state, it is answered by bidirectional Dijkstra. Answers are exact either way, and a transaction holding uncommitted changes always sees them.

*How it works*

Expand Down Expand Up @@ -579,14 +579,14 @@ counted on its own, by its own push-down or plan, and the counts are multiplied.
least one row. Two parts of one `MATCH` clause are multiplied only when the schema proves their relationships cannot
be the same edge, since a clause binds every relationship once. A product that does not fit a 64-bit integer is an
error (issue #9596).
* a `WITH` that only passes variables on, `*` and aliases included (`WITH message, creator`, `WITH m AS x`), with no
* a `WITH` that only passes variables on, `+*+` and aliases included (`WITH message, creator`, `WITH m AS x`), with no
aggregation, `DISTINCT`, `WHERE`, `ORDER BY`, `SKIP` or `LIMIT`: it leaves the number of rows alone, so the statement
is counted as if the clauses on both sides were one query part (issue #9597).
* `count(x)` of a node or relationship variable a non-optional `MATCH` binds, which counts the same rows as `count(*)`;
* `count(x)` of a node or relationship variable a non-optional `MATCH` binds, which counts the same rows as `+count(*)+`;
a single relationship between two unconstrained nodes, `MATCH ()-[e:KNOWS]->() RETURN count(e)` (untyped, with several
types or undirected too), read from the view's per-type totals, or without a view in one walk of the edge lists that
loads no edge; and `MATCH (n) RETURN count(n)`, the sum of the vertex types' counters (issue #9600). Unlike the SQL
`SELECT count(*) FROM KNOWS`, which counts edge records, the relationship count includes lightweight edges, which keep no
`+SELECT count(*) FROM KNOWS+`, which counts edge records, the relationship count includes lightweight edges, which keep no
record.
* the same pattern however it is written: the comma-separated parts of a `MATCH` are read as the graph they describe, so a
chain cut into parts is counted as the chain, and a cycle such as LSQB Q2 (a `KNOWS` hop closed by a three-hop chain, or
Expand All @@ -608,9 +608,9 @@ must be undirected, anonymous and of one type, and the three variables carry one
`COUNT TRIANGLES (CSR sorted intersection)` with the order it counts.

*Multi-hop chains on the view.* A chain of labeled hops such as `MATCH (a:P)-[:K]->(b:P)-[:K]->(c:P)` is walked on the
view (`EXPLAIN` shows `GAVFusedChain`). Since v26.10.2 a `count(*)`, or `count(x)` of a variable of the chain, is counted
view (`EXPLAIN` shows `GAVFusedChain`). Since v26.10.2 a `+count(*)+`, or `count(x)` of a variable of the chain, is counted
during the walk with up to two grouping keys that are chain variables, in a `RETURN` or a `WITH`
(`RETURN a, count(*) AS n`); `EXPLAIN` shows it on the chain as `fused count(*) AS n`. When the statement returns the
(`+RETURN a, count(*) AS n+`); `EXPLAIN` shows it on the chain as `+fused count(*) AS n+`. When the statement returns the
paths' rows instead, they are produced in bounded batches, so memory no longer grows with the number of paths and a
`LIMIT` stops the walk early (issue #9738). If the view is rebuilt while such a result is still being read, the query
fails with a retryable error rather than mixing rows from two builds: run it again.
Expand Down
2 changes: 1 addition & 1 deletion src/main/asciidoc/how-to/integrations/grafana.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ The https://github.com/ArcadeData/arcadedb-grafana-datasource[ArcadeDB Grafana p
*Features:*

* **Time Series mode** - visual query builder with auto-discovered types, fields, tags, and aggregation functions (SUM, AVG, MIN, MAX, COUNT)
* **SQL mode** - ArcadeDB SQL with macro expansion (`$__timeFrom`, `$__timeTo`, `$__timeFilter(col)`, `$__interval`)
* **SQL mode** - ArcadeDB SQL with macro expansion (`+$__timeFrom+`, `+$__timeTo+`, `+$__timeFilter(col)+`, `+$__interval+`)
* **Cypher mode** - OpenCypher queries with optional Node Graph visualization
* **Gremlin mode** - Apache Gremlin traversals with optional Node Graph visualization
* **Alerting** - full Grafana alerting support via the Go backend
Expand Down
2 changes: 1 addition & 1 deletion src/main/asciidoc/how-to/migration/importer.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Parsed 362000 (54256/sec) - 0 documents (0/sec) - 164118 vertices (5260/sec) - 3
----

An RDF source is recognised from the shape of its first statement - `subject predicate object` with an optional
closing `.` - so quoted literal objects, language tags (`@en`), typed literals (`^^<datatype>`), blank nodes (`_:b1`)
closing `.` - so quoted literal objects, language tags (`@en`), typed literals (`^^<datatype>`), blank nodes (`+_:b1+`)
and Windows (CRLF) line endings are all read as RDF, and the character separating the terms is used as the field
delimiter. _(Since v26.10.1: a file using any of those was analysed as delimited text instead and the import failed
with a number-parsing error naming an IRI. If a file still cannot be recognised, set the separator explicitly with
Expand Down
2 changes: 1 addition & 1 deletion src/main/asciidoc/how-to/operations/ha.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -692,7 +692,7 @@ With ephemeral Raft storage, wiping the log on restart could leave the cluster i

Durable storage lets a restarted node rejoin by *replaying its own persisted log* rather than always requiring a full snapshot resync from the leader.

*Migration:* the per-node directory is named `raft-storage-<nodeName>` dynamically, which container runtimes and Kubernetes cannot mount as a volume (a wildcard like `raft-storage-*` is created as a literal directory, not expanded). Set `arcadedb.ha.raftStorageDirectory` to a *static* path (e.g. `/home/arcadedb/raft-storage`) and mount *that* path on durable storage before upgrading. On Kubernetes, back it with a `PersistentVolumeClaim` — see <<kubernetes,Kubernetes>>. On a plain filesystem you can instead copy the existing `raft-storage-<nodeName>` directory across the upgrade. A throwaway or test cluster that intentionally wants ephemeral behavior can opt out with `arcadedb.ha.raftPersistStorage=false`.
*Migration:* the per-node directory is named `raft-storage-<nodeName>` dynamically, which container runtimes and Kubernetes cannot mount as a volume (a wildcard like `+raft-storage-*+` is created as a literal directory, not expanded). Set `arcadedb.ha.raftStorageDirectory` to a *static* path (e.g. `/home/arcadedb/raft-storage`) and mount *that* path on durable storage before upgrading. On Kubernetes, back it with a `PersistentVolumeClaim` — see <<kubernetes,Kubernetes>>. On a plain filesystem you can instead copy the existing `raft-storage-<nodeName>` directory across the upgrade. A throwaway or test cluster that intentionally wants ephemeral behavior can opt out with `arcadedb.ha.raftPersistStorage=false`.

[[ha-remote-commit-contract]]
===== Committed-remotely response contract
Expand Down
2 changes: 1 addition & 1 deletion src/main/asciidoc/how-to/operations/observability.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ grouped under `db="unknown"` rather than appearing one series per name.
| `arcadedb.engine.commit.lock.handoffs` / `.commit.lock.handoff.seconds` | Those locks passed to a waiting commit, and the total time from the release to that commit running _(Since v26.11.1)_
|===

The `commit.lock.*` and `wal.group.*` counters are read as averages. `rate(...hold.seconds) / rate(...holds)` is how long
The `+commit.lock.*+` and `+wal.group.*+` counters are read as averages. `rate(...hold.seconds) / rate(...holds)` is how long
a commit keeps the files it writes locked, and with many clients writing into the same type it is what limits the commits
per second: about 30 microseconds is normal, milliseconds mean the commits are waiting for the disk while they hold the
locks (`arcadedb.txWalFlush` set to 1 or 2 with `arcadedb.txWalGroupCommit=false`). `rate(wal.group.commits) / rate(wal.group.commit.syncs)`
Expand Down
Loading
Loading