Commit graph

23 commits

Author SHA1 Message Date
Linus Groh
6e7459322d AK: Remove StringBuilder::build() in favor of to_deprecated_string()
Having an alias function that only wraps another one is silly, and
keeping the more obvious name should flush out more uses of deprecated
strings.
No behavior change.
2023-01-27 20:38:49 +00:00
Timothy Flynn
41e0e4cdd7 LibSQL: Add parsing and evaluation of BOOLEAN type literals
This allows you to enter TRUE or FALSE in a SQL statement for BOOLEAN
types. Note that this differs from SQLite, which requires entering 1 or
0 for BOOLEANs; having explicit keywords feels a bit more natural.
2023-01-01 10:16:55 +00:00
Timothy Flynn
72e41a7dbd LibSQL: Support 64-bit integer values and handle overflow errors
Currently, integers are stored in LibSQL as 32-bit signed integers, even
if the provided type is unsigned. This resulted in a series of unchecked
unsigned-to-signed conversions, and prevented storing 64-bit values.
Further, mathematical operations were performed without similar checks,
and without checking for overflow.

This changes SQL::Value to behave like SQLite for INTEGER types. In
SQLite, the INTEGER type does not imply a size or signedness of the
underlying type. Instead, SQLite determines on-the-fly what type is
needed as values are created and updated.

To do so, the SQL::Value variant can now hold an i64 or u64 integer. If
a specific type is requested, invalid conversions are now explictly an
error (e.g. converting a stored -1 to a u64 will fail). When binary
mathematical operations are performed, we now try to coerce the RHS
value to a type that works with the LHS value, failing the operation if
that isn't possible. Any overflow or invalid operation (e.g. bitshifting
a 64-bit value by more than 64 bytes) is an error.
2022-12-14 09:21:30 -05:00
Timothy Flynn
b2b9ae27fd LibSQL: Parse and execute sequential placeholder values
This partially implements SQLite's bind-parameter expression to support
indicating placeholder values in a SQL statement. For example:

    INSERT INTO table VALUES (42, ?);

In the above statement, the '?' identifier is a placeholder. This will
allow clients to compile statements a single time while running those
statements any number of times with different placeholder values.

Further, this will help mitigate SQL injection attacks.
2022-12-07 13:09:00 +01:00
Linus Groh
57dc179b1f Everywhere: Rename to_{string => deprecated_string}() where applicable
This will make it easier to support both string types at the same time
while we convert code, and tracking down remaining uses.

One big exception is Value::to_string() in LibJS, where the name is
dictated by the ToString AO.
2022-12-06 08:54:33 +01:00
Timothy Flynn
1524288127 LibSQL: Rewrite the SQL::Value type to be contained within one class
Currently, the Value class is essentially a "pImpl" wrapper around the
ValueImpl hierarchy of classes. This is a bit difficult to follow and
reason about, as methods jump between the Value class and its impl
classes.

This changes the Variant held by Value to instead store the specified
types (String, int, etc.) directly. In doing so, the ValueImpl classes
are removed, and all methods are now just concise Variant visitors.

As part of this rewrite, support for the "array" type is dropped (or
rather, just not re-implemented) as it was unused. If it's needed in the
future, support can be re-added.

This does retain the ability for non-NULL types to store NULL values
(i.e. an empty Optional). I tried dropping this support as well, but it
is depended upon by the on-disk storage classes in non-trivial ways.
2022-10-14 17:47:44 +03:30
Timothy Flynn
7d41b46a7d LibSQL: Remove infallible type conversions from SQL::Value
Force the callers to either know that the type is convertible, or to
handle the conversion failure.
2022-10-14 17:47:44 +03:30
Timothy Flynn
c0b54f18b5 LibSQL: Copy SQL::Value instances less frequently (which may be vectors) 2022-10-14 17:47:44 +03:30
sin-ack
3f3f45580a Everywhere: Add sv suffix to strings relying on StringView(char const*)
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).

No functional changes.
2022-07-12 23:11:35 +02:00
Lenny Maiorani
f912a48315 Userland: Change static const variables to static constexpr
`static const` variables can be computed and initialized at run-time
during initialization or the first time a function is called. Change
them to `static constexpr` to ensure they are computed at
compile-time.

