split() treats the delimiter as a regular expression while replace() treats it literally
メンテナーはふだん 1 日以内に返信
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 82/100
調査の方向性
src/backend/utils/adt/agtype.c を読み、age_split() から開始して、その区切り文字の処理を age_replace() と比較してください。提供された psql の再現手順を、Cypher 経由と直接 SQL 経由の両方で実行してください。'.'、'|'、'+' などのリテラルの区切り文字が regex のエスケープなしで正しく分割され、置換の動作も一貫していれば完了です。
索引モデルが issue の本文から書いたものです。
説明
AGE Version: extension 1.8.0 on PostgreSQL 18.6
Installation Method: Docker
API: Cypher and direct SQL
Steps to reproduce (paste into psql as-is)
LOAD 'age';
SET search_path = ag_catalog, public;
-- Cypher path (re-run: DROP GRAPH xdb CASCADE first)
SELECT * FROM create_graph('xdb');
SELECT * FROM cypher('xdb', $$ RETURN split('a.b.c', '.') $$) AS (r agtype);
-- SQL path (same C function, no graph needed)
SELECT age_split('a.b.c', '.'); -- -> ["", "", "", "", "", ""]
SELECT age_split('a1b1c', '1'); -- -> ["a", "b", "c"] (plain delimiter: works)
SELECT age_replace('a.b.c', '.', '-'); -- -> "a-b-c"
SELECT age_split('a.b.c', '\.'); -- -> ["a", "b", "c"] (only because it is regex-escaped)
SELECT age_split('a|b', '|'); -- -> ["a", "|", "b"]
SELECT age_split('a+b+c', '+'); -- -> ERROR: invalid regular expression: quantifier operand invalid
Expected behavior
openCypher defines the split delimiter as a literal string: split('a.b.c', '.') → ['a','b','c']. Neo4j, Memgraph and FalkorDB all return this without any escaping, and replace('a.b.c', '.', '-') → 'a-b-c' in AGE too — so both functions must interpret '.' identically.
Actual behavior
split('a.b.c', '.')→["","","","","",""](six empty strings): the delimiter is compiled as a regular expression, so '.' matches every character.split('a1b1c', '1')→["a","b","c"]: plain delimiters work, so the regex interpretation only surfaces for metacharacters — exactly where queries silently break.split('a.b.c', '\.')→["a","b","c"]: correct only because the user manually regex-escapes the dot.split('a|b', '|')→["a","|","b"]: the empty-alternation regex splits at every position.split('a+b+c', '+')→ERROR: invalid regular expression: quantifier operand invalid.replace('a.b.c', '.', '-')→"a-b-c": the same engine treats the same delimiter literally.
The engine is internally inconsistent, deviates from openCypher and all sibling engines, and silently corrupts results for common literal delimiters ('.', '|', '+', ...).
Root cause
age_split() (src/backend/utils/adt/agtype.c) passes the delimiter verbatim to PostgreSQL's regexp_split_to_array(), which compiles it as a regular expression; age_replace() performs a literal replacement. Cypher split()/replace() are rewritten to these same SQL functions, so both APIs are affected.
- 主要言語
- C
- スター
- 4.9k
- フォーク
- 529
- 平均マージ
- 8日 15時間
- マージ済み PR(30日)
- 3
環境構築
- Dockerfile・Docker Compose ファイルなし
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
apache/age のほかの issue
-
Mark agtype_string_match_starts_with / _ends_with IMMUTABLE (contains already is)対応中かも @mmustafasenoglu が 13 日前に担当しました。 オープン
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
apache/age#2576 · リアクション 1 件 ·
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
メンテナーはふだん 1 日以内に返信
-
TRUNCATE fails with `schema "ag_catalog" does not exist` in databases without AGE, when AGE is in shared_preload_libraries対応中かも @crdv7 が 14 日前に担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
メンテナーはふだん 1 日以内に返信
-
Integer modulo (%) by a zero divisor errors with `floating-point exception` (22P01) instead of `division by zero`対応中かも @cocofabio が 20 日前に担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 86/100
メンテナーはふだん 1 日以内に返信
-
難易度 5/5 1週間以上 初心者へのやさしさ 30/100
メンテナーはふだん 1 日以内に返信
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
kovidgoyal/kitty#10625 ·
メンテナーはふだん 1 日以内に返信
-
Feature Status: Needs Triage
難易度 2/5 1〜3時間 初心者へのやさしさ 73/100
メンテナーはふだん 1 日以内に返信
-
docs
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
メンテナーはふだん 1 日以内に返信
-
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
RubyMetric/chsrc#396 ·
-
難易度 1/5 1時間未満 初心者へのやさしさ 82/100
riscv-software-src/riscv-isa-sim#2466 ·
メンテナーはふだん 1 日以内に返信