This PR changes the argument parsing and matching to use Clap instead of
our own handrolled one. This makes it much easier to add new commands
and modify existing ones by using the full power of clap's derive
macros. It also produces nice error and help messages for us. However,
there is a bug in Clap that is not correctly modifying the `display
name` in the help section. So the command would appear as `show` instead
of `.show` in the help messages. This is very minimal, but if this is a
blocker for this PR we can just overwrite the help message in its
entirety. Also using Clap would enable us to use its autocomplete crate
to generate autocompletions for these special repl commands which would
be a huge win when compared to the `sqlite3` cli.
This is the current help message:
```sh
Limbo SQL Shell Help
==============
Welcome to the Limbo SQL Shell! You can execute any standard SQL command here.
In addition to standard SQL commands, the following special commands are available:
Usage: <COMMAND>
Commands:
exit Exit this program with return-code CODE
quit Quit the shell
open Open a database file
schema Print this message or the help of the given subcommand(s) Display schema for a table
output Set output file (or stdout if empty)
mode Set output display mode
opcodes Show vdbe opcodes
cd Change the current working directory
show Display information about settings
nullvalue Set the value of NULL to be printed in 'list' mode
echo Toggle 'echo' mode to repeat commands before execution
tables Display tables
import Import data from FILE into TABLE
load Loads an extension library
dump Dump the current database as a list of SQL statements
listvfs List vfs modules available
help Print this message or the help of the given subcommand(s)
Usage Examples:
---------------
1. To quit the Limbo SQL Shell:
.quit
2. To open a database file at path './employees.db':
.open employees.db
3. To view the schema of a table named 'employees':
.schema employees
4. To list all tables:
.tables
5. To list all available SQL opcodes:
.opcodes
6. To change the current output mode to 'pretty':
.mode pretty
7. Send output to STDOUT if no file is specified:
.output
8. To change the current working directory to '/tmp':
.cd /tmp
9. Show the current values of settings:
.show
10. To import csv file 'sample.csv' into 'csv_table' table:
.import --csv sample.csv csv_table
11. To display the database contents as SQL:
.dump
12. To load an extension library:
.load /target/debug/liblimbo_regexp
13. To list all available VFS:
.listvfs
Note:
- All SQL commands must end with a semicolon (;).
- Special commands start with a dot (.) and are not required to end with a semicolon.
```
If we need more information on a specific command, we can leverage CLAP
and do for instance:
```sh
.open -h
```
Reviewed-by: Pere Diaz Bou <pere-altea@homail.com>
Closes#1110
Improve allocation usage from ImmutableRecords by reusing them.
ImmutableRecord is basically a contigous piece of memory that holds the
current record. If we move to some other record we usually deallocate
the previous one and allocate a new one -- obviously this is wasteful.
With this commit we will reuse the ImmutableRecord to allow payload to
be extended if needed or reused if we can, making it faster to iterate
records basically.
Closes#1206Closes#447Closes#1117
Issues:
1. Rust floating point math fucntions are non deterministic.
2. SQLite have complex floating point display rules.
I changed rust functions to libm for math ops and implemented Display
trait for OwnedValue:Float. A lot of float formatting SQLite probably
inherits from C have to be handcrafted.
Closes#1208
### The problem:
I often need to copy the output of an `Explain` statement to my
clipboard. Currently this is not possible because it currently will only
write to stdout.
All other limbo output, I am able to run `.output file` in the CLI, then
enter my query and in another tmux pane I simply `cat file | xclip -in
-selection clipboard`.
### The solution:
Expose a `statement.explain()` method that returns the query explanation
as a string. If the user uses something like `execute` instead of
prepare, it will default to `stdout` as expected, but this allows the
user to access the query plan on the prepared statement and do with it
what they please.
Closes#1166
OwnedValue has become a powerhouse of madness, mainly because I decided
to do it like that when I first introduced AggContext. I decided it was
enough and I introduced a `Register` struct that contains `OwnedValue`,
`Record` and `Aggregation`, this way we don't use `OwnedValue` for
everything make everyone's life harder.
This is the next step towards making ImmutableRecords the default
because I want to remove unnecessary allocations. Right now we clone
OwnedValues when we generate a record more than needed.
We currently have two value types, `Value` and `OwnedValue`. The
original thinking was that `Value` is external type and `OwnedValue` is
internal type. However, this just results in unnecessary transformation
between the types as data crosses the Limbo library boundary.
Let's just follow SQLite here and consolidate on a single value type
(where `sqlite3_value` is just an alias for the internal `Mem` type).
The way this will eventually work is that we can have bunch of
pre-allocated `OwnedValue` objects in `ProgramState` and basically
return a reference to them all the way to the application itself, which
extracts the actual value.
In the INSERT statement generated by dump function, if the type affinity
of the value is TEXT, replace each single quotation mark with two single
quotation marks, and wrap it with single quotation marks.
This is a basic support for the very useful .dump command.
It doesn't yet implement any of the dump options sqlite has,
and it doesn't add some of the logic for things like indexes,
since we don't have them.
Bug: Infinite loop when parsing unclosed string literal
To reproduce:
Run query: `SELECT max(';`
Current behavior:
- Query runner enters an infinite loop when encountering an unclosed
string literal and prints error
Fix:
- Throw error and stop query runner loop
Closes#988Closes#989