{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://open-db.org/schema/1.0.0.json",
  "title": "OpenDB Specification",
  "description": "JSON Schema for OpenDB database documentation specification v1.0.0",
  "type": "object",
  "required": ["opendb", "info"],
  "properties": {
    "opendb": {
      "type": "string",
      "pattern": "^\\d+\\.\\d+\\.\\d+$",
      "description": "The version of the OpenDB specification"
    },
    "info": {
      "$ref": "#/definitions/Info"
    },
    "tables": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/Table"
      }
    },
    "views": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/View"
      }
    },
    "functions": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/Function"
      }
    },
    "queries": {
      "type": "object",
      "description": "Named example queries, keyed by query name",
      "additionalProperties": {
        "$ref": "#/definitions/Query"
      }
    },
    "schemas": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/Schema"
      }
    }
  },
  "additionalProperties": {
    "type": "object",
    "description": "Extension fields must start with x-"
  },
  "patternProperties": {
    "^x-": {
      "description": "Custom extension fields"
    }
  },
  "definitions": {
    "Info": {
      "type": "object",
      "required": ["title", "type"],
      "properties": {
        "title": {
          "type": "string",
          "description": "The name of the database"
        },
        "type": {
          "type": "string",
          "enum": ["postgresql", "mysql", "mariadb", "sqlite", "mssql", "oracle", "other"],
          "description": "Database type"
        },
        "version": {
          "type": "string",
          "description": "Database schema version"
        },
        "description": {
          "type": "string",
          "description": "A description of the database"
        },
        "contact": {
          "$ref": "#/definitions/Contact"
        },
        "license": {
          "$ref": "#/definitions/License"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Tags for categorization"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Contact": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "Contact name"
        },
        "email": {
          "type": "string",
          "format": "email",
          "description": "Contact email"
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "Contact URL"
        },
        "slack": {
          "type": "string",
          "description": "Slack channel or contact"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "License": {
      "type": "object",
      "properties": {
        "name": {
          "type": "string",
          "description": "License name"
        },
        "url": {
          "type": "string",
          "format": "uri",
          "description": "License URL"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Table": {
      "type": "object",
      "required": ["columns"],
      "properties": {
        "description": {
          "type": "string"
        },
        "columns": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/Column"
          }
        },
        "primaryKey": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "indexes": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/Index"
          }
        },
        "foreignKeys": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/ForeignKey"
          }
        },
        "checks": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Check"
          }
        },
        "triggers": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Trigger"
          }
        },
        "partitioning": {
          "$ref": "#/definitions/Partitioning"
        },
        "deprecated": {
          "type": "boolean"
        },
        "examples": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Example"
          }
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Column": {
      "type": "object",
      "required": ["type"],
      "properties": {
        "type": {
          "type": "string",
          "description": "Data type of the column"
        },
        "nullable": {
          "type": "boolean",
          "default": true
        },
        "default": {
          "type": ["string", "number", "boolean", "null"]
        },
        "autoIncrement": {
          "type": "boolean"
        },
        "description": {
          "type": "string"
        },
        "enum": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "length": {
          "type": "integer",
          "minimum": 1
        },
        "precision": {
          "type": "integer",
          "minimum": 1
        },
        "scale": {
          "type": "integer",
          "minimum": 0
        },
        "deprecated": {
          "type": "boolean"
        },
        "pii": {
          "type": "boolean",
          "description": "Contains Personally Identifiable Information"
        },
        "encrypted": {
          "type": "boolean",
          "description": "Whether this column is encrypted"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Index": {
      "type": "object",
      "required": ["columns"],
      "properties": {
        "columns": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "unique": {
          "type": "boolean"
        },
        "type": {
          "type": "string",
          "enum": ["btree", "hash", "gin", "gist", "brin", "spgist"]
        },
        "description": {
          "type": "string"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "ForeignKey": {
      "type": "object",
      "required": ["columns", "referencedTable", "referencedColumns"],
      "properties": {
        "name": {
          "type": "string"
        },
        "columns": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "referencedTable": {
          "type": "string"
        },
        "referencedColumns": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "onDelete": {
          "type": "string",
          "enum": ["CASCADE", "SET NULL", "SET DEFAULT", "RESTRICT", "NO ACTION"]
        },
        "onUpdate": {
          "type": "string",
          "enum": ["CASCADE", "SET NULL", "SET DEFAULT", "RESTRICT", "NO ACTION"]
        },
        "description": {
          "type": "string"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Check": {
      "type": "object",
      "required": ["expression"],
      "properties": {
        "name": {
          "type": "string"
        },
        "expression": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Trigger": {
      "type": "object",
      "required": ["name", "event", "timing", "definition"],
      "properties": {
        "name": {
          "type": "string"
        },
        "event": {
          "type": "string",
          "enum": ["INSERT", "UPDATE", "DELETE"]
        },
        "timing": {
          "type": "string",
          "enum": ["BEFORE", "AFTER", "INSTEAD OF"]
        },
        "level": {
          "type": "string",
          "enum": ["ROW", "STATEMENT"]
        },
        "definition": {
          "type": "string"
        },
        "description": {
          "type": "string"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Partitioning": {
      "type": "object",
      "required": ["type", "columns"],
      "properties": {
        "type": {
          "type": "string",
          "enum": ["RANGE", "LIST", "HASH"]
        },
        "columns": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "description": {
          "type": "string"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "View": {
      "type": "object",
      "properties": {
        "description": {
          "type": "string"
        },
        "columns": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/Column"
          }
        },
        "definition": {
          "type": "string"
        },
        "materialized": {
          "type": "boolean"
        },
        "dependencies": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "deprecated": {
          "type": "boolean"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Function": {
      "type": "object",
      "properties": {
        "description": {
          "type": "string"
        },
        "parameters": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Parameter"
          }
        },
        "returns": {
          "type": "string"
        },
        "language": {
          "type": "string",
          "enum": ["sql", "plpgsql", "plpython", "plperl", "java", "c"]
        },
        "definition": {
          "type": "string"
        },
        "deterministic": {
          "type": "boolean"
        },
        "deprecated": {
          "type": "boolean"
        },
        "examples": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Example"
          }
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Query": {
      "type": "object",
      "required": ["sql"],
      "description": "A worked example of how to read the database. Documentation, not a stored procedure -- a query lives here because someone had to work out how to join these tables, and the next person should not have to.",
      "properties": {
        "summary": {
          "type": "string",
          "description": "One line saying what question the query answers"
        },
        "description": {
          "type": "string",
          "description": "CommonMark. Why you would run this, and what to watch out for"
        },
        "sql": {
          "type": "string",
          "description": "The statement. Parameters are written as :name placeholders"
        },
        "tables": {
          "type": "array",
          "items": {
            "type": "string"
          },
          "description": "Tables and views the query reads. Stated rather than parsed out of the SQL, and it is what lets a table's documentation list the queries that touch it"
        },
        "parameters": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Parameter"
          }
        },
        "returns": {
          "type": "object",
          "additionalProperties": {
            "$ref": "#/definitions/Column"
          },
          "description": "The result columns, keyed by name"
        },
        "examples": {
          "type": "array",
          "items": {
            "$ref": "#/definitions/Example"
          },
          "description": "Example runs: `input` holds parameter values, `output` the rows they return"
        },
        "tags": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "deprecated": {
          "type": "boolean"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Parameter": {
      "type": "object",
      "required": ["name", "type"],
      "properties": {
        "name": {
          "type": "string"
        },
        "type": {
          "type": "string"
        },
        "default": {
          "type": ["string", "number", "boolean", "null"]
        },
        "description": {
          "type": "string"
        },
        "mode": {
          "type": "string",
          "enum": ["IN", "OUT", "INOUT", "VARIADIC"],
          "description": "Parameter direction. Defaults to IN when omitted."
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Schema": {
      "type": "object",
      "properties": {
        "description": {
          "type": "string"
        },
        "tables": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "views": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "functions": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "queries": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    },
    "Example": {
      "type": "object",
      "properties": {
        "description": {
          "type": "string"
        },
        "data": {
          "type": "object",
          "description": "Example data for tables/views"
        },
        "input": {
          "type": "object",
          "description": "Example input for functions"
        },
        "output": {
          "description": "Example output for functions"
        }
      },
      "patternProperties": {
        "^x-": {}
      }
    }
  }
}
