# CHART Table definition files for raw or derived tables or views

namespace xsi = "http://www.w3.org/2001/XMLSchema-instance"

start = table

table = element table  {
    # attribute xmlns:xsi { "http://www.w3.org/2001/XMLSchema-instance" } &
    attribute xsi:noNamespaceSchemaLocation { text } &
        # "http://chart/eps/schemas/table.xsd" |
        # "http://chart/s3/schemas/table.xsd" |
        # "http://chart/msg/schemas/table.xsd" } &
        # "http://chart/gsasr/schemas/table.xsd" } &

    ## table description string
	element description { text } &

    ## Link to wiki or other page describing this table.
    element url { text }? &

    ## nominal frequency for this table. Should be set to a reasonable value even for tables with
    ## irregular frequency
	element period { xsd:duration }? &  # frequency should be forced for ts tables

    ## true if this table does not have a regular frequency
    element regular { xsd:boolean }? &

	## Mark flat tables as spare, meaning they get an extra per-column CNT (count)
	## statistic
	element sparse { xsd:boolean }? &

	## true if this ts table has an associated calibration view
    element has-cal { xsd:boolean }? &

	## basic table usage
    element type { "raw" | "view" | "derived" | "storage" | "stats" }? &

    ## table should have day/night regions computed in extended statistics table
    ## could be merged with stats-storage?
    element day-night-stats { xsd:boolean }? &

    ## override the default datatype for `sensing_time` field
    element sensing-time-type { "datetime" | "datetime_ms" | "datetime_us" }? &

    ## allow to hide in plot tool tree view
    element visible { xsd:boolean }? &

    ## MSG specific
    element source { "DP" }? &

    ## for Views, list each <source-table> here
    ## Not to be used with sys, raw or derived tables
    element source-table { text }* &  # view only

    ## for time-series tables with >250 fields which must have seperate _MINS, _MAXS, _AVGS
    ## and _STDS tables for orbital stats.
    ## Not used in sys tables
    element stats-storage { 'none' | 'single' | 'split' }? &  # ts only

	## Allow tables to declare their stats are stored in a separate, explicitly defined
	## table instead of an automatically generated one
	element stats-table { text }? &

	## For 'tables' stored inside a JSONB column, specify a different table to hold
	## parameter name<->keymap lookups. Other table must have a fixed definition;
	## see chartjcs project or documentation for details.
	## Set as an attribute of the table not the individual column
	element keycodes { test }? &

	## Specify the underlying database table name to associate with this table
	element db-name { text }? &

	## configure hashed split parameters for JSONB stats table
	element split-params {
		# Number of hash bins
		element bins { xsd:unsignedInt } &
		# Database table name template (Python format(); use "i" as variable)
		element db-name-template { text }
	}? &

    ## all-points table type
    element storage { 'timeseries' | 'key-value' | 'jsonb' }? &

	## some types of storage (JSONB and custom) need a parameter to give the actual
	## table the data is stored in
	element storage-table { text }? &

	## column in storage table used to hold JSONB values
	element storage-column { text }? &

	## (unused) display name for storage
	element label { text }? &

	## For tables storing PUS statistics we record the column used for the
	## structures. This is set in the all-points table using the stats,
	## not in the stats table
	element stats-column { text }? &

    ## Index definitions are optional for timeseries tables and if given, replace the default
	## index. For system tables no indexes are created by default and all required indexes
	## must be given
    element index {
       element name { text }? &
       element type { "normal" | "unique" | "primary-key" }? &
       element field { text }+ &
       element compress { xsd:integer }? &
	   element sid-fields { empty }?
    }* &

    ## For raw tables we can specifcy the source SF00 file
    element source-sf00 {  # raw only
        ## SF00 assembly ID identifiing the data type of input file
        element assembly-id { xsd:unsignedInt } &

        ## name of SF00 file. Should match values in common/sf.py.
        element name { text } &

        ## field description
        element description { text }? &

        ## snack length in bytes, excluding header
        element length { xsd:unsignedInt }? &

        ## frequency of the input SF00 file
        element period { xsd:duration } &

        ## To ingest a snack using multiple repeated sections instead of just mapping a single
        ## snack to a single table row
        element repeat { xsd:unsignedInt }? &

        ## If `repeat` is used set the byte delta between repeats
        element stride { xsd:unsignedInt }? &

        ## allows snacks to be ingested conditionally
        element condition { test }? &

	    ## time-offset is applied to the GRH timestamp of each snack as it is ingested
        element time-offset { xsd:duration }?  # ts only
    }? &

    ## List of fields to be included in a unique index
    ## sys tables only.
    #element unique {
    #    element name { text }+
    #}? &
    group* &
    field* &

    ## for Views only, the SQL source
    element view-sql { text }?  # views only
}

