The main difference between = and != is how null values are handled.
SQLite passes a flag "NULLEQ" to Eq and Ne to disambiguate that.
In the presence of that flag, NULL = NULL.
Some prep work is done to make sure we can pass a flag instead of a
boolean to Eq and Ne. I looked into the bitflags crate but got a bit
scared with the list of dependencies.
Warning:
The following query produces a different result for Limbo:
```
select * from demo where value is null or id == 2;
```
I strongly suspect the issue is with the OR implementation, though. The
bytecode generated is quite different.
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#847
The main difference between = and != is how null values are handled.
SQLite passes a flag "NULLEQ" to Eq and Ne to disambiguate that.
In the presence of that flag, NULL = NULL.
Some prep work is done to make sure we can pass a flag instead of a
boolean to Eq and Ne. I looked into the bitflags crate but got a bit
scared with the list of dependencies.
Instead of always having the caller specify all instructions, this
work introduces convenience functions into the program builder,
making the code a lot cleaner.
The error is due to comparing the PRIMARY KEY's name to INTEGER when in
it was all in lowercase. This was causing `needs_auto_index` to be set
to `true`.
After the fix:
```
/limbo /tmp/sc2-limbo.db
Limbo v0.0.13
Enter ".help" for usage hints.
limbo> CREATE TABLE temp (t1 integer, primary key (t1));
hexdump -s 28 -n 4 /tmp/sc2-limbo.db
000001c 0000 0200 -- matches SQLite
0000020
```
Closes https://github.com/tursodatabase/limbo/issues/824
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#830
The pragma list will only grow. The strum crate can be used to:
* automatically convert to string from enum
* automatically convert to enum from string
* implement an iterator over all elements of the enum
Both () and = variants covered. It is important to make sure that
the transaction is a read transaction, so we cannot hide all that logic
inside update_pragma, and have to make our decision before that.
SQLite holds on to it deeply, for example:
sqlite> create table a(a int);
sqlite> create table b(b integer);
sqlite> create table c(c glauber);
sqlite> pragma table_info=a;
0|a|INT|0||0
sqlite> pragma table_info=b;
0|b|INTEGER|0||0
sqlite> pragma table_info=c;
0|c|glauber|0||0
So we'll keep it as well so we can produce the same responses.
#739
Started adding support for `LIMIT...OFFSET...`
- New `OffsetLimit` opcode
- `OFFSET` is now supported for:
- `SELECT...LIMIT...OFFSET`
- `SELECT...GROUP BY...LIMIT...OFFSET`
- `SELECT...ORDER BY...LIMIT...OFFSET`
- Subqueries for `SELECT` statements
**In progress/todo**
- [x] Testing
- [x] Handle negative offset value
- **(will make in separate PR)** Add support for
`DELETE...LIMIT...OFFSET`
- **(will make in separate PR)** Use `limit + offset` sum register from
`OffsetLimit` to constrain number of records inserted into sorter
Closes#779
Allow us to write queries like:
SELECT name, type, sql FROM sqlite_schema where sql isnull
and
SELECT name, type, sql FROM sqlite_schema where sql not null
Reviewed-by: Jussi Saurio <jussi.saurio@gmail.com>
Closes#829
Closes#812
`-9223372036854775808` is `MIN_INT64`. So when we extract out the minus
and try to parse the remainder it becomes greater than MAX_INT64
(9223372036854775807) and will trigger overflow, which converts the
literal into `Real`. So we have to handle it as a special case.
Reviewed-by: Kim Seon Woo (@seonWKim)
Closes#814
Allow us to write queries like:
SELECT name, type, sql FROM sqlite_schema where sql isnull
and
SELECT name, type, sql FROM sqlite_schema where sql not null
First review #820
The function follows RFC 7386 JSON Merge Patch semantics:
* If the patch is null, the target is replaced with null
* If the patch contains a scalar value, the target is replaced with that
value
* If both target and patch are objects, the patch is recursively applied
* null values in the patch result in property removal from the target
Closes#821
skip rows
Emit Integer, OffsetLimit instructions for offset, and define function to emit IfPosinstruction to skip rows
Emit IfPos instructions to handle offset for simple select
Emit IfPos to handle offset for select with order by
Moved repeated emit_offset function call into emit_select_result
I think it is mostly correct, not so sure how to handle `BLOB`. One
thing that caught my attention is that sqlite seems to have a
optimization for trivial cases, saving some bytecodes, for instance:

I'm looking that right now.
Closes#777
Take the logical OR of the values in register P1 and P2 and store the answer in register P3. If either P1 or P2 is nonzero (true) then the result is 1 (true) even if the other input is NULL. A NULL and false or two NULLs give a NULL output.
Take the logical AND of the values in registers P1 and P2 and write the result into register P3. If either P1 or P2 is 0 (false) then the result is 0 even if the other input is NULL. A NULL and true or two NULLs give a NULL output.
Wire pragma wal_checkpoint to checkpoint infra
- add basic support for parsing and instruction emitting `pragma
wal_checkpoint;`
- checkpoint opcode for instruction
- checkpoint execution in `virtual machine`
- cli test
Part of #696.
Before
```
limbo> pragma wal_checkpoint;
× Parse error: Not a valid pragma name
```
After
```
Enter ".help" for usage hints.
limbo> pragma wal_checkpoint;
0|0|0
```
```
Closes#694
Relates to #127. This PR is still in draft and I have a few left things
to do (tests, improve implementation), just opening it so anyone can
track this work meanwhile.
Closes#664