Commit Graph
1027 Commits
Author SHA1 Message Date
discord9 ad7b0ace64 feat(flow): support eval schedule offsets (#8878)
* feat(flow): support eval schedule offsets

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(flow): remove redundant schedule assertion

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* refactor(flow): trim eval offset compatibility scope

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(flow): trim eval offset edge coverage

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* docs(flow): trim eval offset comment noise

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(flow): address eval offset review feedback

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(compat): cover Flow eval offset persistence

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-09-04 02:39:59 +00:00
LFC 84bd993131 refactor(json2): concretize JSON2 schemas at merge scan boundaries (#9016)
* refactor(json2): concretize JSON2 schemas at merge scan boundaries

Infer concrete JSON2 output types from remote plans and expose them on MergeScanLogicalPlan before physical planning. Recompute affected local schemas and remove the JSON2-specific rewrite from MergeScanExec.

Add SQLness coverage for whole JSON2 columns in windows and joins.

Signed-off-by: luofucong <luofc@foxmail.com>

* fix ci

Signed-off-by: luofucong <luofc@foxmail.com>

---------

Signed-off-by: luofucong <luofc@foxmail.com>
2026-09-04 02:02:24 +00:00
shuiyisong b86da3d35f feat: support raw OTLP delta metrics (#8970)
* feat: support raw OTLP delta metrics

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: fmt

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* test(promql): update sqlness results for normalized label matching

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: derive temporality label from default column prefix

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* test(promql): add analyze coverage for delta temporality

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix(promql): scope label alignment to temporality marker

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: handle count-only histograms and vector broadcasts

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: exclude temporality marker from entity descriptions

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: use a fixed label for OTLP aggregation temporality

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix(promql): preserve mixed-range semantics for raw delta

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

---------

Signed-off-by: shuiyisong <xixing.sys@gmail.com>
2026-09-03 09:28:11 +00:00
LFC d62a5a990a feat(json2): support list indexing for JSON2 columns (#9013)
feat(query): support list indexing for JSON2 columns

Extend JSON2 paths through DataFusion field-access planning, including nested list indexes and object fields following an index.

Preserve Variant reads for bracket JSONPath expressions and normalize dot accesses after subscripts to work around the current DataFusion planner limitation.

Add unit and sqlness coverage for nested indexes, type conflicts, missing paths, flushes, and compacted SSTs.

Signed-off-by: luofucong <luofc@foxmail.com>
2026-09-03 08:50:55 +00:00
fys 05c65f54a8 feat(json2): support empty and null JSON2 value (#9010)
* feat(json2): support empty and null JSON2 value

Signed-off-by: fys <fengys1996@gmail.com>

* test(json2): cover explicit NULL and omitted-column inserts

Signed-off-by: fys <fengys1996@gmail.com>

* fix: cargo fmt

Signed-off-by: fys <fengys1996@gmail.com>

* fix: infer empty JSON object as object type

Signed-off-by: fys <fengys1996@gmail.com>

---------

Signed-off-by: fys <fengys1996@gmail.com>
2026-09-03 06:22:27 +00:00
discord9 27a7047f31 feat: preserve row sequences and support exact sequence-range reads (#8865)
* feat(mito2): support exact sequence range reads

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(mito2): cover preserve row sequence table alter

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): clear preserve_row_sequence marker on copy_region_from

copy_region_from copies source FileMeta into the target region, which has an
independent sequence domain. The physical per-row sequences in the copied
file belong to the source region only; trusting them in the target would let
an exact sequence-range request replay source-domain rows as if they were
target sequences. Clear the preserve_row_sequence marker on copied files so
the target fails closed with SequenceRangeUnsupported until the scan provably
cannot intersect the copied rows.

Add a regression test: copying from a preserve-enabled source into a
preserve-enabled target clears the marker, and an exact (2, 7] request on the
target returns SequenceRangeUnsupported instead of replaying source rows.

Fixes #8865

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* style: remove redundant doc comments for exact sequence range options

Approved comment-cleanup-only changes for #8865: drop outdated doc
summaries duplicated on the exact_sequence_range wrapper and the
preserve_row_sequence field, drop pure-restatement doc comments on the
SetRegionOption/UnsetRegionOption PreserveRowSequence variants, and
remove the four structural SQL comments from the alter_preserve_row_sequence
case. No behavior changes; .result regenerated by the sqlness runner.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): fail closed exact reads on copied files and extension ranges

Address review feedback on #8865:

- copy_region_from: clear the source-domain FileMeta::sequence along with
  the preserve_row_sequence marker. An unmarked file retaining a stale
  source-domain max sequence could be silently skipped by
  files_allow_exact_sequence_range() as 'proven disjoint' in the target's
  independent sequence domain, dropping rows on exact (C, H] reads. With
  sequence=None the capability check fails closed (SequenceRangeUnsupported)
  until the copied rows are provably disjoint.
- Engine/reader: reject exact sequence-range reads whenever a follower
  region has an extension range provider attached. Extension streams are
  returned without a row-level sequence filter, so exactness cannot be
  proven; treat the capability as missing (fail closed) instead of emitting
  out-of-range rows. The reader also fails closed as defense in depth.

Tests: extend copy_region_from regression to assert the copied file's
sequence hint is cleared; mito2 suite 1148/1148 passing.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* style(mito2): use doc comments for test function descriptions

Elevate the block comments describing test functions (in scan_test and
copy_region_from_test) to /// doc comments, matching the convention used
elsewhere in the exact sequence range change. No logic change.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* refactor(mito2): extract helpers and trim comment noise in exact sequence reads

PR finalization for #8865 (zero behavior change, full mito2 suite green):

- engine: extract validate_sequence_fences and
  sequence_range_unsupported_reason, keeping error variants, check order
  and reason strings identical; OSS binds the extension blocker to false.
- handle_copy_region: extract remap_copied_file_meta and
  file_descriptors_for_meta; rename file_ids -> source_file_ids and
  files_to_copy -> new_file_metas.
- compactor: rename max_input_sequence -> known_max_input_sequence,
  document the None semantics (empty input vs unknown sequence).
- Remove restating/outdated comments (ScanInput::sequence_range doc
  first line, outdated file-pruning note, options test restatements),
  compress verbatim comments while keeping why/invariants/contracts.

Verified: cargo check -p mito2 (+ --features enterprise), cargo fmt,
git diff --check, mito2 suite 1148/1148 passing.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): reject foreign-region SSTs in exact sequence reads

Reading an SST whose FileMeta.region_id differs from the scanned region
means the region's sequence domain is broken (manifest corruption or a
repartition/copy path that leaked a source-domain file). Treat this as
an explicit RegionSequenceDomainBroken error instead of silently
ignoring the file's sequence or falling back to a full scan: the region
is unusable for exact sequence-range reads until the foreign lineage is
compacted away or repaired.

- files_allow_exact_sequence_range / exact_sequence_range now return
  Result and propagate the error through engine fence validation and
  scan construction (StatusCode::Internal, distinct from the
  fallback-capable SequenceRangeUnsupported).
- Row-level flat-batch sequence filtering rejects foreign-region files
  as defense in depth.
- Engine test asserts the broken-domain error rather than
  Unsupported/fallback.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): never trust unmarked SSTs for exact-range disjoint skipping

An unmarked file's FileMeta.sequence may be synthesized by the
region-edit or repartition paths (committed+1 import barrier), not a
physical max of its rows. Treating it as a whole-file disjoint proof
could permanently skip rows that were never incrementally consumed
once the flow checkpoint passes that value.

Exact sequence-range capability now requires every SST in the region to
carry the preserve_row_sequence marker; any unmarked file disables
exactness (fallback), and the (C, H] file-selection skip also only
applies to marked files. Foreign-region files still raise
RegionSequenceDomainBroken as before.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): scope exact sequence-range capability to the time-selected read set

The exact capability check used to walk the entire SstVersion, so a
single unmarked or foreign-region SST anywhere in the region disabled
exact reads or raised RegionSequenceDomainBroken even when the
request's time range could never touch that file.

Both the engine fence and the scan builder now derive the read set with
shared time-pruning + exact-min/sst-min selection and validate
capability only over the files actually selected: a time-pruned file
cannot contribute a row to (C, H], so it cannot affect exactness. The
existing fail-loud semantics are unchanged for every selected file
(foreign region id -> RegionSequenceDomainBroken; unmarked -> exact
unavailable).

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): wash untrusted sequences in compaction and restore barrier skipping

Compaction with any non-preserved input now writes a sequence-less
output: the physical __sequence column is zeroed (the flat format
requires the internal columns) and FileMeta.sequence records the
region-local admission barrier committed_sequence + 1 (falling back to
the flushed frontier). preserve_row_sequence stays false.

Exact sequence-range scans interpret an unmarked file's sequence as an
admission barrier: barrier <= C means flow has already consumed the
whole file, so it is skipped at file level; a missing or newer barrier
fails closed. Foreign-region files stay in the selected read set so the
capability fence still raises RegionSequenceDomainBroken.

