gsvalidator

module
v0.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 21, 2026 License: MIT

README

gsvalidator

Rule-driven validation for SQLite databases.

Rules are declared in JSON: the table and field to check, the validator to apply, and whether a failure is an error or a warning. gsvalidator runs the rules against a database and reports each failing record. It does not assume a particular schema: named relations let rules follow joins between tables, and a mapper interface connects rule table and field names to the physical schema.

Validators

Validator Checks that
presence, absence a field is set, or is empty
regex a value matches a pattern
length a string's length is within bounds
range a numeric or date value is within bounds
check_digit an identifier's check digit is valid (ORCID, ISSN, ISBN-10, ISBN-13, Luhn)
foreign_key_exists a foreign key resolves to an existing row through a declared relation
related_field_equals, related_field_not_equals, related_field_in_set a field on a record reached through a relation equals, differs from, or is one of a set of values
count_across the number of matching rows in another table is within bounds
ancestor_exists, ancestor_field_check, parent_rank_higher, no_self_cycle along a self-referencing parent chain: an ancestor matches, a field compares against an ancestor's, the parent ranks higher, or the chain has no cycle

Rule bundles

A bundle is a single JSON document holding a schema's relations and its rules. enforcement is hard or soft; severity is error, warn, info or debug.

{
  "name": "example",
  "version": "1.0.0",
  "relations": {
    "book:publisher": {
      "target_table": "publisher",
      "cardinality": "one",
      "join": [{ "from": "book.publisher_id", "to": "publisher.id" }]
    }
  },
  "rules": [
    {
      "rule_id": "book_title_presence",
      "table_name": "book",
      "field_name": "title",
      "validator_type": "presence",
      "enforcement": "hard",
      "severity": "error",
      "error_message": "Title is required",
      "is_active": true
    },
    {
      "rule_id": "book_year_format",
      "table_name": "book",
      "field_name": "published_year",
      "validator_type": "regex",
      "enforcement": "soft",
      "severity": "warn",
      "parameters": { "pattern": "^[0-9]{4}$" },
      "warning_message": "Year should have four digits",
      "is_active": true
    }
  ]
}

Usage

loader := repository.NewJSONBundleLoader("rules.json") // or NewBytesBundleLoader for //go:embed
pkg, err := loader.LoadPackage(ctx)
if err != nil {
	return err
}
resolver := joins.NewRelationResolver(pkg.Relations, mapper)

registry := validator.NewRegistry()
registry.Register(&validator.PresenceValidator{})
registry.Register(validator.NewRegexValidator())
registry.Register(validator.NewForeignKeyExistsValidator(resolver))

uc := usecase.NewValidateTableUseCase(db, loader, mapper, registry)
report, err := uc.Execute(ctx, "book")
if err != nil {
	return err
}
fmt.Println(report.HardErrors, report.SoftWarnings)

mapper is your implementation of usecase.SchemaMapper: it maps rule table and field names to the physical schema, names each table's primary key, and loads records. Register the validators your rules use; relation-aware validators take the resolver, and parent-chain validators take the mapper.

presenter.NewSQLiteFormatter writes a report's results to a validation_results table.

Install

go get github.com/sfborg/gsvalidator

Requires Go 1.25 or later.

License

MIT. See LICENSE.

Directories

Path Synopsis
adapter

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL