sqlparser support for jsonb

This commit is contained in:
Simon Binder 2024-01-17 22:39:55 +01:00
parent 8adb3bd903
commit b6fbfdbab9
No known key found for this signature in database
GPG Key ID: 7891917E4147B8C0
4 changed files with 60 additions and 5 deletions

View File

@ -1,9 +1,10 @@
## 0.33.1
## 0.34.1
- Fix explicit `NULL` column constraints being dropped when converting nodes
to SQL.
- Add analysis errors for illegal unqualified references to `old` and `new` in
triggers.
- Analysis support for sqlite 3.45 and jsonb functions.
## 0.33.0

View File

@ -5,15 +5,19 @@ class Json1Extension implements Extension {
@override
void register(SqlEngine engine) {
final supportsJsonb = engine.options.version >= SqliteVersion.v3_45;
engine
..registerFunctionHandler(const _Json1Functions())
..registerFunctionHandler(_Json1Functions(supportsJsonb))
..registerTableValuedFunctionHandler(const _JsonEachFunction())
..registerTableValuedFunctionHandler(const _JsonTreeFunction());
}
}
class _Json1Functions implements FunctionHandler {
const _Json1Functions();
final bool _supportBinaryJson;
const _Json1Functions(this._supportBinaryJson);
static const Set<String> _returnStrings = {
'json',
@ -29,12 +33,27 @@ class _Json1Functions implements FunctionHandler {
'json_group_object',
};
static const Set<String> _returnBlobs = {
'jsonb',
'jsonb_array',
'jsonb_insert',
'jsonb_object',
'jsonb_patch',
'jsonb_remove',
'jsonb_replace',
'jsonb_set',
'jsonb_group_array',
'jsonb_group_object'
};
@override
Set<String> get functionNames => const {
Set<String> get functionNames => {
..._returnStrings,
if (_supportBinaryJson) ..._returnBlobs,
'json_type',
'json_valid',
'json_extract',
if (_supportBinaryJson) 'jsonb_extract',
'json_array_length',
};
@ -51,6 +70,8 @@ class _Json1Functions implements FunctionHandler {
if (_returnStrings.contains(name)) {
return const ResolveResult(ResolvedType(type: BasicType.text));
} else if (_returnBlobs.contains(name)) {
return const ResolveResult(ResolvedType(type: BasicType.blob));
} else {
switch (name) {
case 'json_type':
@ -59,6 +80,7 @@ class _Json1Functions implements FunctionHandler {
case 'json_valid':
return const ResolveResult(ResolvedType.bool());
case 'json_extract':
case 'jsonb_extract':
return const ResolveResult.unknown();
case 'json_array_length':
return const ResolveResult(ResolvedType(type: BasicType.int));

View File

@ -93,6 +93,10 @@ class SqliteVersion implements Comparable<SqliteVersion> {
/// can't provide analysis warnings when using recent sqlite3 features.
static const SqliteVersion minimum = SqliteVersion.v3(34);
/// Version `3.55.0` has added support for a binary JSON format and introduces
/// `jsonb` variants of JSON functions.
static const SqliteVersion v3_45 = SqliteVersion.v3(45);
/// Version `3.44.0` has added `ORDER BY` clauses as parameters for aggregate
/// functions and more SQL functions.
static const SqliteVersion v3_44 = SqliteVersion.v3(44);
@ -122,7 +126,7 @@ class SqliteVersion implements Comparable<SqliteVersion> {
/// The highest sqlite version supported by this `sqlparser` package.
///
/// Newer features in `sqlite3` may not be recognized by this library.
static const SqliteVersion current = v3_44;
static const SqliteVersion current = v3_45;
/// The major version of sqlite.
///

View File

@ -1,10 +1,13 @@
import 'package:sqlparser/sqlparser.dart';
import 'package:test/test.dart';
import '../../analysis/errors/utils.dart';
void main() {
group('json with new type inference', () {
final engine = SqlEngine(EngineOptions(
enabledExtensions: const [Json1Extension()],
version: SqliteVersion.v3_45,
));
// add user (name, phone) table
final table = engine.schemaReader.read(
@ -23,6 +26,7 @@ void main() {
}
const resolvedString = ResolveResult(ResolvedType(type: BasicType.text));
const resolvedBlob = ResolveResult(ResolvedType(type: BasicType.blob));
test('create json', () {
expect(findResult("json('{}')"), resolvedString);
@ -38,6 +42,19 @@ void main() {
expect(findResult('json_group_object()'), resolvedString);
});
test('create binary json', () {
expect(findResult("jsonb('{}')"), resolvedBlob);
expect(findResult("jsonb_array('foo', 'bar')"), resolvedBlob);
expect(findResult("jsonb_insert('{}')"), resolvedBlob);
expect(findResult("jsonb_replace('{}')"), resolvedBlob);
expect(findResult("jsonb_set('{}')"), resolvedBlob);
expect(findResult('jsonb_object()'), resolvedBlob);
expect(findResult("jsonb_patch('{}', '{}')"), resolvedBlob);
expect(findResult("jsonb_remove('{}', '{}')"), resolvedBlob);
expect(findResult('jsonb_group_array()'), resolvedBlob);
expect(findResult('jsonb_group_object()'), resolvedBlob);
});
test('json_type', () {
expect(
findResult("json_type('foo', 'bar')"),
@ -71,4 +88,15 @@ SELECT DISTINCT user.name
expect(result.errors, isEmpty);
});
});
test('does not allow jsonb functions before 3.45', () {
final engine = SqlEngine(EngineOptions(version: SqliteVersion.v3_44));
final result = engine.analyze('SELECT jsonb(?);');
expect(result.errors, [
analysisErrorWith(
lexeme: 'jsonb',
type: AnalysisErrorType.unknownFunction,
)
]);
});
}