AutoSql is a small specification language used throughout the UCSC Genome Browser to describe
the columns of a table or the fields of a annotation file. A single AutoSql file (conventionally
given the .as extension) defines the name, type, and a human-readable description of each
field.
Most Genome Browser users encounter AutoSql when adding extra fields to a
bigBed or bigGenePred
track. The bedToBigBed utility reads an .as file (via its -as= option) to learn the names
and types of any fields beyond the standard BED columns, and the Genome Browser uses those field
descriptions to label values on item detail pages and in filter menus.
Let's start with a basic BED format example. A 6-column BED record stores a position (chromosome, start, end), a name, a score, and a strand. Its AutoSql specification looks like this:
table bed6
"Browser Extensible Data, 6-column variant"
(
string chrom; "Reference sequence chromosome or scaffold"
uint chromStart; "Start position in chromosome"
uint chromEnd; "End position in chromosome"
string name; "Name of item"
uint score; "Score from 0-1000"
char[1] strand; "+ or - for strand"
)
The format is a hybrid between a C structure and a SQL table definition. Each declaration begins
with a type (table, object, or simple), an object name, and a quoted description, followed
by a parenthesized list of fields. Every field has a type, a name, and its own quoted comment.
From this specification, autoSql produces the SQL table definition:
#Browser Extensible Data, 6-column variant
CREATE TABLE bed6 (
chrom varchar(255) not null, # Reference sequence chromosome or scaffold
chromStart int unsigned not null, # Start position in chromosome
chromEnd int unsigned not null, # End position in chromosome
name varchar(255) not null, # Name of item
score int unsigned not null, # Score from 0-1000
strand char(1) not null, # + or - for strand
#Indices
PRIMARY KEY(chrom)
);
and the matching C structure:
struct bed6
/* Browser Extensible Data, 6-column variant */
{
struct bed6 *next; /* Next in singly linked list. */
char *chrom; /* Reference sequence chromosome or scaffold */
unsigned chromStart; /* Start position in chromosome */
unsigned chromEnd; /* End position in chromosome */
char *name; /* Name of item */
unsigned score; /* Score from 0-1000 */
char strand[2]; /* + or - for strand */
};
Along with the structure, autoSql generates functions to load a row from the database, save a
structure in tab- or comma-separated form, and free dynamically allocated structures (for
example, bed6Load, bed6TabOut, and bed6Free). This saves writing the many lines of
repetitive field-by-field conversion code that reading and writing such records would otherwise
require.
Every AutoSql object follows the same shape:
<declareType> <name> [index] [auto]
"<description>"
(
<fieldType> <fieldName>; "<field description>"
...
)
table, object, or simple. See Object types.The quoted comments are not optional decoration. They are required, and the Genome Browser surfaces the per-field comments to users, so write them as if an end user will read them.
AutoSql supports the following basic field types:
| Type | Description |
|---|---|
int |
32-bit signed integer |
uint |
32-bit unsigned integer |
short |
16-bit signed integer |
ushort |
16-bit unsigned integer |
byte |
8-bit signed integer |
ubyte |
8-bit unsigned integer |
bigint |
64-bit integer |
float |
single-precision IEEE floating point |
double |
double-precision IEEE floating point |
char |
8-bit character (can only be used in an array) |
string |
variable-length string, up to 255 bytes |
lstring |
"long string" — variable-length string up to 2 billion bytes |
enum |
enumerated type holding a single symbolic value |
set |
set type holding multiple symbolic values |
In addition, the simple, object, and table types may be used as fields, allowing one object
to contain another. See a more complex example below.
An array is declared by placing a size in square brackets between the field type and the field name. The size may be either a fixed number or the name of a previously declared field, which gives a variable-length array:
char[2] state; "Fixed-length array of 2 characters"
int pointCount; "Number of points"
uint[pointCount] points; "Variable-length array sized by pointCount"
When the size is a field name, that field must be declared before the array that uses it.
A char array is the standard way to store a short fixed-width string, such as the strand
character in a BED-like file (char[1] strand;).
The enum and set types map to SQL enum and set columns and provide compact symbolic values.
Each symbolic value must be a valid C identifier. For an enum, a field holds exactly one of the
listed values; for a set, a field may hold any combination, represented as a comma-separated
string when loaded from text.
table symbolCols
"example of enum and set symbolic columns"
(
int id; "unique id"
enum(male, female) sex; "enumerated column"
set(cProg,javaProg,pythonProg,awkProg) skills; "set column"
)
This is a common pattern for real Genome Browser data. For example, the bigDbSnp format uses an enum to record each variant's class:
enum(snv, mnv, ins, del, delins, identity) class; "Variation class/type"
autoSql generates a C enum for the symbolic values and stores a set as an unsigned bit field.
If you do not specify any index, autoSql assumes the first field is the primary key and indexes
it. To control indexing, add one of the following keywords after a field name:
primary — make the field the primary key.unique — index a field whose values are all unique.index — index a field that may contain duplicate values.
You can index just the first part of a long field by following the keyword with a character count
in brackets, for example index[12]. An integer field can be made auto-incrementing — letting
the database assign a new numeric value to each row — by adding the auto keyword after the index
keyword, if any.
table bedIndexed
"BED-like record with explicit indexes"
(
uint id primary auto; "Autoincrementing primary key for this record"
string name unique; "Name of item - must be unique"
string chrom index; "Reference sequence chromosome or scaffold"
uint chromStart index; "Start position in chromosome"
uint chromEnd; "End position in chromosome"
lstring description index[12]; "Item description - indexing just the first 12 characters"
)
AutoSql has three kinds of objects, which differ in what code is generated and in how arrays of them are stored in memory:
| Type | Generates SQL? | Array storage in memory |
|---|---|---|
simple |
No | C array |
object |
No | Singly linked list |
table |
Yes (SQL + C) | Singly linked list |
simple — objects that do not appear in lists. An array of a simple object is stored in
memory as a C array. (Historically simple objects could not contain strings or
variable-sized arrays; that restriction has been lifted.)object — like simple, but a next pointer is automatically inserted as the first field
of the generated C structure, and what looks like an array in the .as file becomes a singly
linked list in memory.table — like object, but autoSql also generates a SQL table definition. This is the
type used for anything stored in the database.
For example, given point[3] as a field, declaring point as simple stores the three points
as a C array, while declaring it as object stores them as a linked list.
Objects can contain other objects, which makes it possible to describe nested structures such as a gene locus built from transcripts, each of which is in turn built from exons:
simple exon
"A single exon"
(
int start; "Start position of exon in chromosome"
int end; "End position of exon in chromosome"
)
object transcript
"A transcript made up of one or more exons"
(
string name; "Transcript accession"
char[1] strand; "+ or - for strand"
int exonCount; "Number of exons in transcript"
simple exon[exonCount] exons; "Array of exons"
)
table gene
"A gene locus with one or more transcripts"
(
string chrom; "Reference sequence chromosome or scaffold"
int chromStart; "Start position of locus in chromosome"
int chromEnd; "End position of locus in chromosome"
string name; "Gene symbol or identifier"
int transcriptCount; "Number of transcripts"
object transcript[transcriptCount] transcripts; "List of transcripts"
)
Here gene is a table, so it gets both SQL and C output, while transcript and exon are
component objects referenced by its fields. Because exon is declared simple, the exons
array is stored in memory as a C array within each transcript; because transcript is declared
object, the transcripts of a gene form a singly linked list.
For a real Genome Browser format that uses this kind of nesting, see
txGraph.as, which
nests simple and object types to describe a transcription graph.
.as file to define extra fields..as
definition passed to bedToBigBed.autoSql.doc:
the original AutoSql documentation, including the full grammar.