## fields can be grouped, recursively
group = element group {
   element description { text }? &
   element name { text } &
   group* &
   field*
}

## fields can exist inside a table or a group
field = element field {
    ## field name
    element name { text } &

    ## for keyvalue stores only the key
    element key { xsd:integer }? &

   ## MSG uses these, currently for information only
   element category { text }? &

    ## field data type
    element datatype {
        "boolean" |
        "int" |
        "uint" |
        "float" |
        "double" |
        "hirs-signed" |  # special type of signed integer in HIRS raw data; see ICD
        "inverted-uint" |  # unsigned integer with inverted bits, used in SEM data
        "MIL1750a" |  # floating point encoding
        "string" |
        "unicode" |
        "xml" |
        "date" |
        "datetime" |
        "datetime_ms" |
        "jsonb" |
        "gen_datetime" |  # sys only
        "autoincrement "}? &  # sys only

	## Database engine compression method for column
	element compression { "default" | "none" | "lz4" }? &

	## if we need to use a non-standard method to read binary values into this field
	element decoder {
		"hirs-signed" |
		"inverted-uint" |
		"MIL1750a"
	}? &

	## define special display criteria
	element display { "pidref" }? &

    ## for int and string types, give the size in chars (string) or bits (int or uint)
    element length { xsd:unsignedInt { maxInclusive="10000" } }? &  # length also used by string

    ## field description
    element description { text }? &

    ## name of calibration function
    element calibration-name { text }? &

    ## do we allow NULL values?
    element allow-null { xsd:boolean }? &

    ## allow indexes to be declared for individual fields inline
    element index {
        "true" |
        "primary-key" }? &  # sys only

    ## field unit
    element unit { text }? &

    ## restrict the field values to a list of enumerated values
    element choices {
		element description { text }? &
        element item {
            ## value is required for raw tables only
            element value { xsd:integer }? &

            ## for names representing a range of values
            element min-value { xsd:integer }? &

            ## for names representing a range of values
            element max-value { xsd:integer }? &

            ## value name
            element name { text } &

            ## description of item
            element description { text }?
        }+
    }? &

    ## name of calibration function
    element calibration { text }? &
    element position { xsd:unsignedInt }? &  # raw only
    ## Apply a bitwise AND against eaw values
    element mask { text }? &  # raw only
    ## Apply a bit shift to raw values
    element shift { xsd:unsignedInt }? &  # raw only
    element validity-group { text }? &  # raw only
    element validity-group-prime { text }? &  # raw only
    ## Ingested data of this value will be recorded as database NULLs
    element invalid { text }? &
    element limits | raw-limits {
        element red {
            ## many limits values must be evaluated i.e. 10-25
            element low { text }? &  # xsd:float
            element high { text }?
        }? &
        element yellow {
            element low { text }? &
            element high { text }?
        }?
    }? &
    element hidden { xsd:boolean }? &
	element default { text }? &
	## For PUS ingestion of datetime objects we allow the number of bytes of coarse
	## time (seconds) to be specified. Remaining bytes are fine time (proportion of
	# second)
	element coarse-time-length { xsd:unsignedInt }? &
	## For PUS ingestion a parameter may be defined as deduced, meaning it is a debug
	## parameter based on the definition given by the value of a different parameter
	element related { text }?
}

## tests are applied against individual bytes
test = element test {
    ## byte offset to be tested
    element position { xsd:unsignedInt } &
    element shift { xsd:unsignedInt }? &
    element mask { text }? & (
## a clause can use either <equals> a specific value, or give a range from <min-value>
## to <max-value>. Unbounded ranges can be specified by omitting either min or max value
        element equals { xsd:unsignedInt } |
        (element min-value { xsd:unsignedInt }? &
            element max-value { xsd:unsignedInt }?
        ) )
}* &
    element and { test* }* &
    element or { test* }*

Download as raw Relax-NG Compact here or as raw XSD here