This allows some removal of `strlen` because the length of the
`StringView` can be used which is pre-computed at compile-time.
2022-03-18 19:58:57 +01:00
Timothy Flynn
e649ff5d31 LibSQL: Return a not-yet-implemented error for unimplemented expressions
Easier to debug than returning a NULL value.
2022-02-13 21:30:38 +00:00
Timothy Flynn
b683e8ab77 LibSQL: Return unimplemented errors from unimplemented MATCH expressions
A bit friendlier than crashing the entire SQLService process.
2022-02-10 23:11:13 +01:00
Timothy Flynn
f3c6cb40d7 LibSQL: Convert SQL expression evaluation to use ResultOr
Instead of setting an error in the execution context, we can directly
return that error or the successful value. This lets all callers, who
were already TRY-capable, simply TRY the expression evaluation.
2022-02-10 23:11:13 +01:00
Timothy Flynn
6620f19979 LibSQL+SQLServer: Return the new Result class from statement executions
We can now TRY anything that returns a SQL::Result or an AK::Error.
2022-02-10 12:20:35 +00:00
mnlrsn
66216d3af6 LibSQL: Add simple REGEXP match
The implementation of LIKE uses regexes under the hood, and this
implementation of REGEXP takes the same approach. It employs
PosixExtended from LibRegex with case insensitive and Unicode flags
set. The implementation of LIKE is based on SQLlite specs, but SQLlite
does not offer directions for a built-in regex functionality, so this
one uses LibRegex.
2022-01-23 22:34:53 +03:30
Guilherme Gonçalves
f91d471843 LibSQL: Implement LIKE SQL expressions 2022-01-07 10:50:39 +03:30
Jan de Visser
c369626ac1 LibSQL: Gracefully react to unimplemented valid SQL
Fixes a crash that was caused by a syntax error which is difficult to
catch by the parser: usually identifiers are accepted in column lists,
but they are not in a list of column values to be inserted in an INSERT.

Fixed this by putting in a heuristic check; we probably need a better
way to do this.

Included tests for this case.

Also introduced a new SQL Error code, `NotYetImplemented`, and return
that instead of crashing when encountering unimplemented SQL.
2021-12-04 20:49:22 +03:30
Jan de Visser
001949d77a LibSQL: Improve error handling
The handling of filesystem level errors was basically non-existing or
consisting of `VERIFY_NOT_REACHED` assertions. Addressed this by
* Adding `open` methods to `Heap` and `Database` which return errors.
* Changing the interface of methods of these classes and clients
downstream to propagate these errors.

The constructors of `Heap` and `Database` don't open the underlying
filesystem file anymore.

The SQL statement handlers return an `SQLErrorCode::InternalError`
error code if an error comes back from the lower levels. Note that some
of these errors are things like duplicate index entry errors that should
be caught before the SQL layer attempts to actually update the database.

Added tests to catch attempts to open weird or non-existent files as
databases.

Finally, in between me writing this patch and submitting the PR the
AK::Result<Foo, Bar> template got deprecated in favour of ErrorOr<Foo>.
This resulted in more busywork.
2021-12-04 20:49:22 +03:30
Jan de Visser
3425730294 LibSQL: Implement table joins
This patch introduces table joins. It uses a pretty dumb algorithm-
starting with a singleton '__unity__' row consisting of a single boolean
value, a cartesian product of all tables in the 'FROM' clause is built.
This cartesian product is then filtered through the 'WHERE' clause,
again without any smarts just using brute force.

This patch required a bunch of busy work to allow for example the
ColumnNameExpression having to deal with multiple tables potentially
having columns with the same name.
2021-11-10 14:47:49 +01:00
Jan de Visser
9022cf99ff LibSQL: Add better error handling to evaluate and execute methods
There was a lot of `VERIFY_NOT_REACHED` error handling going on. Fixed
most of those.

A bit of a caveat is that after every `evaluate` call for expressions
that are part of a statement the error status of the `SQLResult` return
value must be called.
2021-10-25 12:59:42 +02:00
Jan de Visser
9d1e27d8a8 LibSQL: Implement evaluate() method of BinaryOperatorExpression
Mostly just calls the appropriate methods on the Value objects.
Exception are the `Concatenate` (string concat), and the logical `and`
and `or` operators which are implemented directly in
`BinaryOperatorExpression::evaluate`
2021-10-25 12:59:42 +02:00
Jan de Visser
fe50598a03 LibSQL: Allow expressions and column names in SELECT ... FROM
Up to now the only ``SELECT`` statement that worked was ``SELECT *
FROM <table>``. This commit allows a column list consisting of
column names and expressions in addition to ``*``. ``WHERE``
still doesn't work though.
2021-10-05 02:22:19 +02:00
Jan de Visser
d074a601df LibSQL+SQLServer: Bare bones INSERT and SELECT statements
This patch provides very basic, bare bones implementations of the
INSERT and SELECT statements. They are *very* limited:
- The only variant of the INSERT statement that currently works is
   SELECT INTO schema.table (column1, column2, ....) VALUES
      (value11, value21, ...), (value12, value22, ...), ...
   where the values are literals.
- The SELECT statement is even more limited, and is only provided to
  allow verification of the INSERT statement. The only form implemented
  is: SELECT * FROM schema.table

These statements required a bit of change in the Statement::execute
API. Originally execute only received a Database object as parameter.
This is not enough; we now pass an ExecutionContext object which
contains the Database, the current result set, and the last Tuple read
from the database. This object will undoubtedly evolve over time.

This API change dragged SQLServer::SQLStatement into the patch.

Another API addition is Expression::evaluate. This method is,
unsurprisingly, used to evaluate expressions, like the values in the
INSERT statement.

Finally, a new test file is added: TestSqlStatementExecution, which
tests the currently implemented statements. As the number and flavour of
implemented statements grows, this test file will probably have to be
restructured.
2021-08-21 22:03:30 +02:00