edgedb-cli icon indicating copy to clipboard operation
edgedb-cli copied to clipboard

Support passing query parameters to query files

Open Sikarii opened this issue 2 years ago • 7 comments

Hey!

Passing a script that contains parameters into the CLI will throw edgedb error: DescriptorMismatch: query arguments expected. And it appears that there is seemingly no option to pass them in.

I would prefer the command having some way of passing them in and/or having the option to get interactive prompts for them.

Command (and it's output)

# cat queries\test.edgeql | edgedb
edgedb error: DescriptorMismatch: query arguments expected

# edgedb query --file queries\test.edgeql 
edgedb error: DescriptorMismatch: query arguments expected

Sikarii avatar Oct 11 '22 18:10 Sikarii

Yes, we don't have a way currently. Can you describe your use case a bit more? I'm not sure whether asking interactively makes sense here. Or if we ask interactively whether memoizing variables with the same name across different queries is something expected.

tailhook avatar Oct 12 '22 10:10 tailhook

I personally use the scripts mostly to do occasional seeding to my database, with the script taking in parameters to push different objects to the database.

I would agree that piping into EdgeDB should always imply non-interactive mode, however I would've at least expected edgedb query --file to prompt me for the variables interactively.

As for memoizing them across queries, I think that would be very unexpected; If you run a query with required parameters, you should always provide them.

create-user.edgeql
WITH
  userName := <str>$userName,
  userRoles := <array<str>>$roles,
INSERT User {
  name := userName,
  roles := (select UserRole filter .name in array_unpack(userRoles))
};

Sikarii avatar Oct 12 '22 14:10 Sikarii

As for memoizing them across queries, I think that would be very unexpected; If you run a query with required parameters, you should always provide them.

I mean, in script like this:

INSERT User { name := <str>$userName };
INSERT Inventory { item := (SELECT User FILTER .name = <str>$userName)};

Do you expect userName to be entered twice? (well, technically this can be rewritten into a single query, but this can be less convenient for huge number of inserts)

tailhook avatar Oct 12 '22 14:10 tailhook

As for memoizing them across queries, I think that would be very unexpected; If you run a query with required parameters, you should always provide them.

I mean, in script like this:

INSERT User { name := <str>$userName };
INSERT Inventory { item := (SELECT User FILTER .name = <str>$userName)};

Do you expect userName to be entered twice? (well, technically this can be rewritten into a single query, but this can be less convenient for huge number of inserts)

Oh, my bad. This is an interesting question, my instincts say that it should only have to be entered once since it shares the same query parameter name.

And I believe it should follow the same semantics as the REPL and the clients that interact with EdgeDB, I believe all of them provide one value per query parameter key/name.

Here's the REPL that only asks for it once:

edgedb> WITH
.......   username := <str>$username
....... SELECT {
.......   user1 := username,
.......   user2 := <str>$username
....... };
Parse: 98.7067ms
Parameter <str>$username: test
{{user1: 'test', user2: 'test'}}

Sikarii avatar Oct 12 '22 16:10 Sikarii

Oh, I actually need this. In my case, I use separate files for queries that I later read from my backend code. During development, I want to test the queries before writing any code.

AlexDaniel avatar Aug 10 '23 12:08 AlexDaniel

I'll just leave this here:

#!/bin/bash
(( $# < 1 )) && echo "Usage: $0 <query-file> [...query-args]" && exit 1

query_file=$1
shift;

readarray -t found_tokens < <(grep -Po '>\K\$[\w_]+' -- "$query_file")

declare -A query_args

for arg in "${found_tokens[@]}"; do
    [[ -v query_args[$arg] ]] && continue

    value=$1
    if shift; then
        query_args[$arg]=$value
    else
        read -rp "Enter value for $arg: " value
        query_args[$arg]=$value
    fi
done

sed_args=()
for arg in "${!query_args[@]}"; do
    sed_args+=(-e "s/\\$arg/${query_args[$arg]}/g")
done

edgedb query --file <(sed "${sed_args[@]}" -- "$query_file")

It will ask interactively for args. Moreover, you can also provide the args (in the order of appearance in the file) on the command line, and this way you can easily rerun the query with the same args without having to type them in.

AlexDaniel avatar Aug 27 '23 01:08 AlexDaniel

+1 The CLI is a convenient way to quickly run a query from a file without having to copy and paste around in some UI or mock a client in code.

vwkd avatar Sep 05 '23 19:09 vwkd