xo / usql

Universal command-line interface for SQL databases
MIT License
8.91k stars 351 forks source link

Feature request: implement the \bind meta-command #453

Closed alejandrodnm closed 6 months ago

alejandrodnm commented 6 months ago

With pg16 the \bind meta-command was added to psql.

https://www.postgresql.org/docs/16/app-psql.html#APP-PSQL-META-COMMAND-BIND

kenshaw commented 6 months ago

Thanks for pointing this out, as I was not aware this was added to psql. For compatibility reasons, this will be added. I was considering adding different functionality that would do something similar (and may still do so), but there's no problem with getting this implemented/added.

kenshaw commented 6 months ago

I have it working, but I need to fix the statement parser:

Connected with driver postgres (PostgreSQL 16.2 (Debian 16.2-1.pgdg120+2))
Type "help" for help.

pg:postgres@=> select $1 \g
pg:postgres@-> ^C
pg:postgres@=> \bind blah
pg:postgres@=> select $1
pg:postgres@-> \g
 ?column? 
----------
 blah 
(1 row)

pg:postgres@=> 
kenshaw commented 6 months ago

For database drivers that support positional arguments, you can do things like the following now (SQL Server:

$ ./usql ms://
Connected with driver sqlserver (Microsoft SQL Server 16.0.4115.5, RTM, Express Edition (64-bit))
Type "help" for help.

ms:sa@=> \bind a b c
ms:sa@=> select @p2, @p2, @p3, @p1;
 1 | 2 | 3 | 4 
---+---+---+---
 b | b | c | a 
(1 row)

ms:sa@=>  
kenshaw commented 6 months ago

I'm going to push what I have, but the statement parser still needs to be fixed for it to work fluidly with PostgreSQL. It's a fairly straightforward fix -- and I am likely to get it done today -- but requires quite a bit of testing.

The command will work with all databases, the only issue I've identified so far is with use of $1 style identifiers where the database supports dollar strings (ie, PostgreSQL), and trying to do an inline \bind following by a \g. The workaround for this is to just use a \bind command prior to the execution.

kenshaw commented 6 months ago

Ok, I've fixed it:

$ psql postgres://postgres:P4ssw0rd@localhost
psql (16.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384, compression: off)
Type "help" for help.

postgres=# select $1, $2, $2 \bind a b \g
 ?column? | ?column? | ?column? 
----------+----------+----------
 a        | b        | b
(1 row)

postgres=# \q
$ ./usql pg://
Connected with driver postgres (PostgreSQL 16.2 (Debian 16.2-1.pgdg120+2))
Type "help" for help.

pg:postgres@=> select $1, $2, $2 \bind a b \g
 ?column? | ?column? | ?column? 
----------+----------+----------
 a        | b        | b 
(1 row)

pg:postgres@=>  
alejandrodnm commented 6 months ago

@kenshaw 🙇 awesome work