Skip to content

feat: Query parameters in interactive mode (:param)#98

Open
Ignition wants to merge 2 commits into
masterfrom
feat/param-command
Open

feat: Query parameters in interactive mode (:param)#98
Ignition wants to merge 2 commits into
masterfrom
feat/param-command

Conversation

@Ignition
Copy link
Copy Markdown

@Ignition Ignition commented Jun 5, 2026

Query parameters

Adds cypher-shell-style parameters to the interactive REPL:

  • :param <name> <expression> — set a parameter to a server-evaluated value
  • :params — list parameters
  • :params clear — remove all

Expressions are evaluated server-side via RETURN, so parameters get full Cypher types and can reference earlier ones (:param age 21 * 2). Set values are passed to every later query and used as $name.

Fix: replxx abort on multi-line buffers

history_previous() in the pinned replxx indexes prev_newline_position(_pos - 1) without the _pos > 0 guard its sibling has, so navigating up through a multi-line buffer aborts the shell. Fixed by a small patch to replxx applied via PATCH_COMMAND, plus a Ctrl-J rebind so pasted multi-line input submits one line at a time.

Add cypher-shell-style query parameters to the interactive REPL:

  :param <name> <expression>   set a parameter to a server-evaluated value
  :params                      list all set parameters
  :params clear                remove all parameters

Expressions are evaluated server-side via RETURN, giving full Cypher type
support, and may reference previously set parameters. Set parameters are
passed to every subsequent query via mg_session_run.

The parser (ParseParamCommand) and parameter store (ParamStore) live in a
new mgclient-only `params` library and are covered by unit tests. mg_memory
is extracted into its own header so the library and its test don't depend on
replxx. The REPL wiring (dispatch, server-eval, ExecuteQuery params arg) is
thin glue verified manually.
@Ignition Ignition requested a review from mattkjames7 June 5, 2026 11:39
@Ignition Ignition self-assigned this Jun 5, 2026
@Ignition Ignition force-pushed the feat/param-command branch from 05291fb to 2662b16 Compare June 5, 2026 12:16
@Ignition Ignition added bug bug enhancement enhancement labels Jun 5, 2026
mgconsole assembles multi-line queries itself via the continuation prompt and
does not use replxx's in-buffer multiline editing, which is buggy in the pinned
release-0.0.4. history_previous() calls prev_newline_position(_pos - 1) without
the `_pos > 0` guard its sibling history_next() has; with a newline at buffer
position 0 (navigating up through a recalled multi-line history entry) it passes
-1 and trips an assertion that aborts the process. Separately, in-buffer
multiline redraws clear to end of screen and erase already-printed output.

Patch replxx (replxx-patches/, applied via the replxx-proj PATCH_COMMAND) to add
the missing bounds guard to history_previous. This fixes the abort for any
newline-bearing buffer, including multi-line entries decoded from the history
file.

Rebind Ctrl-J (line feed, 0x0A) to commit_line so a bare newline submits the
current line like Enter instead of feeding replxx's NEW_LINE action. A multi-line
paste then submits one physical line at a time, which is what GetQuery expects,
and keeps pasted or typed newlines out of the buffer so the redraw corruption
stays unreachable for the common paste case. It does not cover newlines that
arrive from history, which is why the bounds guard is the actual crash fix.
@Ignition Ignition force-pushed the feat/param-command branch from 2662b16 to 79b81af Compare June 5, 2026 12:23
Copy link
Copy Markdown
Contributor

@mattkjames7 mattkjames7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of suggestions + question about replxx (not sure what alternatives we have here).

I compiled it and had a play with it myself, looks good! :shipit:

@@ -0,0 +1,24 @@
Add the missing bounds guard to ReplxxImpl::history_previous.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the replxx repo is unmaintained - should we consider an alternative at some point?

Comment thread src/parameters.cpp

namespace {

constexpr const char *kWhitespace = " \t\r\n";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we include \f and \v in here?

CHECK(result.command->kind == ParamCommand::Kind::kSet);
CHECK_EQ(result.command->name, std::string{"x"});
CHECK_EQ(result.command->expression, std::string{"1 + 2"});
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably check that result.error is empty here

CHECK(result.command.has_value());
if (result.command) {
CHECK(result.command->kind == ParamCommand::Kind::kList);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and check result.error here

CHECK(result.command.has_value());
if (result.command) {
CHECK(result.command->kind == ParamCommand::Kind::kClear);
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

check result.error is empty

// Lines that are not parameter commands are left for other handlers, including
// look-alikes such as `:paramfoo` that share the `:param` prefix.
void non_param_lines_are_ignored() {
for (const char *line : {":help", ":quit", "MATCH (n) RETURN n;", ":paramfoo", ""}) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

could also add :paramsfoo here too

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug bug enhancement enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants