Skip to main content

Scalar Types

The five scalar types — Null, Boolean, Integer, Float, String — are the atoms of every value in LoraDB. Lists, maps, temporal values, spatial points, and graph types are compositions over these.

Null​

Represents the absence of a value. LoraDB uses three-valued logic for comparisons involving null.

RETURN null, null = null, null <> null, 1 = null
// null, null, null, null

Boolean operators propagate null carefully:

ExpressionResult
null AND truenull
null AND falsefalse
null OR truetrue
null OR falsenull
NOT nullnull

Null tests​

Use IS NULL / IS NOT NULL — not = null:

MATCH (n) WHERE n.optional IS NULL     RETURN n;
MATCH (n) WHERE n.optional IS NOT NULL RETURN n

Null in aggregates​

AggregateBehaviour
count(*)Counts rows; null bindings still count
count(expr)Skips null
sum, avg, min, maxSkip null
collect(expr)Keeps null

See Aggregation Functions for the full table.

Null in ordering​

null sorts last in ascending order and first in descending order. Guard with coalesce to change placement — see Ordering.

Boolean​

true or false. Bools are not integers in LoraDB — true = 1 evaluates to false. Use toInteger(b) to convert.

RETURN true AND false;            // false
RETURN true OR false;             // true
RETURN NOT true;                  // false
RETURN true XOR false;            // true
RETURN toInteger(true),          // 1
     toInteger(false)          // 0

Parameters​

Bools bind transparently:

MATCH (u:User) WHERE u.active = $active RETURN u

Use as a flag property​

MATCH (p:Product) WHERE p.in_stock RETURN p;
MATCH (p:Product) WHERE NOT p.in_stock RETURN p

Note the short form: WHERE p.in_stock is equivalent to WHERE p.in_stock = true, but will also match only true — it drops rows where p.in_stock is false or null.

Integer​

64-bit signed (i64). Literals can be decimal, hex, or octal.

RETURN 42, -1, 0, 0xFF, 0o17
// 42, -1, 0, 255, 15

Arithmetic​

OpExampleNotes
+, -, *1 + 2Integer if both operands are integers
/10 / 3 → 3Integer division (truncates toward zero) when both operands are integers; Float if either is
%10 % 3 → 1Remainder, signed like the dividend; Float if either operand is
^2 ^ 10 → 1024Exponent
unary -, +-x

Integer divide or modulo by zero fails the query; with a Float operand it returns null.

RETURN 1 / 0;      // error: integer division by zero
RETURN 1.0 / 0     // null

See Math Functions → Arithmetic operators for the full details, including mixed-type arithmetic.

Conversion​

RETURN toInteger('42'),     // 42
     toInteger(3.9),      // 3       (truncates)
     toInteger('abc'),    // null
     toFloat(42)          // 42.0

Use as an id​

Integers are the most common id type:

MATCH (u:User {id: $id}) RETURN u

For very large ids, note integer precision in JS — values above 2^53 lose precision when crossing the JS boundary.

Limitations​

Integer +, -, *, /, % and unary - are overflow-checked: a result outside the i64 range fails the query with a LORA_VALIDATION error (integer addition overflowed, …) instead of wrapping. For extreme inputs, convert to Float first.

Float​

64-bit floating point (f64, IEEE 754).

RETURN 3.14, 1.0e10, -0.5

Mixed-type arithmetic promotes to Float:

RETURN 1 + 2.5;       // 3.5 (Float)
RETURN 10 / 3.0      // 3.333…

IEEE 754 quirks​

  • NaN == NaN → false
  • NaN comparisons → false
  • Float division by zero returns null — 1.0 / 0.0 and 0.0 / 0.0 never produce Infinity or NaN
RETURN 1.0 / 0.0;          // null
RETURN 0.0 / 0.0          // null

Rounding​

See Math → Rounding:

RETURN math.round(3.5);        // 4
RETURN math.round(2.5);        // 3        (default half-up rounding)
RETURN math.ceil(0.1);         // 1
RETURN math.floor(-0.1)       // -1

