{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://runninglake.com/schema/v1alpha1/view.json",
  "title": "View",
  "description": "A View as RunningLake's configuration repository declares it, at views/<name>.yaml. Generated from the Go types the control plane decodes this file into, so it checks the shape the gate reads — field names and types, and which fields may exist. The gate also applies rules no schema can express — required fields inside spec among them — so a file this schema accepts can still be refused by `rl diff`. Take #/properties/spec for the spec alone.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "apiVersion",
    "kind",
    "metadata"
  ],
  "properties": {
    "apiVersion": {
      "type": "string",
      "const": "runninglake.io/v1alpha1",
      "description": "The config schema's version, which is independent of the HTTP API's (rule unsupported-api-version)."
    },
    "kind": {
      "type": "string",
      "const": "View",
      "description": "The kind this file declares. A kind that disagrees with the file's path is refused (rule kind-mismatch)."
    },
    "metadata": {
      "required": [
        "name"
      ],
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "name": {
          "type": "string",
          "pattern": "^[a-z0-9_-]{1,63}$",
          "description": "The resource's name, which is also its path segment. It must be the name this file's path gives it (rule name-mismatch)."
        },
        "labels": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        },
        "annotations": {
          "type": "object",
          "additionalProperties": {
            "type": "string"
          }
        }
      }
    },
    "spec": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": false,
      "properties": {
        "layer": {
          "description": "Layer and Schema name where the view lives; Name is the view's own segment. The file is views/<layer>-<schema>-<name>.yaml and its truth is these three, for the reason a Volume's is: a resource name is unique per kind, so two schemas may each hold a view called daily_revenue.",
          "type": [
            "string",
            "null"
          ]
        },
        "schema": {
          "type": [
            "string",
            "null"
          ]
        },
        "name": {
          "type": [
            "string",
            "null"
          ]
        },
        "sql": {
          "description": "SQL is the one declared statement, in the restricted authoring dialect. It is stored as the author wrote it: the control plane transpiles per engine when it writes representations, and a statement rewritten on the way in could not be shown back to the person who wrote it. Fifteen rules of the dialect are checked at `rl diff`: every ORDER BY item says NULLS FIRST or NULLS LAST (dialect-null-order), a SUM or AVG over a floating-point cast is a warning (dialect-float-aggregate), and so is every FLOOR or CEIL call (dialect-floor-ceil), every TRY_CAST to a type that is not text (dialect-try-cast) and every DATE_DIFF but the days between two dates (dialect-date-diff), every `/` and AVG that is not in DOUBLE (dialect-division), every TRIM that names no characters (dialect-trim), every SUBSTRING whose start or length can reach an edge (dialect-substring), every CONCAT, GREATEST and LEAST with an argument that can be NULL (dialect-null-argument), every cast of a DOUBLE to an integer or a DECIMAL that is not rounded first (dialect-double-cast), every DATE plus or minus an INTERVAL, or truncated, that is not cast back to a DATE (dialect-date-result), every EXTRACT(DOW FROM ...) that is not reduced with MOD(..., 7) (dialect-day-of-week), every TIMESTAMP literal past six fractional digits and every cast to TIMESTAMP that names no precision (dialect-timestamp-precision), every cast to text of a DOUBLE (dialect-double-as-text), and every SUM of a cast to an integer (dialect-sum-integer; the gates add the SUM of a declared integer column).",
          "type": [
            "string",
            "null"
          ]
        },
        "reads": {
          "description": "Reads is what the statement reads, declared by the author in the spelling a Grant's target uses: structured, never dotted. The republication rule judges the view against this list and against nothing else, because nothing here parses the statement (4.16.20); a read the author left out, or declared at the wrong depth, is caught only when the statement is parsed.",
          "type": [
            "array",
            "null"
          ],
          "items": {
            "type": [
              "object",
              "null"
            ],
            "additionalProperties": false,
            "properties": {
              "layer": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "schema": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "table": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        },
        "displayName": {
          "type": [
            "string",
            "null"
          ]
        },
        "description": {
          "type": [
            "string",
            "null"
          ]
        }
      }
    }
  }
}
