Skip to content

Commit

Permalink
Upgrade to boon v0.6
Browse files Browse the repository at this point in the history
Use the new `use_loader()` function to configure it with an empty list
of loaders, thereby preventing Boon from loading the default file
loader. Remove `FailLoader`, as it is no longer needed ot override the
default file loader.

Adjust to the lazy schema validation added in
santhosh-tekuri/boon@fbcc178 to test that an invalid metaschema triggers
an error at compile time instead of schema loading time. Affects both
the pgrx and pg_regress tests.

Update tests for boon error message URLs to include the fragment `#`
character.
  • Loading branch information
theory committed Jun 12, 2024
1 parent 7c7f8d8 commit b421e34
Show file tree
Hide file tree
Showing 8 changed files with 43 additions and 37 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,16 @@ All notable changes to this project will be documented in this file. It uses the

## [v0.1.1] --- Unreleased

The them of this release is *fast follows.*
The theme of this release is *fast follows.*

### ⬆️ Dependency Updates

* Updated boon to v0.6.

### ⚡ Improvements

* Removed custom schema loader, taking advantage of the feature of boon v0.6
to remove all loaders (santhosh-tekuri/boon#12).

## [v0.1.0] --- 2024-04-30

Expand Down
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ pg_test = []

[dependencies]
pgrx = "=0.11.4"
boon = "0.5"
boon = "0.6"
serde_json = "1.0"

[dev-dependencies]
Expand Down
32 changes: 11 additions & 21 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use boon::{CompileError, Compiler, Schemas};
use pgrx::prelude::*;
use pgrx::{Json, JsonB, VariadicArray};
use serde_json::Value;
use std::error::Error;

pgrx::pg_module_magic!();

Expand Down Expand Up @@ -237,8 +236,8 @@ extern "C" fn _PG_init() {
fn new_compiler(id: &str, schemas: &[Value]) -> Result<Compiler, CompileError> {
let mut compiler = Compiler::new();
compiler.set_default_draft(GUC.get().into());
// Replace file loader to prevent boon from accessing the file system.
compiler.register_url_loader("file", Box::new(FailLoader));
// Use an empty loader to prevent boon from accessing the file system.
compiler.use_loader(Box::new(boon::SchemeUrlLoader::new()));

for (i, s) in schemas.iter().enumerate() {
let sid = if let Value::String(s) = &s["$id"] {
Expand Down Expand Up @@ -294,25 +293,14 @@ fn validate(id: &str, schemas: &[Value], instance: Value) -> Result<bool, Compil
}
}

// FailLoader always fails to load the URL for its scheme. Used to replace the
// default "file" loader to prevent boon from trying to read the file system.
struct FailLoader;

impl boon::UrlLoader for FailLoader {
fn load(&self, url: &str) -> Result<Value, Box<dyn Error>> {
Err(Box::new(boon::CompileError::UnsupportedUrlScheme {
url: url.to_string(),
}))
}
}

#[cfg(any(test, feature = "pg_test"))]
#[pg_schema]
mod tests {
use super::*;
use pgrx::pg_sys::panic::CaughtError::PostgresError;
use pgrx::{spi::SpiError, Json, JsonB};
use serde_json::json;
use std::error::Error;

// Enum used to record handling expected errors.
#[derive(Debug, Eq, PartialEq)]
Expand Down Expand Up @@ -383,7 +371,7 @@ mod tests {

// Make sure it compiles user and address.
let mut c = c.unwrap();
let mut schemas = Schemas::new();
let mut schemas: Schemas = Schemas::new();
c.compile(&id, &mut schemas)?;

let mut schemas = Schemas::new();
Expand Down Expand Up @@ -414,7 +402,7 @@ mod tests {
if let Err(e) = err {
assert!(e.source().is_some());
if let Some(e) = e.source() {
// We should have the unsupported scheme error from FailLoader.
// We should have the unsupported scheme because no loaders enabled.
assert_eq!("unsupported scheme in file:///test.json2", format!("{e}"));
} else {
// Shouldn't happen
Expand All @@ -426,7 +414,9 @@ mod tests {
}

// Test an invalid draft.
assert!(new_compiler(&id, &[json!({"$schema": "lol"})]).is_err());
let mut c = new_compiler(&id, &[json!({"$schema": "lol"})]).unwrap();
let mut schemas: Schemas = Schemas::new();
assert!(c.compile(&id, &mut schemas).is_err());

Ok(())
}
Expand Down Expand Up @@ -663,7 +653,7 @@ mod tests {
.catch_when(PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, |e| {
if let PostgresError(e) = e {
assert_eq!(
"file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#\n- at '/type': anyOf failed\n - at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'\n - at '/type': want array, but got string",
"file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#\n- at '/type': anyOf failed\n - at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'\n - at '/type': want array, but got string",
e.message(),
);
}
Expand Down Expand Up @@ -729,7 +719,7 @@ mod tests {
.catch_when(PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, |e| {
if let PostgresError(e) = e {
assert_eq!(
"file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#\n- at '/type': anyOf failed\n - at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'\n - at '/type': want array, but got string",
"file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#\n- at '/type': anyOf failed\n - at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'\n - at '/type': want array, but got string",
e.message(),
);
}
Expand Down Expand Up @@ -847,7 +837,7 @@ mod tests {
.catch_when(PgSqlErrorCode::ERRCODE_INTERNAL_ERROR, |e| {
if let PostgresError(e) = e {
assert_eq!(
"file:///lol.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#\n- at '/type': anyOf failed\n - at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'\n - at '/type': want array, but got string",
"error loading https://example.com/address.schema.json: unsupported scheme in https://example.com/address.schema.json",
e.message(),
);
}
Expand Down
4 changes: 2 additions & 2 deletions test/expected/is_valid.out
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@ SELECT jsonschema_is_valid('{"type": "object"}'::jsonb);

-- Invalid schema
SELECT jsonschema_is_valid('["not a schema"]'::json);
INFO: file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
INFO: file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '': want boolean or object, but got array
jsonschema_is_valid
---------------------
f
(1 row)

SELECT jsonschema_is_valid('["not a schema"]'::jsonb);
INFO: file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
INFO: file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '': want boolean or object, but got array
jsonschema_is_valid
---------------------
Expand Down
4 changes: 2 additions & 2 deletions test/expected/matches.out
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ INFO: jsonschema validation failed with file:///schema.json#

-- Invalid schema
SELECT json_matches_schema('{"type": "nonesuch"}', '{"x": "y"}');
ERROR: file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
SELECT jsonb_matches_schema('{"type": "nonesuch"}', '{"x": "y"}');
ERROR: file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
Expand Down
14 changes: 7 additions & 7 deletions test/expected/validates.out
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,12 @@ INFO: jsonschema validation failed with file:///schema.json#

-- Invalid schema
SELECT jsonschema_validates('{"x": "y"}'::json, '{"type": "nonesuch"}'::jsonb);
ERROR: file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
SELECT jsonschema_validates('{"x": "y"}'::jsonb, '{"type": "nonesuch"}'::json);
ERROR: file:///schema.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: file:///schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
Expand Down Expand Up @@ -201,24 +201,24 @@ INFO: jsonschema validation failed with https://example.com/user-profile.schema
(1 row)

-- Invalid schema
\set invalid_schema '{"type": "nonesuch", "$id": "file:///lol.json"}'
\set invalid_schema '{"type": "nonesuch"}'
SELECT jsonschema_validates(:'user'::json, :'user_schema_id', :'invalid_schema'::json, :'user_schema'::json );
ERROR: file:///lol.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: https://example.com/user-profile.schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
SELECT jsonschema_validates(:'user'::json, :'user_schema_id', :'invalid_schema'::jsonb, :'user_schema'::jsonb );
ERROR: file:///lol.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: https://example.com/user-profile.schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
SELECT jsonschema_validates(:'user'::jsonb, :'user_schema_id', :'invalid_schema'::jsonb, :'user_schema'::jsonb );
ERROR: file:///lol.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: https://example.com/user-profile.schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
SELECT jsonschema_validates(:'user'::jsonb, :'user_schema_id', :'invalid_schema'::json, :'user_schema'::json );
ERROR: file:///lol.json is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
ERROR: https://example.com/user-profile.schema.json# is not valid against metaschema: jsonschema validation failed with https://json-schema.org/draft/2020-12/schema#
- at '/type': anyOf failed
- at '/type': value must be one of 'array', 'boolean', 'integer', 'null', 'number', 'object', 'string'
- at '/type': want array, but got string
Expand Down
2 changes: 1 addition & 1 deletion test/sql/validates.sql
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ SELECT jsonschema_validates(:'invalid_user'::jsonb, :'user_schema_id', :'addr_sc
SELECT jsonschema_validates(:'invalid_user'::jsonb, :'user_schema_id', :'addr_schema'::json, :'user_schema'::json );

-- Invalid schema
\set invalid_schema '{"type": "nonesuch", "$id": "file:///lol.json"}'
\set invalid_schema '{"type": "nonesuch"}'
SELECT jsonschema_validates(:'user'::json, :'user_schema_id', :'invalid_schema'::json, :'user_schema'::json );
SELECT jsonschema_validates(:'user'::json, :'user_schema_id', :'invalid_schema'::jsonb, :'user_schema'::jsonb );
SELECT jsonschema_validates(:'user'::jsonb, :'user_schema_id', :'invalid_schema'::jsonb, :'user_schema'::jsonb );
Expand Down

0 comments on commit b421e34

Please sign in to comment.