Use as a ratio / rate​

MATCH (r:Review)
RETURN r.stars / 5.0 AS normalised   // 0.0 .. 1.0

String​

UTF-8 text. Either quote style works.

RETURN 'hello', "world"
RETURN 'it''s fine'        // 'it's fine'  (double the quote to escape)
RETURN "with \n newline"   // string with a literal newline

Concatenation​

RETURN 'Hello, ' + 'Ada';         // 'Hello, Ada'
RETURN 'id=' + 42;               // 'id=42'
RETURN 'id=' + toString(42)      // 'id=42'

A string and a number concatenate, in either order, with the number printed as toString prints it. Other types (booleans, maps, temporals) must be converted first: + between a string and one of them is an error, not a silent null. A null operand still gives null.

Useful functions​

See String Functions for the full reference. Highlights:

RETURN string.lower('LoraDB'),           // 'loradb'
     string.split('a,b,c', ','),         // ['a', 'b', 'c']
     string.slice('LoraDB', 0, 4),   // 'Lora'
     string.replace('aba', 'a', 'x')     // 'xbx'

Comparison​

Strings sort byte-lexicographically. Case-sensitive comparisons are the default; normalise with string.lower / string.upper for case-insensitive matching — see WHERE → string matching.

MATCH (u:User)
WHERE string.lower(u.name) = string.lower($search)
RETURN u

Lengths: bytes vs code points​

RETURN value.size('café'),      // string size
     string.length('café')    // 4  (code points)

For display-length, prefer string.length. For general polymorphic size checks, use value.size.

Parameters​

Scalar parameters bind transparently from host-language values — Rust primitives, JS numbers / strings / booleans, Python int / float / str / None. See the per-platform Getting Started guide for your language.

MATCH (u:User)
WHERE u.id = $id AND u.active = $active
RETURN u

Comparison matrix​

Scalar equalityOrdering
Booleantrue = true → truefalse < true
Integernumericnumeric
Floatnumeric (IEEE 754)numeric; NaN incomparable
Stringcase-sensitivebyte-lex
Nullnull-propagatingnull-propagating (last asc, first desc)

Cross-type comparisons return null (type mismatch detection is not yet implemented — see Limitations).

Common patterns​

Default a missing scalar​

MATCH (p:Person)
RETURN p.name, coalesce(p.nickname, p.name) AS display

Safe equality​

MATCH (a), (b)
WHERE coalesce(a.key, '') = coalesce(b.key, '')
RETURN a, b
MATCH (u:User)
WHERE string.lower(u.email) CONTAINS string.lower($q)
RETURN u

Boolean flag pattern​

MATCH (p:Product) WHERE p.in_stock RETURN p

;// Equivalent, explicit:
MATCH (p:Product) WHERE p.in_stock = true RETURN p

The bare form drops rows where p.in_stock is null — common source of surprise when a property is missing rather than false. Guard with coalesce:

MATCH (p:Product)
WHERE coalesce(p.in_stock, false)
RETURN p

Branch on a scalar with CASE​

MATCH (u:User)
RETURN u.handle,
     CASE u.tier
       WHEN 'pro'  THEN 'paying'
       WHEN 'free' THEN 'trial'
       ELSE             'unknown'
     END AS segment

See CASE — LoraDB's conditional expression, supporting both "match a value" and "generic boolean per branch" forms.

Edge cases​

Nulls in arithmetic​

1 + null is null. Any arithmetic involving null propagates.

MATCH (p:Person)
RETURN p.name, p.age + 1 AS next_age
// \`null\` if p.age is null

Booleans and truthiness​

WHERE x drops a row only when x is false or null. Any other value keeps it — including 0, '', and [], so WHERE 0 filters nothing. Write the comparison you mean (WHERE x <> 0, WHERE x IS NOT NULL) rather than relying on a bare value.

Very small numbers​

Sub-nanosecond precision is lost on Float. For exact arithmetic on small quantities (money, percentages), use scaled integers (cents, basis points).

See also​