This closes the recovery loop: after a region repartition, one
time-scoped fallback consumes the migrated rows, then compaction washes
the untrusted per-row sequences away and exact incremental reads resume
via file-level barrier skipping.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* chore(mito2): drop restating comments in known_max_input_sequence tests

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(mito2): trim SQLness result EOF whitespace

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* refactor(mito2): reuse exact scan file selection

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(mito2): strengthen sequence scan coverage

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* style(mito2): trim ALTER option comments

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(mito2): remove no-op bulk compaction check

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): preserve trusted row sequences when reading SSTs

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(mito2): preserve target sequence domain for imported SSTs

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(mito2): add trailing blank line to SQLness result EOF

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* chore(mito2): trim exact sequence scan plumbing

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* refactor(mito2): fold exact SST selection checks

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(mito2): make legacy compaction rewrite deterministic

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(mito2): make PK compaction rewrite deterministic

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-09-03 06:20:09 +00:00
LFC 15317a131b feat(json2): support JSON2 paths in SQL functions (#9007)
feat(query): support JSON2 paths in SQL functions

Update the DataFusion fork to expose scalar function planning hooks.

Infer JSON2 path output types from scalar, aggregate, and window function signatures, while preserving the default Utf8View behavior for functions that accept arbitrary inputs.

Add unit and sqlness coverage for type conflicts, mixed typed and untyped JSON paths, filters, aggregates, and window functions.

Signed-off-by: luofucong <luofc@foxmail.com>
2026-09-03 04:19:55 +00:00
Ning Sun 6f1dd0cb76 feat: allow widening the time index column's timestamp unit via ALTER TABLE, mito2 table only (#8894)
* feat: allow widening the time index column's timestamp unit via ALTER TABLE ... MODIFY COLUMN

Previously MODIFY COLUMN rejected the time index column outright. Now the
time index unit can be widened (Second -> Milli -> Micro -> Nano), which is
lossless for data that fits the target unit: historical data in old SSTs is
cast to the new unit on read by the existing schema-compat layer, and
compaction rewrites it lazily. Narrowing and non-timestamp targets remain
rejected; tag columns keep being rejected. Widening is rejected if any
SST's time range would overflow the target unit's i64 range (e.g.
millisecond -> nanosecond beyond year 2262), since the cast would silently
null those values.

Read-path correctness for old-unit SSTs (verified by new engine e2e tests
and sqlness WHERE queries):

- row-group min/max pruning: parquet statistics of a timestamp column are
  raw integers in the file's unit; when the region metadata's type differs
  (also the case for altered field columns), stats are now interpreted in
  the file's type and converted to the expected type before pruning.
  Without this, a new-unit predicate silently pruned whole row groups of
  old-unit files (wrong results, rows missing).
- SST-level simple filters are skipped for columns whose file type differs
  from the expected type; the predicate is applied by the query layer's
  residual filter above the region scan. Also drop the stale
  "timestamp columns cannot change type" debug_assert.
- retry idempotency: a same-type ModifyColumnType on the time index
  validates as a no-op and `need_alter` returns false, so a retried alter
  procedure (region already altered before the previous attempt failed)
  converges instead of aborting forever.

- add TimeUnit ordering and ConcreteDataType::is_timestamp_unit_widening_to
- relax ModifyColumnType validation in store-api and table metadata
- tests: unit tests in datatypes/store-api/table; mito2 engine e2e tests
  (flushed SST + new writes + reopen + retry + overflow + predicate scans,
  cross-unit dedup, mixed-unit SSTs, compaction); sqlness cases incl.
  partitioned table and WHERE filters over old-unit data

Signed-off-by: Ning Sun <sunning@greptime.com>

* fix: resolve parquet filter issue

* test: provide sqlness tests

* refactor: drop trivial test cases and shorten comments

Review pass over the branch's additions:

- datatypes: keep a representative subset of the widening-matrix asserts
- table: collapse the three single-branch rejection blocks into one loop
- mito2: drop the boundary gt_eq and post-compaction predicate asserts
  (covered by the exact-filter regression test and sqlness); drop the
  engine-level gt_eq/lt_eq casts (full operator matrix stays in the
  cast_timestamp_unit unit tests)
- sqlness: drop a bare full scan already covered by the filter above it
- shorten function doc comments across datatypes/store-api/table/mito2/
  recordbatch to the essential semantics

Signed-off-by: Ning Sun <sunning@greptime.com>

* fix: drop physical prefilter for columns whose file type differs

Follow-up to the review feedback on CompatBatch/prune reader/filter
handling for widened time index units.

Between/InList/IsNull predicates are prefiltered by PhysicalFilterContext,
which builds its physical expression against the FILE's schema while the
predicate literals are in the expected (post-alter) unit. Evaluating them
against an old-unit SST raised a cross-unit comparison error (Timestamp(ms)
>= Timestamp(µs)) that failed the whole scan. Physical prefilter predicates
are best-effort pruning hints (the query layer re-applies them above the
scan), so drop the prefilter when the column's file type differs from the
expected type, mirroring the simple-filter strategy.

Verified: Between and a non-rewritten (large) InList on old-unit data no
longer error and filter exactly end-to-end (sqlness), and no matching rows
are lost at the engine level (engine test).

Signed-off-by: Ning Sun <sunning@greptime.com>

* test: add direct unit tests for stats cast and prefilter drop

The two-step stats cast (reinterpret raw Int64 stats in the file's
timestamp type, then rescale to the expected type) and the physical
prefilter drop on file/expected type mismatch were only covered
end-to-end; add localized unit tests so a regression fails at the
exact site:

- stats.rs (previously no tests): RowGroupPruningStats min/max over a
  hand-built RowGroupMetaData — passthrough with no expected metadata,
  passthrough on same type, and rescale (1000ms -> 1_000_000us, not
  1000us) on a widened expected unit
- reader.rs: PhysicalFilterContext::new_opt keeps a Between prefilter
  when file and expected types match and drops it on unit mismatch

Signed-off-by: Ning Sun <sunning@greptime.com>

* fix: tolerate mixed time units range cache key coverage check

* docs: flag mixed-unit hazard in the (unwired) series index

The series index stores per-series min/max ts as raw Int64 in the unit
of the region metadata at write time, and the searcher builds its range
predicates from a single per-region metadata. After a time index unit
widen, files of one region would carry mixed units, so a per-file unit
(or an index rebuild on such alters) is required before this index is
wired into scans. Leave notes at both sites.

Signed-off-by: Ning Sun <sunning@greptime.com>

* test: cover mixed-unit compaction for sparse encoding and strict windows

Compaction-path audit follow-up. The compat cast and window math were
already covered for dense regions; add the two remaining e2e scenarios:

- sparse primary key encoding (used by metric-engine physical regions):
  widening then compacting mixed-unit files rewrites the old-unit time
  index correctly through the sparse compaction compat path
- strict-window manual compaction: each window output trims rows with a
  predicate built in the region's new unit against an old-unit file;
  every instant must survive exactly once (no loss, no cross-window
  duplication), rescaled

Also documents the audit finding that Regular ranged (manual)
compaction never trims rows: TwcsPicker sets output_time_range to None
and the request time range only selects candidate windows.

Signed-off-by: Ning Sun <sunning@greptime.com>

* test: cover time index unit change in FlatCompatBatch directly

The compat layer's rescaling of a widened time index was only verified
end-to-end; add direct unit tests for both paths:

- dense: identical units skip compat entirely; a widened unit rescales
  the time index column (1000ms -> 1_000_000us, not reinterpreted) while
  other columns pass through and the output schema matches the expected
  metadata
- compact sparse (the metric-engine compaction path): same rescaling

Signed-off-by: Ning Sun <sunning@greptime.com>

* refactor: move timestamp unit division into common-time

The exact unit division (UnitQuotient + div_mod_units) is time
semantics, not filter logic; move it next to TimeUnit in common-time
with a compact test covering representable/non-representable values,
negative (floor) instants, and quotient overflow. The ScalarValue
helpers stay in filter.rs since common-time has no datafusion
dependency.

Signed-off-by: Ning Sun <sunning@greptime.com>

* test: compat rescales a widened time index and fills an added column together

The realistic multi-alter sequence (widen at T1, add column at T2,
read a T0 SST) exercises cast and default-fill in the same
compute_index_and_fields pass; assert both in one output batch.

Signed-off-by: Ning Sun <sunning@greptime.com>

* fix: preflight time index widening overflow before any region alters

Address review feedback on the overflow guard:

- preflight: when the frontend operator receives a widening alter on the
  time index, run an existence scan (ts outside the target unit's i64
  range, LIMIT 1, via the query engine so it covers every region of the
  table in both standalone and distributed modes) BEFORE any DDL task is
  submitted. A region that fits can no longer commit the new schema
  while another region rejects the alter with a non-retryable error.
  File and row-group pruning keep the scan cheap when nothing overflows.
  The per-region check in mito2 stays as the final guard for data
  written after the preflight (the remaining race window); without a
  validate-only wire field (region.proto lives in the external
  greptime-proto repo) a fully atomic two-phase validate/commit is out
  of scope here.

- fast path: cast_timestamp_unit returns the filter unchanged when the
  literal is already in the target unit, skipping the div-mod rebuild.

Signed-off-by: Ning Sun <sunning@greptime.com>

* fix: address review comments

* fix: address auto review comments

* fix: remove time index widening overflow preflight

Overflow needs timestamps beyond the target unit's i64 range (~year
2262 for nanoseconds), which real workloads never write, so the two
existence scans before every widening alter are not worth the cost.
Region validation already rejects the alter when an SST's time range
overflows the target unit; it now logs the rejection (with the
offending file) and returns a deterministic client-facing message.

Signed-off-by: Ning Sun <sunning@greptime.com>

* test: make sqlness test stable

* fix: log instead of rejecting time index widening overflow

Overflowing values cast to NULL on read but do not otherwise affect
reads or writes, so the alter is allowed; the region-level check now
only logs (with the offending file) when an SST's time range exceeds
the target unit's i64 range.

Signed-off-by: Ning Sun <sunning@greptime.com>

---------

