Skip to content

Commit

Permalink
Add module schema
Browse files Browse the repository at this point in the history
  • Loading branch information
theory committed Jul 19, 2024
1 parent 022cdc8 commit 760dfb0
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 5 deletions.
10 changes: 5 additions & 5 deletions schema/v2/extension.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
"description": "An Extension represents a `CREATE EXTENSION` extension provided by the distribution.",
"type": "object",
"properties": {
"sql": {
"$ref": "path.schema.json",
"description": "A path pointing to the SQL file used by `CREATE EXTENSION`."
},
"control": {
"$ref": "path.schema.json",
"description": "A path pointing to the [control file](https://www.postgresql.org/docs/current/extend-extensions.html) used by `CREATE EXTENSION`."
},
"sql": {
"$ref": "path.schema.json",
"description": "A path pointing to the SQL file used by `CREATE EXTENSION`."
},
"doc": {
"$ref": "path.schema.json",
"description": "A path pointing to the documentation file for the extension, which **SHOULD** be more than a README."
Expand All @@ -36,9 +36,9 @@
"additionalProperties": false,
"examples": [
{
"control": "pair.control",
"sql": "sql/pair.sql",
"doc": "doc/pair.md",
"control": "pair.control",
"abstract": "A key/value pair data type",
"tle": true
},
Expand Down
57 changes: 57 additions & 0 deletions schema/v2/module.schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://pgxn.org/meta/v2/module.schema.json",
"title": "Module",
"description": "An Extension represents a loadable module (a.k.a., shared library) that can be loaded into PostgreSQL.",
"type": "object",
"properties": {
"type": {
"enum": ["extension", "hook", "bgw"],
"description": "The type of the module, one of \"extension\" for a module supporting a `CREATE EXTENSION` extension, \"bgw\" for a background worker, or \"hook\" for a hook."
},
"lib": {
"$ref": "path.schema.json",
"description": "A path pointing to the pointing to the shared object file, without the suffix."
},
"doc": {
"$ref": "path.schema.json",
"description": "A path pointing to the documentation file for the module, which **SHOULD** be more than a README."
},
"abstract": {
"type": "string",
"description": "A short String value describing the module.",
"minLength": 1
},
"preload": {
"enum": ["server", "session"],
"description": "A string indicating that the module requires loading before it can be used. A value of `server` means that the module requires loading on server start, while `session` means it can be loaded in a session. Omit this field if the module does not require preloading."
}
},
"required": ["type", "lib"],
"patternProperties": {
"^[xX]_.": {
"description": "Custom key"
}
},
"additionalProperties": false,
"examples": [
{
"type": "extension",
"lib": "src/my_extension"
},
{
"type": "bgw",
"lib": "lib/my_bgw",
"doc": "doc/my_bgw.md",
"preload": "server",
"abstract": "My background worker"
},
{
"type": "hook",
"lib": "lib/my_hook",
"doc": "doc/my_hook.md",
"preload": "session",
"abstract": "My hook"
}
]
}
169 changes: 169 additions & 0 deletions tests/v2_schema_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,175 @@ fn test_v2_extension() -> Result<(), Box<dyn Error>> {
Ok(())
}

#[test]
fn test_v2_module() -> Result<(), Box<dyn Error>> {
// Load the schemas and compile the extension schema.
let mut compiler = new_compiler("schema/v2")?;
let mut schemas = Schemas::new();
let id = id_for(SCHEMA_VERSION, "module");
let idx = compiler.compile(&id, &mut schemas)?;

for valid_module in [
("hook", json!({"type": "hook", "lib": "src/hook"})),
("bgw", json!({"type": "bgw", "lib": "src/bgw"})),
("extension", json!({"type": "extension", "lib": "src/ext"})),
(
"with abstract",
json!({"type": "hook", "lib": "src/hook", "abstract": "This and that"}),
),
(
"server",
json!({"type": "hook", "lib": "src/hook", "preload": "server"}),
),
(
"session",
json!({"type": "hook", "lib": "src/hook", "preload": "session"}),
),
(
"all fields",
json!({"type": "hook", "lib": "src/hook", "doc": "bog.md", "abstract": "This and that", "preload": "session"}),
),
(
"x field",
json!({"type": "hook", "lib": "src/hook", "x_hi": true}),
),
(
"X field",
json!({"type": "hook", "lib": "src/hook", "X_bar": 42}),
),
] {
if let Err(e) = schemas.validate(&valid_module.1, idx) {
panic!("extension {} failed: {e}", valid_module.0);
}
}

for invalid_module in [
// Basics
("array", json!([])),
("string", json!("crank")),
("empty string", json!("")),
("true", json!(true)),
("false", json!(false)),
("null", json!(null)),
("empty object", json!({})),
(
"invalid field",
json!({"type": "bgw", "lib": "src/bgw", "foo": "hi"}),
),
(
"bare x_",
json!({ "type": "bgw", "lib": "src/bgw", "x_": "hi"}),
),
(
"bare X_",
json!({ "type": "bgw", "lib": "src/bgw", "X_": "hi"}),
),
// type
("no type", json!({"lib": "bgw"})),
("empty type", json!({"type": "", "lib": "bgw"})),
("invalid type", json!({"type": "burp", "lib": "bgw"})),
("null type", json!({"type": null, "lib": "bgw"})),
("empty type", json!({"type": "", "lib": "bgw"})),
("number type", json!({"type": 42, "lib": "bgw"})),
("bool type", json!({"type": true, "lib": "bgw"})),
("array type", json!({"type": [], "lib": "bgw"})),
("object type", json!({"type": {}, "lib": "bgw"})),
// lib
("no lib", json!({"type": "bgw"})),
("null lib", json!({"lib": null, "type": "bgw"})),
("empty lib", json!({"lib": "", "type": "bgw"})),
("number lib", json!({"lib": 42, "type": "bgw"})),
("bool lib", json!({"lib": true, "type": "bgw"})),
("array lib", json!({"lib": [], "type": "bgw"})),
("object lib", json!({"lib": {}, "type": "bgw"})),
// doc
(
"empty doc",
json!({"type": "bgw", "lib": "src/bgw", "doc": ""}),
),
(
"null doc",
json!({"type": "bgw", "lib": "src/bgw", "doc": null}),
),
(
"number doc",
json!({"type": "bgw", "lib": "src/bgw", "doc": 42}),
),
(
"bool doc",
json!({"type": "bgw", "lib": "src/bgw", "doc": true}),
),
(
"array doc",
json!({"type": "bgw", "lib": "src/bgw", "doc": ["hi"]}),
),
(
"object doc",
json!({"type": "bgw", "lib": "src/bgw", "doc": {}}),
),
// abstract
(
"empty abstract",
json!({"type": "bgw", "lib": "src/bgw", "abstract": ""}),
),
(
"null abstract",
json!({"type": "bgw", "lib": "src/bgw", "abstract": null}),
),
(
"number abstract",
json!({"type": "bgw", "lib": "src/bgw", "abstract": 42}),
),
(
"bool abstract",
json!({"type": "bgw", "lib": "src/bgw", "abstract": true}),
),
(
"array abstract",
json!({"type": "bgw", "lib": "src/bgw", "abstract": ["hi"]}),
),
(
"object abstract",
json!({"type": "bgw", "lib": "src/bgw", "abstract": {}}),
),
// preload
(
"empty preload",
json!({"type": "bgw", "lib": "src/bgw", "preload": ""}),
),
(
"invalid preload",
json!({"type": "bgw", "lib": "src/bgw", "preload": "startup"}),
),
(
"null preload",
json!({"type": "bgw", "lib": "src/bgw", "preload": null}),
),
(
"number preload",
json!({"type": "bgw", "lib": "src/bgw", "preload": 42}),
),
(
"bool preload",
json!({"type": "bgw", "lib": "src/bgw", "preload": true}),
),
(
"array preload",
json!({"type": "bgw", "lib": "src/bgw", "preload": ["hi"]}),
),
(
"object preload",
json!({"type": "bgw", "lib": "src/bgw", "preload": {}}),
),
] {
if schemas.validate(&invalid_module.1, idx).is_ok() {
panic!("{} unexpectedly passed!", invalid_module.0)
}
}

Ok(())
}

#[test]
fn test_v2_app() -> Result<(), Box<dyn Error>> {
// Load the schemas and compile the extension schema.
Expand Down

0 comments on commit 760dfb0

Please sign in to comment.