Signed-off-by: Ning Sun <sunning@greptime.com>
2026-09-02 04:29:32 +00:00
LFC 529f046110 refactor: json2 v2 storage layout (#8979)
* refactor: json2 v2 storage layout

Signed-off-by: luofucong <luofc@foxmail.com>

* resolve PR comments

Signed-off-by: luofucong <luofc@foxmail.com>

* fix ci

Signed-off-by: luofucong <luofc@foxmail.com>

* rethinking when "needs_remainder"

Signed-off-by: luofucong <luofc@foxmail.com>

* restore "ReadColumns"

Signed-off-by: luofucong <luofc@foxmail.com>

* resolve PR comments

Signed-off-by: luofucong <luofc@foxmail.com>

* fix ci

Signed-off-by: luofucong <luofc@foxmail.com>

---------

Signed-off-by: luofucong <luofc@foxmail.com>
2026-09-01 13:39:56 +00:00
shuiyisong c4dafb5826 fix(promql): resolve derived labels in aggregation arithmetic (#8994)
Signed-off-by: shuiyisong <xixing.sys@gmail.com>
2026-09-01 13:03:00 +00:00
discord9 7252ceb4bb feat(flow): add generic delta merge for incremental aggregates (#8938)
* feat(function): add internal delta merge aggregates

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(function): cover delta merge aggregates in SQL

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* feat(function): add Welford delta merge aggregate

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-09-01 12:27:54 +00:00
Lei, HUANG c6b10bfbb9 feat(function): add mergeable stddev_pop state functions (#8972)
* feat(function): add Welford stddev functions

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test(function): cover merged Welford time windows

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(function): use stddev_pop SQL names

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(function): make Welford arithmetic partition-stable

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(function): reject invalid singleton Welford states

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test(function): pin Welford state compatibility

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor(function): remove unreachable variance clamp

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(function): reject DISTINCT Welford aggregates

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test(compat): bound Welford downgrade targets

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-08-31 14:15:33 +00:00
dennis zhuang 109257505e feat: report what the graph derives and fix two duplicate-node bugs (#8936)
* feat(semantic-graph): let the generic container yield to k8s.container

A container inside a Kubernetes pod reaches the graph twice: as the
k8s.container entity kube-state-metrics describes, identified by
[pod uid, container name], and as the generic container the OTel resource
attributes describe, identified by container.id. One physical container,
two nodes.

Kubernetes is the primary scenario, so k8s.container keeps its identity
and the generic type stands down where it applies. Conventions gain a
row-level condition for that: `suppressed_by` withdraws a declaration on
rows where any of the named columns has a value. The test has to be per
row, not per table — one descriptor table holds both pod rows and
bare-runtime rows.

Every branch that turns a declaration into rows now shares one guard
(`declaration_predicate`), so the condition cannot apply to entities but
not to the edges they carry.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(semantic-graph): report derived entity declarations in table_semantics

information_schema.table_semantics only read table options, so the
declarations the built-in conventions derive — for trace tables, for
whitelisted Prometheus and OTel descriptor metrics — were invisible.
"Why is my table not in the graph?" was answerable only from debug logs,
which is not a self-service path.

A new `entity_declarations` column reports the entities a table actually
contributes: each one's identity, whether it came from an option or from
the conventions, and any row-level condition attached to it. An expected
entity missing from the list is the answer — the table name is not
whitelisted, the source stamp is wrong, an id column is absent.

The row filter widens to match: a table that declares nothing by option
but derives entities by convention now appears, since it is in the graph
and the view has to say so. The provider reaches the derivation through a
new metadata-only trait method, keeping catalog below operator.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(semantic-graph): never yield a container to an entity nothing derives

The generic container withdrew on any row carrying a pod UID, on the
assumption that k8s.container would cover it. Nothing guaranteed that:
k8s.container came only from kube-state-metrics, so an OTLP-only
deployment — or one whose KSM data had expired or fell outside the query
window — lost the container node and its edges entirely instead of
gaining a more specific one.

The rule now names the superseding type rather than a trigger column, and
withdraws only where that type's full identity is on the row. Both OTel
sources declare k8s.container themselves, under the identity
kube-state-metrics gives it ([pod uid, container name]), so the two
sources name one node; `k8s.container.name` joins the descriptor's
projected attributes to carry it.

Resolution runs once every declaration for the table is known, so a
superseding type that ends up undeclared — its columns are gone, or an
explicit declaration of it was skipped — leaves the guard empty and the
generic container standing. A container can change type; it cannot
disappear.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor(semantic-graph): build the declaration JSON by serializing a type

The column was assembled entry by entry into a serde_json::Map, cloning
every value and allocating a String per key. A Serialize struct that
consumes the declaration moves the same data instead, and the field order
now reads type, origin, identity, then description.

The scan path around it was doing the same kind of avoidable work:
declarations were derived before the predicate could discard the table,
the supersession pass cloned every declaration's identity to look up one,
and the option parse claimed the time index for tables that turn out to
declare nothing.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(semantic-graph): keep the structured identity for single-column ids

`entity_id_attrs` was NULL whenever the identity came from one column, so a
consumer holding `host` = `a3f2...` had no way to tell which column produced
it, and no way back to the source table. Most identities are single-column —
host, k8s.pod, k8s.node, service — so the common case was the opaque one.

Build the JSON object unconditionally. Entity equality still reads `entity_id`
alone, so this changes no merging: it records which attributes the id was
assembled from, beside an id that deliberately omits them.

Also corrects the `entity_id` column doc, which still described the `k=v,k=v`
rendering replaced in #8904 by values joined in declared order.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(semantic-graph): keep what a container carried when it yields

Yielding to k8s.container cost the row two things it had as a generic
container. The runtime container id, which kube_pod_container_info keeps
descriptive precisely because it is the handle back to runtime logs and
metrics, went missing entirely: neither an id nor an attribute of any
node. And the edge vocabulary knew only the generic type, so a row with
the more complete labels ended up with fewer connections than one
without — the container layer no longer reached its host.

Both OTel sources now keep the runtime id and name descriptive on
k8s.container, and the vocabulary gains the two edges that mirror the
generic type's. Nothing checks a supersession against the edge
vocabulary, so that requirement is written down where the rule is.

Also: the conventions-failure path now reports the explicit half as its
comment always claimed, entity_declarations reports scope columns, and
identifies() is private again now that only declaration_predicate calls
it. The two RFCs catch up with entity_id_attrs being unconditional, the
view listing convention-derived tables, and supersession existing.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(semantic-graph): report unmatched clients and the longest request

`real_wins` pins a `calls` edge's RED metrics to the observed span pairs:
when a window's edge key holds any pair, the unmatched client spans are
suppressed so one (window, edge) yields one row. That leaves no way to
tell a callee that stopped responding from traffic that stopped arriving —
both show up as a lower request_count.

Add two columns to `semantic_relationships`:

- `unmatched_count` — client spans with no server span, counted outside
  `real_wins` on the same row, so the suppressed population stays visible
  without splitting the edge into two rows. NULL for agent calls, whose
  inner join leaves nothing unmatched, and for declared edges.
- `duration_max` — the longest single request. It goes through
  `real_wins`: a pair is timed by the server span while an unmatched
  client is timed by its own (network wait included), so mixing them would
  make the max describe a different population than duration_sum and
  duration_count. Agent calls compute it from the child spans they already
  aggregate.

The projection contract goes from 16 to 18 columns; every branch projects
both. Explicit column queries are unaffected, `SELECT *` and
ordinal-based readers see the new shape.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test(semantic-graph): drop the duplicated source-gate case

The whitelist gate on `source=opentelemetry` is already covered by
`otel_implicit_declarations_are_gated` and by the wrong-source case in
`table_semantics`; here it only paid for another table create, insert and
full graph derivation.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* style(semantic-graph): trim the comments back to what the code cannot say

Several comments restated the code, repeated a rationale already stated at
the type or in the RFC, or explained a test in more words than the test
body.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-31 10:39:17 +00:00
Yingwen 28e2b5aca2 feat: expose missing SST manifest fields (#8965)
* feat: expose missing SST manifest fields

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix: preserve SST manifest column ordinals

Signed-off-by: evenyag <realevenyag@gmail.com>

---------

Signed-off-by: evenyag <realevenyag@gmail.com>
2026-08-28 07:55:57 +00:00
localhost 35ea88a4ef feat(ci): run query regression on ephemeral Aliyun ECS runners (#8937)
* feat(ci): add aliyun ecs ephemeral runner path for query regression

Signed-off-by: paomian <xpaomian@gmail.com>

* fix: improve condition for query-regression job execution in workflow

* feat: update Docker installation to use official repository and add GPG key handling

* Refactor query regression runner setup and configuration

- Removed deprecated PersistentVolumeClaim for build cache.
- Introduced a new bootstrap script for setting up the ECS runner host.
- Deleted obsolete Helm values files for runner configuration.
- Updated the Aliyun ECS runner provisioning script to reflect new cache paths.
- Modified GitHub workflows to use the new Aliyun ECS runner setup.
- Adjusted documentation to clarify the new runner lifecycle and provisioning process.

* fix: enhance runner service management during bootstrap process

* fix: update alibabacloud_tea_openapi dependency version in metadata

* feat: enhance ECS runner scripts with region_id and resource_group_id support

* fix: move containerd content store to data root for improved storage management

* feat: rename query-regression runner to ephemeral-github runner and update related scripts

* fix: update sentinel polling method to use serial console output for improved reliability

* fix: add environment variable checks for Alibaba Cloud access keys in ECS client

* fix: improve error handling in GitHub API requests for better diagnostics

* fix: improve cache disk detection logic for Aliyun ECS instances

* fix: enhance cache disk waiting logic with detailed output and error handling

* fix: update dependency version for alibabacloud_tea_openapi in teardown script

* fix: enhance cache disk waiting logic for better compatibility and clarity

* fix: enhance console output handling and add incremental logging during instance provisioning

* fix: add PATH environment variable for runner jobs in service and provision script

* fix: add machine telemetry sampling and logging during query regression jobs

* fix: update query regression documentation and provision script for cache disk handling

* fix: update SCCACHE_CACHE_SIZE validation to 10G for improved caching efficiency

* fix: remove outdated cache size checks and cleanup logic for fresh system disk runs

* fix: enhance instance deletion logic with region handling and console output export

* fix: add swap file setup and OOM handling for ECS runner to improve stability

* fix: update OOM handling and service restart logic for ECS runner to enhance stability

* fix: increase system disk size to 100 GiB for cold double nightly builds to prevent ENOSPC errors

* fix: increase system disk size to 150 GiB for ECS runner to prevent ENOSPC errors

* fix: add keep_instance option to preserve ECS instance for post-mortem debugging

* fix: disable unattended upgrades to prevent job cancellations during library updates

* fix: reduce system disk size to 40 GiB for ECS runner to prevent ENOSPC errors

* feat: Refactor Aliyun ECS runner provisioning and introduce nightly regression comparison

- Update `aliyun-ecs-runner-provision.py` to remove cache disk handling, simplifying the provisioning process.
- Introduce `query-regression-nightly-refs.py` to resolve and compare SHAs from successful nightly builds.
- Create `query-regression-nightly.yml` workflow to trigger nightly comparisons based on successful builds.
- Enhance `query-regression.yml` to include a `test-tooling` job for validating Python scripts before provisioning.
- Update tests for the new nightly reference selection logic and refactor existing tests to align with the new caching strategy.
- Modify documentation to reflect changes in caching and nightly comparison workflows.

* fix: enhance runner image tool verification with detailed checks

* fix: improve error handling in runner image tool verification

* fix: update tool versions in ECS image and workflow for consistency

* fix: correct typo in error message for unparseable ECS creation time

* fix: update README and workflow files for query regression tests and image hygiene

---------

Signed-off-by: paomian <xpaomian@gmail.com>
2026-08-26 12:11:14 +00:00
dennis zhuang 6d86e6ff06 feat: synthesize OTLP resource descriptor for the semantic entity graph (#8904)
* fix(servers): compose OTLP metrics job from service.namespace/service.name

The OTel Prometheus compatibility spec defines job as
"<service.namespace>/<service.name>" when the namespace is present.
The OTLP metrics path only used the bare service.name, so the job tag
diverged from target_info produced by Prometheus-side exporters for the
same resource. Compose the namespace form, and keep not fabricating a
job when service.name is absent.

Behavior change: resources carrying service.namespace now get
"namespace/name" as their job tag value.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(otlp): synthesize otel_resource_info at OTLP metrics ingestion

Ordinary OTLP metrics scatter filtered resource attributes as tags over
every logical metric table, so metrics-only services contribute nothing
to the semantic entity graph. Each request now also projects its
distinct resources into one info-metric-shaped mito table,
otel_resource_info: a fixed allowlist of identity-relevant attributes
under their raw OTel keys (independent of the label translation
strategy and the promote/ignore headers) plus derived job/instance
compatibility columns, value 1.0, and the newest data-point timestamp.

The descriptor is written after the main insert is committed; a failure
there (conflicting pre-existing table, auto-create disabled) degrades
to an OTLP partial_success warning with rejected_data_points = 0
instead of failing the request and triggering client retries of
already-accepted data. A request writing a metric named
otel_resource_info suppresses synthesis. Legacy mode is unchanged.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(operator): otel info-metric conventions with host/container entities

Whitelist the ingestion-synthesized otel_resource_info descriptor via a
new otel_info_metrics conventions map, gated on source=opentelemetry
(the existing gate hardcoded source=prometheus). Its declarations use
explicit descriptive lists instead of descriptive_rest so identifying
attributes of other entities do not leak into service.instance.

Conventions tightened per the Astronomy Shop findings: host identity is
host.id with host.name descriptive only (host.name is not stable across
SDKs and resource detectors), a generic container entity (new entity
type) is declared only when container.id is present, and trace-v1
tables now synthesize host/container from their flattened resource
attributes too. New co-declared edges: service.instance runs_on
container, container runs_on host.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test(otlp): cover the resource descriptor in integration tests

Covers the descriptor's raw-key columns and info-metric options through
the HTTP path, the namespace/name job composition end-to-end, column
names being independent of the translation strategy, the allowlist
excluding unlisted resource attributes, auto-create after a drop, the
metric-name collision suppressing synthesis, and the partial-success
warning (rejected_data_points = 0) when a pre-existing incompatible
table fails the descriptor write while metric data is accepted.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: cargo fmt

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(frontend): degrade descriptor permission denial to a warning

A table-level permission policy denying otel_resource_info would have
failed the whole OTLP metrics request because the descriptor's
permission check ran before the main insert. The descriptor is derived
enrichment: check its permission in the degrade path so a denial skips
the write and surfaces as the partial-success warning, like any other
descriptor write failure.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(otlp): guard descriptor writes with semantic ownership markers

A pre-existing schema-compatible table named otel_resource_info would
silently receive descriptor rows while its missing semantic stamps kept
it out of the entity graph. The descriptor write now requires the
auto-created table's ownership markers (mito engine + signal_type +
source + metric.type=info + metadata_quality=declared) and otherwise
degrades to the partial-success warning; the entity-graph gate for the
otel whitelist likewise requires metric.type=info, so a user table
stamped with only signal/source no longer picks up implicit
declarations.

Also fold the descriptor write cost into the response and surface the
degrade warning through the otel-arrow BatchStatus status_message.
Integration tests pin the full marker set on auto-create and that an
existing owned descriptor keeps accepting writes without degrading —
a missing marker would otherwise silently stop every descriptor write
after the first request.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* perf(otlp): build descriptor rows without the per-resource BTreeMap

Projecting a resource allocated a BTreeMap and then collected it into the
row key, and every attribute was matched against the allowlist by linear
scan. Collect the tags into a Vec and sort once, and match the allowlist
instead of scanning it. Measured on the conversion path: descriptor work
drops 16-18%, from 10.6% to 8.9% of conversion CPU on the worst shape
(1000 resources with 4 data points each), where the cost tracks resource
count rather than data-point count.

Also trims the comments and tests added with the descriptor to what
carries information.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test(otlp): pin the descriptor permission-denial degrade path

A policy denying the descriptor table must not fail the metrics request,
which the fix in 2401b3dd9c does but nothing covered. Verified as a
regression guard by mutation: moving the permission check back before
the main write makes this test fail.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test(otlp): keep legacy mode covered after trimming the unit tests

Trimming the descriptor tests dropped the only assertion that legacy
mode skips the job/instance remap and the promote filter. Both alter
the columns of tables already in use, so fold the check into the legacy
conversion test rather than leaving it uncovered.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(semantic-graph): stop encoding column names into composite entity ids

A composite entity id rendered the identifying columns as sorted
`col=value` pairs, so the same identity split into one entity per
signal: a trace table names its columns service_name and
resource_attributes.service.instance.id where a metric table names them
job and instance. One service instance became two nodes with two
parallel edge sets, breaking the walk from a trace to that instance's
metrics.

Render an id as its values in declared order instead, escaping the
separator so components stay distinguishable, which is what single-column
ids already did by keeping only the value. entity_id_attrs still carries
the structured form.

Values alone are not enough for a namespaced service: the metric side
folds service.namespace into job while traces keep the bare name. Add
qualified_by to the conventions so the trace declarations compose the
namespace the same way, per the OTel rule that job is
<service.namespace>/<service.name> or the bare name when the namespace
is empty. A table without the namespace column keeps the unqualified
identity rather than losing the declaration.

Conventions validation now rejects one entity type declared with a
different number of id columns by two sources, which would silently
produce ids that can never match.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* style(otlp): import the parent module by crate path

check-super-imports.py, part of the CI format gate, rejects a
file-level `use super::`.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(otlp): gate the resource descriptor, and fix what review found

Synthesizing greptime_otel_resource_info creates and writes a table the
user never sent, so it is now off unless
otlp.experimental_enable_resource_info says otherwise. With it off the
request costs exactly what it did before the descriptor existed: nothing
is projected, no table is created, no write and no permission check
happen. Tests run with it on. StandaloneOptions carried no otlp field,
so the whole [otlp] section was silently dropped in standalone mode; map
it through, or the new option (and trace_ingest_chunk_size before it)
would do nothing there.

Renamed from otel_resource_info: the greptime_ prefix marks the table as
engine-managed and makes a collision with a user metric unlikely, which
is what the pre-existing-table ownership check and its per-request
catalog lookup were defending against. Both are gone.

A request may carry data for several graph windows, but the descriptor
folded every data-point time into one row at the newest of them, leaving
the earlier windows with metric rows and no entities. Key the rows by
window as well, and take the times from the data points the encoder
actually writes: it drops exponential histograms, and a resource
carrying nothing else was being described as an entity with no
measurements.

Projecting a resource cloned its attributes once per data point. Nest
the windows under the attributes instead, so they are moved once per
resource, and walk the data-point times through a visitor rather than
collecting a Vec per metric.

Also documents what the two maps key and hold, and lifts the projected
attribute names to constants beside KEY_SERVICE_NAME.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(otlp): skip the descriptor's work entirely when it is disabled

The collision scan over the request's output tables ran even with the
feature off. Short-circuit on the option instead, and update the config
snapshot the new [otlp] section changed.

Also drops the doc comment orphaned by the deleted ownership check: it
had attached itself to the trait impl and described a check that no
longer exists.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor(semantic-graph): drop the expect and name the service identity

The CASE is built through Case directly rather than the fallible
when().otherwise() builder, so the non-test path no longer carries an
expect (architecture-invariants $4).

service_identity returned two same-typed Options that both call sites
destructured positionally; a named struct makes a swap fail to compile.

Also records that id-column order is part of the identity, where the
option docs and the conventions authors will read it.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore(semantic-graph): drop comments that narrate the code

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(semantic-graph): cast duration_nano before the trace-table union

Trace tables written before the signed-integer ingest change hold
duration_nano as UInt64 and later ones as Int64. The calls derivation
unions the per-table selects, and the two have no common integer type,
so a deployment holding both shapes could not build the plan. The
cross-table test now spans both.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor(semantic-graph): drop the redundant duration_nano casts

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(otlp): decide exponential histogram acceptance in one place

The resource descriptor mirrored only the experimental gate, so with both
experimental flags on a resource whose only metric is a delta exponential
histogram was described as an entity with no measurements. The encoder's
whole-metric rules move into exponential_histogram_gate, which both call,
and the descriptor takes its timestamps through exponential_histogram_value
so per-point rejections drop out too.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-25 13:08:44 +00:00
dennis zhuang 1851f6bf4d fix(query): keep INSERT timestamp conversion out of the source query (#8911)
* fix(query): keep INSERT timestamp conversion out of the source query

Interpreting an INSERT's string timestamps used to work by pushing the
conversion down into the source query, which changed what that query
means. Two consequences:

- Pushing through a UNION's DISTINCT moved the dedup key from the raw
  strings to parsed instants, so rows spelling the same instant
  differently collapsed into one. On an append-only table that is a
  silently dropped row.
- A UNION branch that needed no conversion (a NULL, or an explicit cast)
  made the whole column give up, leaving sibling branches on UTC while
  the rest of the row used the session timezone.

Convert at the assignment instead, by routing its cast through a
timezone-carrying timestamp type and back. Arrow applies the timezone
when a cast target carries one, and stripping it afterwards preserves
the value. The source query is no longer touched, so both cases go away
and the tree-walking rewrite (roughly 160 lines) is deleted.

The rewrite reads source types, so it now runs TypeCoercion first: a
UNION still carries its loose per-branch schema before coercion, and
retargeting a cast whose input later becomes a timestamp would shift the
value rather than reinterpret it.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(query): address review on INSERT assignment rewrite

- Clone the input `Arc` instead of the whole subtree, and only rebuild it
  when a `Values` row actually changes.
- Defer cloning the cast source until the literal-folding path has been
  ruled out.
- Move the UTC check onto `Timezone::is_utc`, replacing a bare string
  compare.
- Cover a prepared `INSERT ... VALUES (?)`: an untyped placeholder types
  as `Null`, so the assignment cast is left for parameter substitution.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-25 12:34:53 +00:00
Lei, HUANG 73c4140938 feat(function): expose uddsketch rank (#8929)
* feat(function): expose uddsketch rank

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test(function): cover uddsketch rank in sqlness

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(function): support legacy uddsketch rank

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* docs(function): document uddsketch rank behavior

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-08-25 11:31:47 +00:00
LFC 932f87f7a8 refactor(json2): support querying v2 storage layout (#8940)
* feat(json2): support querying v2 storage layout

- route missing JSON2 paths to the v2 remainder field
- reconstruct complete values from explicit fields and remainder data
- preserve root JSON2 columns across projections and filters
- support nested JSON values in json_get string results
- add and reorganize JSON2 sqlness coverage

Signed-off-by: luofucong <luofc@foxmail.com>

* resolve PR comments

Signed-off-by: luofucong <luofc@foxmail.com>

---------

Signed-off-by: luofucong <luofc@foxmail.com>
2026-08-25 11:11:06 +00:00
discord9 3493d2d0fb perf(servers)!: speed up Prometheus JSON response building with ryu and per-series entry reuse (#8815)
* fix(perf): align direct-SST CREATE TABLE with baked index metadata

The offline fixture generator (query_perf_fixture::direct_sst::
build_region_metadata) bakes greptime:inverted_index /
greptime:skipping_index field metadata into the region manifest for
tag/field columns, but create_table_sql emitted a bare CREATE TABLE
without those declarations. MergeScan's remote-schema validation then
failed on any tag/field projection (HTTP 500 'advertised remote stream
schema field mismatch'), breaking direct_readable_sst perf cases.

CREATE TABLE now declares the matching SKIPPING INDEX WITH
(granularity='1') / INVERTED INDEX column options. A round-trip test
proves the emitted SQL is parser-valid and yields the exact catalog
metadata.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* perf(servers): speed up Prometheus JSON response building with ryu and per-series entry reuse

PrometheusJsonResponse::record_batches_to_data spends ~47% of its CPU
in f64::to_string() per sample and ~32% in IndexMap::entry() per row
(60s profile of concurrent query_range workloads, ~800k series).

- Replace f64::to_string() with ryu::Buffer::format_finite for finite
  values (shortest round-trip, 3-5x faster); NaN/+Inf/-Inf keep the
  previous std formatting so wire output is unchanged.
- Remember the previous row's label vector and entry index; query output
  is clustered by series, so consecutive rows reuse the same IndexMap
  entry via get_index_mut instead of rebuilding and hashing the label
  vector (worst case adds one Vec comparison per series transition).

Also adds a query-regression case (prom_json_response) that measures the
real Prometheus HTTP range API path (/v1/prometheus/api/v1/query_range),
which is the only frontend path that builds the Prometheus JSON response
(TQL ANALYZE formats the SQL JSON shape instead), plus a prom_http query
kind in the regression runner.

Perf (aligned base d90cca4b75, 256 series x 481 points):
- prom_range_2h (JSON response path): 29.31ms -> 21.46ms (-26.8%)
- tql_range_2h_control (non-JSON path): +1.87% (noise)

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(servers): keep Prometheus wire format for integral floats with ryu

ryu::Buffer::format_finite prints integral values as "1.0", but the
Prometheus JSON wire format (matching std f64::to_string) expects "1".
Strip the trailing ".0" that ryu only emits for integral values; extreme
values keep ryu scientific notation, and NaN/Inf keep std output. Adds
wire-format tests covering 1.0, 0.0, -0.0, 1.5, 0.1, 1e21, 1e30, 1e-7,
f64::MAX, NaN, ±Inf.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(servers): address Prometheus response review feedback

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* perf(servers)!: use ryu for Prometheus sample values

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(cmd): skip Prometheus execution time extraction

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-08-25 05:16:50 +00:00
shuiyisong 82444635f5 feat: support quantile and fraction queries on mixed histograms (#8874)
* fix: test

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: remove try_build_float_literal

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: remove NonCommutative

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: NaN

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* chore: add comments

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* test(query): cover frontend-only histogram fold planning

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix(promql): ignore unparseable histogram bucket labels

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: typo

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: sqlness

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

---------

Signed-off-by: shuiyisong <xixing.sys@gmail.com>
2026-08-24 12:45:35 +00:00
LFC d7f1233f77 refactor(json2): support JSON2 storage layout settings in DDL (#8895)
* refactor(json2): add JSON2 storage layout settings

Signed-off-by: luofucong <luofc@foxmail.com>

* resolve PR comments

Signed-off-by: luofucong <luofc@foxmail.com>

---------

Signed-off-by: luofucong <luofc@foxmail.com>
2026-08-17 11:24:44 +00:00
dennis zhuang 10f587bc30 fix(query): preserve timestamp literal semantics in inserts (#8889)
* fix(query): follow timestamp insert assignment lineage

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(query): fold constant insert timestamp literals at the assignment

Following lineage by retyping the source column changed every output
column that reads it: a string column sharing the literal was silently
rewritten to a formatted timestamp, and a nanosecond column was
truncated to the precision of whichever column was converted first.

Resolve the constant read-only and fold it into the assignment
expression instead, which leaves the source query untouched and also
covers literals behind WHERE, ORDER BY and DISTINCT. VALUES rows and
UNION branches carry per-row values, so they keep the in-place rewrite,
now guarded against columns with more than one consumer.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test(query): strengthen insert lineage regression

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test(query): trim redundant insert coverage

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(query): rebuild insert unions loosely and cover UNION distinct

Per review: rebuilding a rewritten union with the strict constructor
rejected legal pre-coercion plans whose untouched columns still differ
across branches. Use try_new_with_loose_types, matching the SQL planner.

Distinct::All joins the rewrite passthrough so UNION (distinct) literals
get session-timezone parsing like UNION ALL; deduplication then keys on
parsed instants instead of raw strings. The top-level rewrite path gains
the same single-consumer guard as rewrite_projection for hand-built DML
plans that share a source column between targets.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* style(query): tighten insert assignment comments

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-17 10:19:08 +00:00
dennis zhuang 09c0b23a23 feat: manage semantic table options via ALTER TABLE SET/UNSET (#8880)
* fix(meta): actually acquire logical table locks in alter-logical-tables procedure

The procedure listed its logical table locks from table_info_values,
which is only filled during Prepare, while procedure lock keys are
fixed at submission — so the logical locks were never acquired. Today
every writer of a logical table's info is serialized by the physical
table lock, which hides the problem; a metadata-only alter procedure
targeting a single logical table would race it.

Resolve the logical table ids at submission, persist them in the
procedure state (serde(default): state dumped by older versions keeps
the previous behavior), lock physical + logical tables, and re-check
the resolved ids against the locked set at Prepare so a table dropped
and recreated after submission cannot be mutated without a lock.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat: manage semantic table options via ALTER TABLE SET/UNSET

CREATE TABLE accepts greptime.semantic.* options, but ALTER TABLE SET
routed every option through SetRegionOption, whose closed match
rejects them — tables auto-created by ingestion could never receive
semantic declarations after the fact.

Semantic options are pure metadata markers no region consumes, so
they now take a metadata-only alter, following the repartition-hint
precedent:

- New AlterKind::SetAnnotations/UnsetAnnotations carrying an
  AnnotationFamily (currently only Semantic), so future marker-style
  option families reuse the same machinery. The converter classifies
  a SET/UNSET batch by key prefix and rejects batches that mix
  annotation keys with regular options.
- The procedure reuses the MetadataOnly flow: no region dispatch,
  table-info update plus cache invalidation only.
- Validation lives in the table-meta mutation layer, so it runs at
  frontend verification and again in the procedure's prepare step
  under the table lock: SET is strict (known key, value domain,
  entity columns exist and render as strings); UNSET is lenient
  inside the namespace so stale keys can be cleaned up.
  ModifyColumnTypes re-checks columns referenced by entity
  declarations at the same layer, closing a verify-then-execute race.
- Logical metric tables are supported: an annotation alter submits a
  regular alter-table task locking only the logical table, and the
  DDL manager's physical-route guard admits it.
- create_table_info re-checks semantic value domains for gRPC-built
  expressions that bypass the SQL parser.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor(table): centralize annotation option classification and validation

Address review feedback on the AnnotationFamily abstraction: with only
one variant that every consumer immediately destructured, the
generality was fake. Make it real and exhaustive instead:

- AnnotationFamily gains RepartitionHint: repartition.column.hint is
  the same kind of marker option (pure metadata, no region consumes
  it) and previously had a hand-rolled special case in the converter,
  the metadata-only classifier, and a dedicated AlterKind pair — all
  deleted, one classification API remains. Per-family logical-table
  eligibility (allows_logical_tables) replaces the hard-coded
  Semantic check in the DDL manager guard.
- One validation core in the table crate (check_annotation) serves
  both DDL entry points. CREATE and ALTER previously duplicated the
  rules; each keeps its existing error variants, status codes and
  messages via thin adapters over a typed error (ALTER missing column
  stays 4002 TableColumnNotFound, CREATE stays InvalidArguments).
- The batch classifier returns Result instead of swallowing the
  mixed-batch error: a mixed SET on a logical table now reports the
  actual problem instead of UnexpectedLogicalRouteTable, and the flow
  classifiers propagate instead of guessing. The converter also moves
  its owned payloads instead of cloning them.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test(meta): cover logical-table annotation alter routing

The route-guard branch admitting metadata-only annotation alters on
logical tables was only exercised end to end by sqlness. Pin it at the
DDL manager level: a semantic SET on a logical table succeeds, updates
only the logical table's metadata and dispatches nothing to datanodes;
a mixed batch reports its own error instead of the route guard's; the
repartition hint stays rejected on logical routes.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(table): keep entity guard on ADD COLUMN and report missing columns first

Review follow-ups: the old verify_alter loop scanned the post-alter
schema, so it also caught DROP COLUMN followed by re-adding the
declared column with a non-string type — the mutation-layer move only
kept the MODIFY path. Guard add_columns the same way (this also covers
ingestion auto-alter). And run the MODIFY drift check after the
existence lookup, so altering a dropped-but-still-declared column
reports ColumnNotExists (4002) like every other MODIFY on a missing
column.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* style(grpc-expr): drop a test comment restating the classifier doc

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor(table): rename annotation validation helpers per review

check_annotation* validated and normalized; align the names with the
validate_and_normalize_* convention nearby, and spell out
AnnotationContext (Cx is not used in this repo).

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-17 09:53:59 +00:00
Lei, HUANG a8924bb95c refactor(udaf): replace uddsketch implementation (#8867)
* refactor(function): replace uddsketch implementation

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* bench(function): compare uddsketch batch ingestion

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* perf(function): avoid copying non-null uddsketch batches

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(function): decode legacy uddsketch states

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(function): harden legacy uddsketch validation

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* format: taplo

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test: add compatibility tests for uddsketch functions

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-08-14 12:20:04 +00:00
dennis zhuang 4dd92c774e feat: add json_object function and use it in the entity-graph derivation (#8870)
* feat: add json_object scalar function

Builds a JSONB object from interleaved (key, value, ...) arguments, like
MySQL's JSON_OBJECT. Values are written into the binary directly, so
JSON-hostile characters (quotes, backslashes, control characters) need no
text-level escaping. Keys must be non-NULL strings; values may be strings,
numbers, booleans, or NULL (JSON null).

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: build entity-graph JSON objects with json_object

The derivation assembled entity_id_attrs and descriptive by concatenating a
JSON text and parsing it, escaping only backslash and double quote in runtime
values. A label containing a control character (e.g. a newline) produced
unparseable text and failed the whole semantic_entities scan instead of one
attribute. json_object assembles the JSONB binary directly from the value
columns, so no text escaping is involved; NULL-to-'' stays at the call site.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: trim comments and fold duplicate test coverage

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: json_object() returns an empty object; narrow values to integers and floats

MySQL's JSON_OBJECT allows an empty pair list, so the signature accepts zero
arguments and the row count falls back to number_rows. Decimals stay rejected
instead of casting to Float64: JSONB numbers (i64/u64/f64) cannot represent
them exactly and a silent precision loss is worse than an explicit cast.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: document key-to-string conversion and align test naming

Keys follow MySQL JSON_OBJECT: any castable type is converted to string.
Rustdoc and the cast-failure message now say so, with a numeric-key test.
Test names take the module-conventional test_ prefix.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-14 08:24:50 +00:00
Morax c3cd186997 fix(query): respect query timezone in timestamp casts (#8859)
* fix(query): respect timezone in insert values

Signed-off-by: Morax <james20081204@gmail.com>

* fix(query): normalize timestamp casts with query timezone

Signed-off-by: Morax <james20081204@gmail.com>

* fix(query): scope timestamp conversion to insert assignments

Signed-off-by: Morax <james20081204@gmail.com>

* style(query): simplify Arc usage

Signed-off-by: Morax <james20081204@gmail.com>

---------

Signed-off-by: Morax <james20081204@gmail.com>
2026-08-14 07:04:51 +00:00
Yingwen 76924c2d36 feat(mito2): introduce two-phase metric series scans (#8826)
* feat(mito2): add two-phase series scan

Signed-off-by: evenyag <realevenyag@gmail.com>

* docs: regenerate configuration reference

Signed-off-by: evenyag <realevenyag@gmail.com>

* test(sqlness): update series scan explain results

Signed-off-by: evenyag <realevenyag@gmail.com>

* test: update config API expectation

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix(mito2): bound two-phase series discovery

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix(mito2): avoid candidate distribution deadlock

Signed-off-by: evenyag <realevenyag@gmail.com>

* chore(mito2): remove obsolete dead code allowances

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix(mito2): share series scan memory pool

Signed-off-by: evenyag <realevenyag@gmail.com>

---------

Signed-off-by: evenyag <realevenyag@gmail.com>
2026-08-14 06:32:17 +00:00
fys 6538db6d61 refactor(json2): push down json2 type hints to parquet reads (#8833)
* refactor(mito): push down json2 type hints to parquet reads

Signed-off-by: fys <fengys1996@gmail.com>

* refactor(mito): share json2 target types with arc

Signed-off-by: fys <fengys1996@gmail.com>

* refactor(mito): derive json2 output schema from target types

Signed-off-by: fys <fengys1996@gmail.com>

* refactor(mito): simplify read columns construction

Signed-off-by: fys <fengys1996@gmail.com>

* fix: cargo check

Signed-off-by: fys <fengys1996@gmail.com>

* fix(mito): reject JSON hints for non-JSON2 read columns

Signed-off-by: fys <fengys1996@gmail.com>

* fix: do not pushdown json type hint of non-json2-col

Signed-off-by: fys <fengys1996@gmail.com>

* fix: unit test

Signed-off-by: fys <fengys1996@gmail.com>

* refactor(query): simplify JSON type hint application

Signed-off-by: fys <fengys1996@gmail.com>

* refactor: clean up JSON2 type hint handling

Signed-off-by: fys <fengys1996@gmail.com>

* refactor(mito2): keep JSON2 hints with flat read format

Signed-off-by: fys <fengys1996@gmail.com>

* fix(mito): use raw parquet projection for output schema

Signed-off-by: fys <fengys1996@gmail.com>

* fix(query): note JSON2 hint scope limitation

Signed-off-by: fys <fengys1996@gmail.com>

* refactor(mito): store JSON target types as native types

Signed-off-by: fys <fengys1996@gmail.com>

* test(json2): cover join hint qualifier limitation

Signed-off-by: fys <fengys1996@gmail.com>

* refactor(mito): remove JSON2 fallback from compat cast

Signed-off-by: fys <fengys1996@gmail.com>

* docs(mito): document ReadColumns ordering contract

Signed-off-by: fys <fengys1996@gmail.com>

* fix: cargo clippy

Signed-off-by: fys <fengys1996@gmail.com>

---------

Signed-off-by: fys <fengys1996@gmail.com>
2026-08-14 06:21:17 +00:00
Ning Sun 354921c80e chore: update mysql test drivers and lru (#8868)
* chore: update mysql test drivers and lru

* fix: test
2026-08-13 10:58:29 +00:00
jeremyhi 764c93bf43 perf(query): choose bounded CTE as hash join build side (#8807)
* fix(query): choose bounded CTE as hash join build side

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* perf(query): remove join estimate cap

* test(compat): accept repartition in analyze plan

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-08-13 10:51:53 +00:00
dennis zhuang 546625c45a feat: embedded convention pack for the entity graph (prom/k8s, gen_ai naming) (#8854)
* feat: embed the derivation conventions as data and adopt gen_ai entity naming

Move the co-declared edge vocabulary, the agent-edge vocabulary and the
virtual-destination candidates from Rust consts into an embedded
conventions.yaml (include_str!), parsed once behind a LazyLock and
validated against the entity-type grammar and the closed rel_type set; a
broken file propagates as a plan error instead of panicking. The agent
vocabulary entity types follow the GenAI semantic-convention namespace
as written: gen_ai.agent / gen_ai.model / gen_ai.tool.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat: drop the tag requirement for entity identity columns

Entity declarations no longer require id columns to be tag/primary-key
columns; only column existence is validated. Trace pipelines flatten the
identifying attributes (span_attributes.gen_ai.agent.id, ...) into field
columns, so the tag rule locked real trace tables out of declaring
entities while buying no correctness — the read-time derivation works on
any column.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat: implicit declarations for well-known prometheus info metrics

Tables stamped signal_type=metric + source=prometheus whose name matches
the conventions.yaml whitelist (kube_pod_info, kube_node_info,
kube_pod_owner, target_info) get implicit entity declarations: k8s.pod /
k8s.node / k8s.workload with name-based identity and target_info's
service / service.instance with the remaining tags as the descriptive
snapshot. The existing co-declared vocabulary then derives runs_on and
part_of from the same rows, so no new edge branch is needed. Explicit
declarations of a type always suppress the implicit one, and the metric
engine's physical table is excluded (it aggregates every logical
table's columns).

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test: cover the prometheus conventions in sqlness and compact the graph cases

Add the whitelisted-info-metric scenario (kube_pod_info, kube_pod_owner,
target_info deriving runs_on / part_of, a non-whitelisted metric
contributing nothing), fold the single-table calls, cross-table pairing
and virtual-node cases into one trace scenario (they exercise the same
union-before-join path), merge the two declaring-metric-table cases, and
reuse one rename probe for both reserved names.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: reject entity id columns without a stable string form

Review follow-ups: the DDL check now validates against the schema and
rejects binary-backed and nested types for identity columns (the
derivation renders ids via CAST to Utf8, so the failure used to surface
only when the graph was scanned); the agent sqlness case keeps its
identity columns as fields to cover the relaxed tag rule end to end;
stale tag-rule comments and a dangling const reference are cleaned up.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: type-check every entity column role, not only ids

The registry renders scope and descriptive values through the same
CAST-to-string path as ids, so a binary-backed column in any role fails
at scan time; the DDL check is now role-independent (and simpler).

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor: name the code-anchored vocabulary constants

Entity types and edge attributes the derivation code itself anchors on
(service, gen_ai.agent, calls, trace/attribute provenance) become
constants in the conventions module; the rest of the vocabulary stays
YAML-only data. ImplicitEntity is renamed PromImplicitEntity, and the
implicit-declaration path logs each skip of a whitelisted info metric
(wrong stamps, suppressed by an explicit declaration, missing id
column) so a missing graph entity is diagnosable.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor: single-source the graph constants

The graph tables' column names move to common-catalog (the schemas
catalog exposes and the plans operator builds must match column by
column), and the conventions module now carries the complete built-in
vocabulary — entity types, rel_types, provenances and connection types —
with the embedded YAML validated by membership against it, so an edit
drifting outside the vocabulary fails the conventions test instead of
deriving nothing.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: treat empty identity components as absent

kube-state-metrics emits empty-string labels an entity id must not be
built from: an unscheduled pod's node and an owner-less pod's owner_kind
/ owner_name. Standard Prometheus drops empty labels (they arrive as
NULL and the existing predicate handles them), but other remote-write
agents may keep them, which produced ghost entities with empty ids and
false runs_on / part_of edges. Every identity predicate (registry,
co-declared edges, span endpoints) now requires non-NULL and non-empty
components through one shared helper.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor: tighten the conventions DSL semantics

Rename the co-declaration rule lists to what they are (co_declared_edges
/ trace_co_declared_edges — derivation rules, not a relation
vocabulary), stop overstating the GenAI entity types (Greptime types
derived from GenAI attributes; OTel defines no model/tool entities),
move target_info's descriptive snapshot to service.instance (the
remaining labels are the target's resource attributes, and instances
would write conflicting snapshots onto the logical service), and extend
the descriptor whitelist with the stable KSM sources: container info
metrics (closing the k8s.pod contains k8s.container rule),
kube_service_info (new k8s.service entity type) and the fuller
descriptive label sets.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: guard entity column types on ALTER as well

ALTER MODIFY COLUMN could change a declared entity column to a type
without a stable string form, deferring the failure to graph scan time;
verify_alter now checks the post-alter schema. Dropping a declared
column stays allowed — the read-time derivation skips the stale
declaration, and semantic options cannot be altered off yet.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat: bridge traces and kube-state-metrics on the pod UID

Trace-v1 tables now get implicit declarations from their flattened
resource attributes (otlp_trace_entities in conventions.yaml): the
service identity — replacing the hardcoded fallback — plus
service.instance and k8s.pod, each applied only when its columns exist.
A new co-declared rule derives service.instance runs_on k8s.pod, and
the whitelisted kube-state-metrics pod identity switches from
namespace+pod names to the UID, so the trace-side pod and every KSM
descriptor land on one entity while names stay descriptive. This also
removes pod identity from the multi-cluster same-name collision.

The conventions rejection tests were passing for the wrong reason (a
half-renamed fixture key failed deserialization before reaching any
validation rule); they now assert the specific error each case targets.
Sqlness covers the UID merge across descriptor tables, pod-contains-
container, the k8s.service node, and the empty-uid/empty-node rows
deriving nothing.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test: cover the OTLP-to-graph chain end to end

One real OTLP export must come out of semantic_relationships as the
zero-configuration chain: service calls service, instance part_of
service, instance runs_on pod (bridged by k8s.pod.uid). Resources
without service.instance.id or k8s.pod.uid derive nothing extra.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: identify k8s.service by UID

Same reasoning as pods: a recreated same-name service must not merge
into the old entity and same-named services across clusters must not
collide; kube_service_info carries a stable uid and nothing joins on the
service's name. Also drop a stale tag-rule mention from the option
validation docs.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: cut duplicated test coverage and redundant comments

The trace service-fallback test collapsed into the resource-entities
test (same synthesis path since the fallback moved to YAML; only the
invalid-explicit-no-fallback case was distinct), role-duplicate and
subsumed DDL cases are gone, the embedded-conventions test is just the
parse (its assertions were decorative), and the YAML section comments no
longer restate the struct docs.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-13 02:31:56 +00:00
dennis zhuang e778a72829 feat: complete the derived-edge vocabulary of the entity graph (#8836)
* feat(operator): pair calls edges across trace tables and derive virtual-node edges

Union the normalized client and server spans of all trace tables before the
join, so a client span pairs with a server span stored in a different table.
A client span with no matching server span becomes an edge to a virtual node
named by span attributes (peer.service / db.name / server.address), with
confidence < 1.0 and attributes.connection_type; a window's real pairs win
over virtual candidates for the same edge key.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(operator): derive same-row co-declared edges from the built-in vocabulary

A table declaring both entity types of a vocabulary pair witnesses the edge
on every row carrying both identities: runs_on / contains / part_of for any
declaring table (provenance 'attribute'), agent uses model / agent invoked
tool only for trace sources (span-structure observations, provenance
'trace').

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(operator): derive parent_agent-calls-agent edges from span structure

Trace tables declaring an agent entity pair each span with its child span
across tables (no span-kind filter), keep pairs whose agent identities
differ, and aggregate RED metrics per window, anchored on the parent span
like the service derivation is anchored on the client.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(frontend): feed co-declared and agent sources into the relationships scan

scan_relationships now passes every declaring table (with its trace-ness)
to the co-declared branch and the trace tables' agent declarations to the
agent-calls derivation. enumerate validates the fixed trace-v1 columns and
derives around a malformed trace table instead of failing the whole scan.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test: cover cross-table pairing, virtual nodes, co-declared and agent edges

sqlness exercises the new derivations end to end (including a malformed
trace-model table being skipped); the integration authorization test now
also pins that a pair split across tables derives no edge when the caller
cannot read one side.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: update the relationships module doc for the new branches

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: import shared derivation helpers via crate paths

The fmt CI gate rejects module-level 'use super::' imports.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: fold co-declared duplicates, decouple agent calls, verify the trace time index

Review findings: the co-declared branch lacked a cross-source DISTINCT, so
two tables witnessing the same edge in one window emitted duplicate rows;
the agent-calls derivation was gated on a usable service declaration; the
trace schema guard accepted a table whose time index is not the column the
derivations bucket by. The empty-trace-table test asserted a union
invariant with no information and is dropped.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: rename the agent-tool edge to invokes and track current OTel peer attributes

The vocabulary's other relation names are present tense; semconv 1.39/1.26
replaced peer.service and db.name with service.peer.name and db.namespace,
so the virtual-node candidates now check the current names first and keep
the deprecated ones for existing telemetry.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: trust the trace-v1 table option instead of matching the fixed schema

The option is only ever stamped by the ingest path, which guarantees the
fixed span columns; matching column types here couples the graph to every
trace schema evolution (e.g. #8816) for a case that cannot occur.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-12 04:06:31 +00:00
Weny Xu 72f6cf09bf refactor(procedure): centralize event context handling (#8834)
* refactor(procedure): centralize event context handling

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(meta): simplify migration trigger reason handling

Signed-off-by: WenyXu <wenymedia@gmail.com>

* refactor(meta): avoid cloning event context

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-08-11 09:05:26 +00:00
discord9 b3faf22290 fix(tests): make two Windows CI failures deterministic (Nightly CI #8837) (#8840)
* fix(tests): reject overlay directories before opening on all platforms

DatanodeOverlay::load() opened the target before checking is_file(). On
Unix, File::open on a directory succeeds and the loader rejects it with
"must be a regular file". On Windows, File::open on a directory fails up
front with "Access is denied", so the type check was never reached and
the rejects_directories_and_parse_errors test failed 4/4 in Nightly CI
(issue #8837).

Check std::fs::metadata before File::open: metadata succeeds on
directories on both platforms, so the error message is now identical
everywhere and the test assertion holds on Windows too.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(datanode): make test_region_error deterministic across platforms

The second phase raced a 100ms mock handle delay against a 200ms
replay_timeout; on busy Windows CI runners the error could land after the
timeout fired, flaking reply.error.is_some() (Nightly CI, issue #8837).
Use a mock handle that returns the error on its first poll with no delay:
the catchup future completes before replay_timeout can ever fire, so the
test no longer depends on wall-clock scheduling.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-08-11 05:52:31 +00:00
Yingwen 78084a9d44 feat: add admin function to discard unflushed data (#8768)
* feat: add admin function to discard unflushed data

Signed-off-by: evenyag <realevenyag@gmail.com>

* test: cover discarding unflushed data by table

Signed-off-by: evenyag <realevenyag@gmail.com>

* chore: fix license header

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix: reject discarding logical metric table data

Signed-off-by: evenyag <realevenyag@gmail.com>

* refactor: defer table name formatting in error paths

Signed-off-by: evenyag <realevenyag@gmail.com>

* chore(deps): update greptime-proto revision

Signed-off-by: evenyag <realevenyag@gmail.com>

* refactor: rename discard unflushed admin function

Signed-off-by: evenyag <realevenyag@gmail.com>

---------

Signed-off-by: evenyag <realevenyag@gmail.com>
2026-08-10 12:19:27 +00:00
dennis zhuang 335a95a369 feat: declared edges and the derivation contract for the entity graph (#8794)
* feat(frontend): run entity-graph derivation as the caller

The derivation contract requires the computed graph tables to run under
the outer query's identity. Capture the caller's QueryContext when the
computed table is resolved, thread it through EntityGraphProvider, and:

- authorize every contributing source table against the caller via the
  new semantic_graph.query permission action, silently excluding denied
  sources (entities, edges and source_tables never appear);
- execute the derivation plan under the caller's context so it inherits
  permissions, cancellation and deadline instead of a fresh default.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(operator): derive the entity-graph window from the scan's time predicate

Implements the RFC window contract for the computed graph tables:

- table: add extract_time_range_strict, a strict variant of the lenient
  time-range extraction that distinguishes an absent observed_at filter
  from one that cannot be safely turned into a range;
- operator: replace GraphWindow with GraphQueryWindow, splitting the
  queried observed_at range from the source-scan range widened to whole
  60s buckets, so boundary buckets aggregate over their full extent;
- frontend: resolve the window from ScanRequest filters — no predicate
  keeps the last-hour default, a missing upper bound means now, and a
  missing lower bound or unextractable shape is an explicit error, never
  a silent fallback.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(operator): system-defined declared-edge table for the entity graph

Reintroduces greptime_private.semantic_relationships_declared with a
canonical, system-owned definition:

- the CREATE TABLE expr (8-tag primary key, business validity columns,
  RED fields, 30d TTL); attributes is now a json column so the future
  union branch matches the computed table without a per-scan parse;
- created on first use on every write path: SQL INSERT creates it
  before executing, and the gRPC row-insert auto-create substitutes the
  canonical expr instead of deriving a schema from the request;
- user DDL (CREATE/ALTER/DROP/RENAME/TRUNCATE) and write-path
  auto-ALTER are rejected via the new is_ddl_reserved_table guard,
  while INSERT/DELETE stay allowed.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat(operator): union declared edges into semantic_relationships

Adds the declared-edge branch to the relationship derivation
(build_relationships_plan replaces build_calls_plan):

- latest revision per edge key first (mito dedups on primary key plus
  observed_at, so a re-asserted edge stores a new revision), then the
  business-validity overlap against the queried window; valid_from
  defaults to the declaration time and a NULL valid_until means the
  edge holds while its row exists;
- the projected observed_at is synthesized inside the queried range
  (Inexact pushdown re-applies the scan's filters above the computed
  table, which would drop rows keyed by the physical revision time);
  window_end/fresh_until of open-ended edges take the window's upper
  bound so 'fresh_until >= now() - ...' queries see them;
- tag columns are cast out of dictionary encoding, and the union is
  re-projected to the 16-column contract;
- the frontend feeds the branch only when the physical table exists,
  the caller may read it, and its schema still matches the canonical
  definition (mismatch is an explicit error, not a silent drop).

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test: cover declared edges, window contract and caller authorization

- sqlness: system auto-create on first INSERT, latest-revision reads,
  open-ended vs retired validity, explicit/lower-only/upper-only window
  behavior, user-DDL rejection, rename-into rejection, DELETE cleanup;
- integration: a permission checker denying one trace table excludes it
  from both semantic_relationships and semantic_entities.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: allow DROP/TRUNCATE on the declared-edge table and fix CI lints

The definition guard rejected every DDL, which left sqlness (and any
shared deployment) no way to remove the table the semantic_graph case
creates — its extra region then broke unrelated region/partition case
expectations. Narrow the guard to what actually protects the canonical
definition: user CREATE, ALTER, RENAME-into and repartition stay
rejected, while DROP and TRUNCATE are allowed — dropping loses nothing
structural, the next INSERT recreates the table canonically, and DROP
doubles as the recovery path if the canonical definition ever changes.
The sqlness case now verifies drop-then-recreate and cleans up after
itself.

Also: rustfmt for the catalog crate and two typo fixes.
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: adapt canonical declared-table create to TriggerReason

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: address review on the declared-edge table lifecycle and revision reads

- gRPC first writes actually work now: the reserved table's creation
  went through the generic create_table_inner, which the definition
  guard itself rejects; both branches of create_or_alter_tables_on_demand
  route it to create_declared_relationships_table instead, and being a
  system action it also bypasses the auto_create_table config/hint;
- revision selection is as-of the queried window: revisions recorded
  after the window's end, or whose validity starts after it, no longer
  outrank (and hide) the revision that was in effect inside it;
- the canonical-schema check validates the whole definition the union
  semantics lean on — time index, primary key, engine, append/merge
  mode — not just column names and types;
- UNDROP TABLE of the reserved name is rejected like CREATE: it could
  resurrect a pre-canonical shape, and the next INSERT recreates the
  table anyway.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* chore: trim over-commenting in the entity-graph code

Comments that restated adjacent code or narrated justification are cut;
the ones stating non-obvious contracts and gotchas stay.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: reject CREATE VIEW against DDL-reserved table names

A view named greptime_private.semantic_relationships_declared would
squat the reserved name: the first INSERT then skips the canonical
create (an object already exists) and graph reads fail on the schema
mismatch. CREATE VIEW now passes the same definition guard as CREATE
TABLE.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat: debug-log authorization exclusions; declared-edge TTL to 90d

Sources the derivation contract silently excludes (per-table denial,
whole-scan denial, the declared-edge table) are invisible from outside;
a debug log at each names what was excluded and why.

The declared-edge table's default TTL becomes 90d, overridable at
creation time via GREPTIMEDB_DECLARED_RELATIONSHIPS_TTL (a proper
configuration option is a TODO).

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: rank declared-edge revisions by the visible edge identity

Ranking partitioned by the full primary key, but the projection drops
scope and generation_id: two assertions of the same visible edge under
different generations both ranked first and came out as duplicate,
indistinguishable rows. Rank by the exposed identity (endpoints,
rel_type, provenance) instead, with generation_id/scope as
deterministic tie-breakers for same-timestamp assertions.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test: drop redundant declared-edge tests

The generations regression is already asserted by the revision and
as-of tests; the DDL shape test restated the declarative builder
against itself. Its one non-tautological check (attributes maps to the
json type) moves into the schema-matcher test.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: reject disjunctive graph windows and unmatchable future windows

- OR/IN over observed_at collapse disjoint ranges into their convex
  hull; a declared edge's synthesized timestamp can land in a gap and
  be dropped by the re-applied filter even though the edge is valid at
  a requested instant. The strict extractor now rejects those shapes.
- A lower bound in the future inverts against the implicit up-to-now
  upper bound; the declared branch then fabricated an edge observed at
  the future bound. Such windows now derive nothing.
- The reserved-table gRPC create path classifies an instant-TTL table
  like every sibling path.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-10 12:18:28 +00:00
dennis zhuang 5d4699db1c docs: refine coding agent maps (#8790)
* docs: refine coding agent maps

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* docs: trim license header guidance

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* docs: update README links and project status

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-10 02:45:37 +00:00
discord9 57b8239ff8 test: rename internal bug numbers in tests to semantic names (#8779)
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-08-07 09:05:20 +00:00
discord9 bb6d55a99f feat: support old-stage datanode config overlays (#8647)
* feat: support old-stage datanode config overlays

Signed-off-by: discord9 <discord9@163.com>

* fix: derive compat overlay policy from WAL config

Signed-off-by: discord9 <discord9@163.com>

---------

Signed-off-by: discord9 <discord9@163.com>
2026-08-07 08:40:46 +00:00
discord9 fbbe5af767 fix(query): avoid unsafe count wildcard rewrites (#8522)
* fix(query): avoid unsafe count wildcard rewrites

Signed-off-by: discord9 <discord9@163.com>

* fix(query): preserve outer count alias

Signed-off-by: discord9 <discord9@163.com>

* fix(query): address review comments on count wildcard rewrite

- Remove the has_projection check: the row count is correct regardless
  of whether a projection exists (per review).
- Explain why checking the first input is equivalent to checking all
  inputs (a plan with zero inputs falls back to count(1)).
- Rename qa_ prefixed tests to follow the module convention.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* test(tql): update tql-cte expectations for count wildcard rewrite

The QP-026 count-wildcard fix rewrites count(*) -> count(time_index), so
the EXPLAIN output for the filtered/final CTE aggregates names the
time-index column. Aligns tql-cte.result with the actual output (CI
failure).

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-08-07 06:46:46 +00:00
dennis zhuang 3d12273c84 feat: read-time entity relationships graph over telemetry (M0+M1) (#8614)
* feat(table): add entity semantic declarations

Define open-ended greptime.semantic.entity.* options, validate entity columns at DDL time, and stamp OTLP trace tables with the service entity declaration.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* feat: add read-time entity relationships graph

Add computed semantic graph tables, typed DataFusion derivation plans for entity registry and trace calls edges, and streaming read-time execution.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* test: exclude semantic graph tables from table constraints

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* refactor(operator): name the plan-builder source groupings

Review feedback: build_registry_plan / build_calls_plan took anonymous
(declarations, DataFrame) tuples while the caller already grouped the same
fields. Introduce RegistrySource { declarations, scan } and CallsSource
{ service, scan } next to the builders and flow them through the frontend
caller and tests. The frontend-side EntitySource keeps holding a TableRef
(the operator builders stay pure over already-built scans), so the named
structs live in operator rather than reusing that type. No behavior change.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
2026-08-07 03:37:14 +00:00
discord9 1693b2727c refactor: port query regression runner to Rust (#8651)
* refactor: port query regression runner to Rust

Signed-off-by: discord9 <discord9@163.com>

* ci: remove optional OTLP report plotter

Signed-off-by: discord9 <discord9@163.com>

* refactor: split query regression runner into modules

Signed-off-by: discord9 <discord9@163.com>

* style: use crate-qualified imports in query regression runner

Signed-off-by: discord9 <discord9@163.com>

* refactor: simplify query regression runner internals

Signed-off-by: discord9 <discord9@163.com>

* feat: abstract inspect-footer storage access behind object store destination

Add an optional --destination <TOML> to inspect-footer (and
--base-destination/--candidate-destination to finalize-remote) so the
storage inspection reads DB data files through the opendal-backed
object_store abstraction instead of bare std::fs. Local paths keep
working unchanged via the --root shortcut (File backend); remote
backends (S3/GCS/...) are described by a DestinationConfig TOML
reusing the object-store crate's ObjectStoreConfig serde shape.

- inspect_footer: list via ObjectStore::list + ObjectMeta filtering
  (parquet keys, non-zero size, metadata/ segment), read footers
  async via ParquetObjectReader + ParquetMetaDataReader with known
  file size (no extra HEAD); output JSON schema unchanged
- finalize-remote: --base-data-home/--candidate-data-home become
  optional, mutually exclusive with the new --*-destination args
- cmd deps: add object_store_opendal + datafusion_object_store
- tests: fs-backend list+footer integration tests (metadata filtering,
  destination TOML mode, root/destination exclusivity)

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* style: drop needless borrow in inspect footer test

Fix clippy::needless_borrows_for_generic_args in the inspect-footer test
(fs::create_dir_all(table.join("metadata"))). Missed by the earlier
focused clippy run because it only covered --bin targets.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-08-06 13:01:32 +00:00
jeremyhi c7c1a61d56 feat: support enabling skip_wal with ALTER TABLE (#8730)
* feat: support enabling skip_wal with alter table

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test: cover skip wal on metric physical region

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: retry skip wal alter on route changes

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: address skip wal review feedback

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: preserve skip wal create options

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: prefer typed skip wal option

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: address skip wal review comments

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: canonicalize legacy skip wal option

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: keep typed skip wal canonical

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: simplify skip wal option tracking

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
2026-08-06 08:29:46 +00:00
discord9 3e63b8abf3 ci: automate compatibility version window (#8608)
* ci: automate compatibility version window

Signed-off-by: discord9 <discord9@163.com>

* ci: address compat version window review feedback

Address all four review comments on the compat version window
automation:

- Keep the PR window to the sliding window only (latest patch of the two
  newest stable minor lines). Exact =vX.Y.Z anchors from case.toml are no
  longer unioned into from_versions; they are validated by the new
  --check-anchors mode and exercised by nightly runs via --nightly-window.
- Add --published-only: the window is computed over stable git tags that
  have a published, non-draft GitHub release carrying the sqlness compat
  artifacts (greptime-linux-amd64 tar.gz and sha256sum), so failed releases
  cannot land in the window.
- Run the updater Python tests plus the window/anchor consistency check in
  PR and merge-group CI (new compat-updater-check job in integration.yml).
- Regenerate tests/compatibility/ci.toml to the current sliding window
  [v1.0.2, v1.1.4].

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
2026-08-06 08:29:00 +00:00
+4 cabc2f6cc6 feat(flow): add information_schema.flow_statistics and SHOW FLOW STATUS (#7987) (#8392)
* feat(flow): add information_schema.flow_statistics and SHOW FLOW STATUS (fixes #7987)

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat(flow): add information_schema.flow_statistics and SHOW FLOW STATUS (fixes #7987)

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* test(flow): add sqlness golden result for flow_status

Signed-off-by: Palak Jha <palakjha916@gmail.com>

* fix(catalog): remove unused OptionExt import in flow_statistics

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* docs(flow): fix stale 'recent errors' comment on QueryFlowExecStats

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* test: regenerate golden results for flow_statistics table

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* style: apply rustfmt to flow_statistics changes

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* refactor(catalog): hoist current_time_millis out of flow loop and clamp uptime

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* chore: remove accidentally committed fmt_check.log

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* Update flow_status.result

del eof trailing blank line as per review

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* test(flow): restore runner-generated trailing blank line for sqlness

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* postgres: include SHOW FLOW STATUS in extended-query describe (return flow_statistics fields)

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix: address reviewer feedback on flow_statistics PR

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(flow): resolve merge conflicts with main

Signed-off-by: polar <palakjha916@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* sqlness check post gen (information_schema.result)

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(flow): record start_time after req/snapshot_seqs built, before dispatch

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(sql): handle ShowFlowStatus in match statement at util.rs

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat: review patch implementation

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* chore: remove accidentally committed local tool output files and fix fmt

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix worker.rs return type formatting

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(flow): apply rustfmt to get_full_flow_stat return type

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix worker.rs return type formatting

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(flow): re-apply rustfmt to get_full_flow_stat return type after merge

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix: merge conflicts

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(auth): warn when credential load disables Postgres SCRAM or drops a line (#8652)

* fix(auth): warn when credential load disables Postgres SCRAM or drops a line

Static and watch user providers degraded silently in two ways:

- A single non-SCRAM verifier (mysql_native_password, or a legacy
  pbkdf2_sha256 hash that predates SCRAM) disables Postgres SCRAM for
  every user and falls back to cleartext, with no signal to the operator.
- A malformed credential line (commonly a plaintext password containing
  '=', which splits into more than two parts) was dropped without a trace.

Emit a warning at each credential load for both cases so operators don't
unknowingly serve cleartext passwords over Postgres or lose a user. This
is logging only; authentication behavior is unchanged. The SCRAM check
never logs secrets, and the malformed-line warning logs the line number
and file, never the line content.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix(auth): warn on credential file read error before truncating

A read error from lines() (I/O failure or invalid UTF-8) ends the
iterator via map_while, silently dropping every remaining credential.
Warn with the line number and file before truncating, matching the
malformed-line handling, so the drop is observable.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* test(object-store): fix racy SecureFs abort test (#8720)

test_writer_abort_is_unsupported_without_atomic_write asserted the file
content immediately after abort() returned Unsupported. SecureFsWriter
writes through tokio::fs::File, whose write_all() only enqueues a blocking
write task (tokio's poll_write returns Ready before the write completes),
so the data may not be visible yet when the test reads the file. Drop the
race-prone content assertion and only verify the Unsupported contract.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat(query): plan native histogram functions (#8705)

* feat(query): plan native histogram functions

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: cr issue & add tests

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: cr issue

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* fix: cr issue

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

---------

Signed-off-by: shuiyisong <xixing.sys@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* perf(promql): avoid repeated scans in sliding range evaluation (#8646)

* perf(promql): use two pointers for sliding range boundaries

Replace the stale cursor heuristic in RangeManipulateStream::calculate_range
with monotonic left/right cursors. The old path rescanned each evaluation
window (O(E x samples-per-window)) and could lose valid samples after sparse
gaps or trailing empty windows. The two pointers keep strict monotonic
progress, reducing boundary generation to O(N + E) while preserving
(curr-range, curr] semantics, start/end shortening, and empty-window output.

Controlled release benchmarks (fixed CPU, ABBA):
- Public RangeManipulate wall time: ~28% faster at 1m/15s, ~66% at 5m/15s,
  ~96% at 1h/15s.
- Warmed distributed TQL ANALYZE 1h queries: ~17-21% faster end to end;
  shorter windows stayed within run-order noise.

Signed-off-by: discord9 <discord9@163.com>

* perf(promql): specialize changes/resets with adaptive edge counting

The generic range_fn macro slices, downcasts, and rescans every overlapping
window for changes() and resets(). Replace the macro path for these two
functions with hand-written UDF wrappers backed by a shared private
edge-count kernel: direct raw-offset scans when requested edges are few,
otherwise one global u64 edge prefix so each window is answered by a prefix
difference.

Behavior is preserved bit-for-bit, including raw null-buffer values, NaN
semantics, signed zero, infinities, empty/singleton windows, independent
timestamp/value offsets, arbitrary window layouts, and exact DataFusion
error messages. The shared proc macro, planner, serializer, and other range
functions are untouched.

Controlled release benchmarks (fixed CPU, ABBA):
- Dense sliding windows (k=4/20/240): 91.7-95.6% less public UDF wall time.
- Low-coverage fallback (N=4096, 8 windows): 73.9-74.4% faster.
- Warmed distributed TQL ANALYZE 5m/1h changes/resets: 12.1-19.7% client
  and 12.0-20.9% server latency improvement; controls stayed within drift.

Signed-off-by: discord9 <discord9@163.com>

* ci(query-regression): include PromQL range boundary case in defaults

An audit of historical query-regression runs found zero range-query
coverage: all 208 PromQL ANALYZE samples were bare selectors, so range
evaluation could regress without CI noticing. Wire the
promql_range_boundary case (introduced in #8646) into DEFAULT_CASES so
label-triggered runs measure the range path. The case is cheap: a ~0.3s
synthetic fixture and about a minute of query execution per base/candidate
pass.

Signed-off-by: discord9 <discord9@163.com>

* chore(promql): address sliding range review nits

Move test-only imports into their test modules and remove the unused
pre-specialization changes and resets helpers.

Signed-off-by: discord9 <discord9@163.com>

* style(promql): apply pinned rustfmt

Signed-off-by: discord9 <discord9@163.com>

* test(promql): cover sparse range results

Share the changes and resets test scaffolding while keeping their behavior
oracles independent. Add an end-to-end sqlness regression for sparse samples,
empty intermediate windows, and a valid trailing sample.

Signed-off-by: discord9 <discord9@163.com>

---------

Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* ci: optimize fuzz and split workflows (#8710)

* ci: batch fuzz targets in GitHub Actions

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: improve fuzz test observability

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(ci): preserve fuzz setup failure artifacts

Signed-off-by: WenyXu <wenymedia@gmail.com>

* test(ci): keep fuzz mock output in logs

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: optimize fuzz worker cache

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: warm fuzz target binaries

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: isolate fuzz workflow

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: centralize fuzz target preparation

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: split general workflows

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: streamline docs required checks

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix: transfer fuzz targets as artifacts

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix: preserve fuzz binary permissions

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: streamline fuzz workers

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: cache PR build dependencies

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: retain main build cache policy

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: address fuzz review feedback

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix: add public constructor for compactor (#8724)

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat(logging): add enable_file_logging option to disable file logging (#8721)

Signed-off-by: xhwhis <hi@whis.me>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* avoid cloning final Prometheus remote write row (#8733)

perf: avoid cloning final Prometheus remote write row

Signed-off-by: lyang24 <lanqingy93@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat(function): add json_object_keys scalar function (#8722)

Expose JSON object key listing for outermost objects, with sqlness coverage.

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* refactor(mito2): revise compaction trigger behavior (#8706)

* refactor(mito2): revise compaction trigger behavior

Distinguish automatic and manual triggers, coalesce explicit automatic follow-ups, and reject concurrent manual compactions.

Remove implicit post-execution continuation and transient idle statuses so scheduler entries always represent an active lifecycle.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito2): track automatic compaction follow-ups

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* docs(mito2): fix compaction transition rustdoc

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito2): mark manual compaction conflict retryable

Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>

* refactor(mito2): drop unused RequestCancelResult::NotRunning variant

request_cancel is only called in tests where the region is guaranteed to be
running, so the NotRunning case was dead code. Simplify to unwrap() and
remove the variant.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito2): gate test-only cancellation import

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix(mito2): prioritize DDL after compaction planning

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat: update dashboard to v0.13.11 (#8737)

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(object-store): skip removed-entry lister test on Windows (#8735)

DirEntry on Windows is a snapshot from FindFirstFileW: file_type() and
metadata() keep returning cached data after the file is removed, so
read_list_entry() cannot observe the deletion. The test asserts the
Unix behavior (lstat returns ENOENT) and fails deterministically on
Windows nightly CI (4/4 tries). Gate it with #[cfg(not(windows))].

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(query): preserve remote dynamic filter target (#8615)

* fix(query): preserve remote dynamic filter target

Signed-off-by: discord9 <discord9@163.com>

* fix(query): check RDF subscriber registration

Signed-off-by: discord9 <discord9@163.com>

* fix(query): refresh initial dyn filter snapshot before dispatch and handle RDF unregister

The remote dynamic filter dispatch ordering regression: freeze the target,
pre-register subscribers, refresh the initial snapshot, then dispatch.
Also implement handle_remote_dyn_filter_unregister to keep unregister
targets consistent with do_get/update.

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

* fix(query): update test-only RegionQueryHandler impl to new trait signatures

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* docs: rework README release badges, drop star history, fix grpc flag (#8743)

* docs: show stable, latest and nightly version badges in README

The single release badge rendered whatever GitHub considered newest, so a
pre-release such as v1.2.0-beta.1 looked like the recommended version.

Split it into three self-updating badges using the shields.io `filter`
parameter, keyed off the existing tag naming:

- stable: `!*-*` matches tags without a hyphen (v1.1.4)
- latest: `!*-*-*` excludes nightly and dev builds (v1.2.0-beta.1)
- nightly: `*-nightly-*` matches the weekly build (v1.2.0-nightly-20260706)

No workflow changes are needed; the badges track new releases on their own.
A one-line caption below them says which channel to pick. The release-date
badge is dropped as the three version badges already carry that signal.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* docs: remove star history chart from README

The chart carried a sealed_token in three URLs and added a large
third-party image to the Project Status section without saying anything
the badges and case studies do not already cover.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* docs: use --grpc-bind-addr in README quickstart

--rpc-bind-addr is now only a hidden alias of --grpc-bind-addr and no
longer shows up in --help.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* Update README.md

Co-authored-by: Ning Sun <classicning@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
Co-authored-by: Ning Sun <classicning@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* chore: check enterprise-gated files are listed in both license configs (#8750)

* chore: check enterprise-gated files are listed in both license configs

A file reachable only through `#[cfg(feature = "enterprise")] mod ...;` is
governed by the GreptimeDB Enterprise License, so it must appear in the
`includes` of licenserc-enterprise.toml and the `excludes` of licenserc.toml.
hawkeye stays silent when it does not: the file keeps its Apache-2.0 header and
passes the default check precisely because it was never excluded from it.

scripts/check-enterprise-license.py walks enterprise-gated `mod` declarations,
resolves them to files (submodules included) and diffs that set against both
configs, also reporting stale entries. It runs in the license job in CI and as
`make check-enterprise-license`.

Documents the split it cannot decide for you — whole enterprise features get
their own file, a gated match arm stays inline — in
.agents/architecture-invariants.md.

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

* fix: tighten enterprise license checks

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>

---------

Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(operator): invalidate local cache after dropping view (#8748)

Signed-off-by: WenyXu <wenymedia@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* chore!: gate soft-drop table behind the enterprise feature (#8747)

* chore: gate soft-drop table behind the enterprise feature

Soft-drop table becomes an enterprise-only feature:

- metasrv rejects gc.experimental_soft_drop.enable=true at startup in
  non-enterprise builds, and ddl_soft_drop_enabled is hard-disabled
  without the enterprise feature as a second line of defense
- the UNDROP TABLE parser/AST/statement variant, ADMIN purge_table()
  registration, and information_schema.recycle_bin registration are
  compiled out unless the enterprise feature is enabled
- common-meta procedures, tombstone keys, and DdlTask serde stay
  unconditional for persisted-procedure recovery and wire compatibility
- the [gc.experimental_soft_drop] section is removed from the OSS
  example config and generated docs (moving to the enterprise repo)
- the soft-drop sqlness cases and their CI job are removed from OSS
  (moving to the enterprise repo); affected information_schema .result
  files are regenerated

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: limit unused_variables allow to non-enterprise builds

Addresses review comment: apply the allow via cfg_attr so enterprise
builds still catch accidental unused variables in register_admin_only.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: include the config key in the soft-drop enterprise gate error

Addresses review comment: name gc.experimental_soft_drop.enable in the
startup validation error so users can locate the setting quickly when
it is set via env vars or layered config.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test: limit unused_mut allow to non-enterprise builds

Addresses review comment: apply the allow via cfg_attr so enterprise
builds still catch unused mut in the table_ddl_event test setup.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* feat: reject soft-drop DDL submissions in non-enterprise builds

Addresses review comment: clients could bypass the SQL-level gates by
submitting DdlTask::UndropTable or DdlTask::PurgeDroppedTable directly
to the procedure service. Reject fresh submissions at the DdlManager
boundary in non-enterprise builds while keeping the procedure loaders
registered for crash recovery and wire compatibility.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test: stop --enable-gc from enabling soft drop in the sqlness template

Addresses review comment: the metasrv test template rendered
[gc.experimental_soft_drop] enable = true under the generic --enable-gc
flag, which non-enterprise metasrv now rejects at startup, making the
documented --enable-gc mode unusable in OSS. Keep the flag scoped to
plain GC; enterprise soft-drop coverage moves to the enterprise repo.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix: gate fresh soft-drop procedures

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test: gate soft-drop fallback coverage

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix: gate soft-drop procedure implementation

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: gate drop table soft-drop behavior

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: gate expired soft-drop gc behavior

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* ci: test enterprise table ddl lifecycle

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* chore: mark purge_table as enterprise licensed

The purge_table module is compiled only with the enterprise feature, so
apply the Enterprise License header and register it with both license
header configurations.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* chore: mark recycle_bin as enterprise licensed

The recycle_bin module is compiled only with the enterprise feature, so
apply the Enterprise License header and register it with both license
header configurations.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* chore: mark soft-drop procedure sources as enterprise licensed

The purge and undrop procedure implementations plus the recycle-bin test
module compile only with the enterprise feature. Apply the Enterprise
License header and register them with both license configurations.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat: make frontend heartbeat extensible and lifecycle-safe (#8726)

* feat: make frontend heartbeat extensible and lifecycle-safe

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: isolate heartbeat extension response handlers

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: cancel in-flight heartbeat response handling

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* test: cover heartbeat wire compatibility

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: clean up failed heartbeat startup

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: address frontend heartbeat review feedback

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(meta): release region guards after drop rollback (#8751)

Signed-off-by: WenyXu <wenymedia@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* refactor!: move native histogram config and `prom_validation_mode` to prom_store (#8744)

* chore: adjust the position of experimental_enable_prometheus_native_histogram

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

* chore: move prom_validation_mode as well

Signed-off-by: shuiyisong <xixing.sys@gmail.com>

---------

Signed-off-by: shuiyisong <xixing.sys@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat: add health-aware gRPC client routing (#8684)

* feat: add gRPC client health routing

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix: harden gRPC client health routing

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix: defer gRPC client health checks until first use

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat(mito2): discard unflushed region data safely (#8600)

* feat: support discarding unflushed region data

Signed-off-by: evenyag <realevenyag@gmail.com>

* fix(mito2): wake stalled writers after discard

Signed-off-by: evenyag <realevenyag@gmail.com>

* refactor(mito2): drop redundant manifest check for discarding unflushed data

Signed-off-by: evenyag <realevenyag@gmail.com>

---------

Signed-off-by: evenyag <realevenyag@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* docs: align wal.sync_period documented default with actual fallback (5s) (#8753)

The example TOMLs and generated config.md documented the default of
wal.sync_period as "10s", but since #5677 moved the WAL sync task to a
background RepeatedTask, an unset sync_period falls back to 5s in
RaftEngineLogStore. The two paths therefore had different fsync
periods: deployments based on the example configs used 10s while bare
configs used 5s.

Align the documentation with the actual code behavior (5s) instead of
changing the code fallback to 10s, so that no existing deployment
silently gets a larger data-loss window on host power loss.

- config/datanode.example.toml, config/standalone.example.toml: 10s -> 5s
- config/config.md: regenerated via make config-docs
- src/cmd/tests/load_config_test.rs: update assertions accordingly

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix: support Utf8View labels in Prometheus response (#8754)

Signed-off-by: evenyag <realevenyag@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix(query): validate merge scan remote schema (#8579)

* fix(query): validate merge scan remote schema

Signed-off-by: discord9 <discord9@163.com>

* fix(query): treat JSON columns as schema-compatible across wire/decode forms

CI (Sqlness json2_limit standalone + distributed) failed on the new
remote-schema validation: a JSON column is Binary + extension metadata
(ARROW:extension:name=greptime.json, greptime:type=Json) on the wire but
decodes to Struct(...) with the extension metadata — validate_remote_schema
compared raw arrow data_type and rejected it as a mismatch.

Adds json_fields_compatible(): JSON fields are equal when name and
nullability match, greptime:type matches, and the JSON2 settings
(ARROW:extension:metadata type hints) match, ignoring the physical arrow
type. Only JSON fields may bypass the raw-type comparison; non-JSON
validation stays strict.

Adds 4 regression tests mirroring the CI failure (wire-binary vs
decoded-struct accepted both directions; different JSON2 settings
rejected; JSON vs plain Binary rejected).

Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>

---------

Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat(grafana): add events dashboard (#8725)

* feat(grafana): add events dashboard

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): tolerate evolving event schemas

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): address events dashboard review

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): restore events dashboard panels

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): bound events dashboard queries

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): include historical event catalogs

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): preserve events drill-down context

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): correct events lifecycle outcomes

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): handle empty event type ranges

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): scope event catalogs to submissions

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): handle empty events dashboard

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(grafana): refresh event schema variables

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* refactor: separate a json2 extension type (#8745)

Signed-off-by: luofucong <luofc@foxmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* feat: add admin function registrar (#8762)

* feat: add admin function registrar

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* fix: reject admin function name collisions

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

* chore: fix typo in admin function test

Signed-off-by: jeremyhi <fengjiachun@gmail.com>

---------

Signed-off-by: jeremyhi <fengjiachun@gmail.com>
Signed-off-by: onepizzateam <palakjha916@gmail.com>

* fix: information_schema.rs table initialization issue

Signed-off-by: onepizzateam <palakjha916@gmail.com>

* rustfmt fix

Signed-off-by: onepizzateam <palakjha916@gmail.com>

---------

Signed-off-by: onepizzateam <palakjha916@gmail.com>
Signed-off-by: Palak Jha <palakjha916@gmail.com>
Signed-off-by: polar <palakjha916@gmail.com>
Signed-off-by: Dennis Zhuang <killme2008@gmail.com>
Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
Signed-off-by: shuiyisong <xixing.sys@gmail.com>
Signed-off-by: discord9 <discord9@163.com>
Signed-off-by: WenyXu <wenymedia@gmail.com>
Signed-off-by: xhwhis <hi@whis.me>
Signed-off-by: lyang24 <lanqingy93@gmail.com>
Signed-off-by: Lei, HUANG <mrsatangel@gmail.com>
Signed-off-by: discord9 <55937128+discord9@users.noreply.github.com>
Signed-off-by: jeremyhi <fengjiachun@gmail.com>
Signed-off-by: evenyag <realevenyag@gmail.com>
Signed-off-by: luofucong <luofc@foxmail.com>
Co-authored-by: dennis zhuang <killme2008@gmail.com>
Co-authored-by: Lei, HUANG <6406592+v0y4g3r@users.noreply.github.com>
Co-authored-by: shuiyisong <113876041+shuiyisong@users.noreply.github.com>
Co-authored-by: discord9 <discord9@163.com>
Co-authored-by: Weny Xu <wenymedia@gmail.com>
Co-authored-by: Ning Sun <sunng@protonmail.com>
Co-authored-by: Whis Liao <xhwhis@gmail.com>
Co-authored-by: Lanqing Yang <lanqingy93@gmail.com>
Co-authored-by: sun <sunchang_long@163.com>
Co-authored-by: Ning Sun <classicning@gmail.com>
Co-authored-by: jeremyhi <jiachun_feng@proton.me>
Co-authored-by: Yingwen <realevenyag@gmail.com>
Co-authored-by: LFC <990479+MichaelScofield@users.noreply.github.com>
2026-08-06 07:24:59 +00:00
LFC 95d9d92e42 refactor: separate a json2 extension type (#8745)
Signed-off-by: luofucong <luofc@foxmail.com>
2026-08-05 12:15:05 +00:00
Lei, HUANG c55f297dec chore!: gate soft-drop table behind the enterprise feature (#8747)
* chore: gate soft-drop table behind the enterprise feature

Soft-drop table becomes an enterprise-only feature:

- metasrv rejects gc.experimental_soft_drop.enable=true at startup in
  non-enterprise builds, and ddl_soft_drop_enabled is hard-disabled
  without the enterprise feature as a second line of defense
- the UNDROP TABLE parser/AST/statement variant, ADMIN purge_table()
  registration, and information_schema.recycle_bin registration are
  compiled out unless the enterprise feature is enabled
- common-meta procedures, tombstone keys, and DdlTask serde stay
  unconditional for persisted-procedure recovery and wire compatibility
- the [gc.experimental_soft_drop] section is removed from the OSS
  example config and generated docs (moving to the enterprise repo)
- the soft-drop sqlness cases and their CI job are removed from OSS
  (moving to the enterprise repo); affected information_schema .result
  files are regenerated

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: limit unused_variables allow to non-enterprise builds

Addresses review comment: apply the allow via cfg_attr so enterprise
builds still catch accidental unused variables in register_admin_only.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: include the config key in the soft-drop enterprise gate error

Addresses review comment: name gc.experimental_soft_drop.enable in the
startup validation error so users can locate the setting quickly when
it is set via env vars or layered config.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test: limit unused_mut allow to non-enterprise builds

Addresses review comment: apply the allow via cfg_attr so enterprise
builds still catch unused mut in the table_ddl_event test setup.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* feat: reject soft-drop DDL submissions in non-enterprise builds

Addresses review comment: clients could bypass the SQL-level gates by
submitting DdlTask::UndropTable or DdlTask::PurgeDroppedTable directly
to the procedure service. Reject fresh submissions at the DdlManager
boundary in non-enterprise builds while keeping the procedure loaders
registered for crash recovery and wire compatibility.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test: stop --enable-gc from enabling soft drop in the sqlness template

Addresses review comment: the metasrv test template rendered
[gc.experimental_soft_drop] enable = true under the generic --enable-gc
flag, which non-enterprise metasrv now rejects at startup, making the
documented --enable-gc mode unusable in OSS. Keep the flag scoped to
plain GC; enterprise soft-drop coverage moves to the enterprise repo.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix: gate fresh soft-drop procedures

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* test: gate soft-drop fallback coverage

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* fix: gate soft-drop procedure implementation

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: gate drop table soft-drop behavior

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* refactor: gate expired soft-drop gc behavior

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* ci: test enterprise table ddl lifecycle

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* chore: mark purge_table as enterprise licensed

The purge_table module is compiled only with the enterprise feature, so
apply the Enterprise License header and register it with both license
header configurations.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* chore: mark recycle_bin as enterprise licensed

The recycle_bin module is compiled only with the enterprise feature, so
apply the Enterprise License header and register it with both license
header configurations.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

* chore: mark soft-drop procedure sources as enterprise licensed

The purge and undrop procedure implementations plus the recycle-bin test
module compile only with the enterprise feature. Apply the Enterprise
License header and register them with both license configurations.

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>

---------

Signed-off-by: Lei, HUANG <ratuthomm@gmail.com>
2026-08-05 04:28:30 +00:00
Whis Liao f639a2099d feat(function): add json_object_keys scalar function (#8722)
Expose JSON object key listing for outermost objects, with sqlness coverage.
2026-08-04 02:31:30 +00:00
Weny Xu a6107fbe3d ci: optimize fuzz and split workflows (#8710)
* ci: batch fuzz targets in GitHub Actions

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: improve fuzz test observability

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix(ci): preserve fuzz setup failure artifacts

Signed-off-by: WenyXu <wenymedia@gmail.com>

* test(ci): keep fuzz mock output in logs

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: optimize fuzz worker cache

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: warm fuzz target binaries

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: isolate fuzz workflow

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: centralize fuzz target preparation

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: split general workflows

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: streamline docs required checks

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix: transfer fuzz targets as artifacts

Signed-off-by: WenyXu <wenymedia@gmail.com>

* fix: preserve fuzz binary permissions

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: streamline fuzz workers

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: cache PR build dependencies

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: retain main build cache policy

Signed-off-by: WenyXu <wenymedia@gmail.com>

* ci: address fuzz review feedback

Signed-off-by: WenyXu <wenymedia@gmail.com>

---------

Signed-off-by: WenyXu <wenymedia@gmail.com>
2026-08-03 07:58:29 +00:00