gavo.adql.nodes module

Node classes and factories used in ADQL tree processing.

class gavo.adql.nodes.ADQLNode[source]

Bases: AutoNode

A node within an ADQL parse tree.

ADQL nodes may be parsed out; in that case, they have individual attributes and are craftily flattened in special methods. We do this for nodes that are morphed.

Other nodes basically just have a children attribute, and their flattening is just a concatenation for their flattened children. This is convenient as long as they are not morphed.

To derive actual classes, define

  • the _a_<name> class attributes you need,

  • the type (a nonterminal from the ADQL grammar)

  • bindings if the class handles more than one symbol (in which case type is ignored)

  • a class method _getInitKWs(cls, parseResult); see below.

  • a method flatten() -> string if you define a parsed ADQLNode.

  • a method _polish() that is called just before the constructor is

    done and can be used to create more attributes. There is no need to call _polish of superclasses.

The _getInitKWs methods must return a dictionary mapping constructor argument names to values. You do not need to manually call superclass _getInitKWs, since the fromParseResult classmethod figures out all _getInitKWs in the inheritance tree itself. It calls all of them in the normal MRO and updates the argument dictionary in reverse order.

The fromParseResult class method additionally filters out all names starting with an underscore; this is to allow easy returning of locals().

asTree()[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

classmethod fromParseResult(parseResult)[source]
iterTree()[source]
type = None
class gavo.adql.nodes.Area(args=(), funName=None)[source]

Bases: FunctionNode

addFieldInfo(context)[source]
type = 'area'
class gavo.adql.nodes.ArrayMapFunction(args=(), funName=None)[source]

Bases: FunctionNode

The arr_map extension.

arg 1 is the expression; any x in it will be the filled with the array elements. arg 2 is the array to take the elements from.

addFieldInfo(context)[source]
type = 'arrayMapFunction'
class gavo.adql.nodes.ArrayReference(children=())[source]

Bases: FieldInfoedNode, TransparentMixin

addFieldInfo(context)[source]
collapsible = False
type = 'arrayReference'
class gavo.adql.nodes.BOMB_OUT[source]

Bases: object

class gavo.adql.nodes.Box(cooSys=None, height=None, origArgs=None, width=None, x=None, y=None)[source]

Bases: GeometryNode

sqlType = 'sbox'
stcArgs = ('x', 'y', 'width', 'height')
type = 'box'
xtype = 'polygon'
class gavo.adql.nodes.CaseExpression(children=())[source]

Bases: FieldInfoedNode, TransparentMixin

addFieldInfo(context)[source]
bindings = ['searchedCase', 'simpleCase']
type = 'searchedCase'
class gavo.adql.nodes.CastSpecification(children=(), newType=None, value=None)[source]

Bases: FieldInfoedNode, TransparentMixin

addFieldInfo(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

geometryConstructors = {'CIRCLE': 'Circle', 'POINT': 'Point', 'POLYGON': 'Polygon'}
type = 'castSpecification'
class gavo.adql.nodes.Centroid(args=(), funName=None)[source]

Bases: FunctionNode

addFieldInfo(context)[source]
type = 'centroid'
class gavo.adql.nodes.CharacterStringLiteral(value=None)[source]

Bases: FieldInfoedNode

according to the current grammar, these are always sequences of quoted strings.

addFieldInfo(context)[source]
bindings = ['characterStringLiteral', 'generalLiteral']
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'characterStringLiteral'
class gavo.adql.nodes.Circle(center=None, cooSys=None, origArgs=None, radius=None)[source]

Bases: GeometryNode

A circle parsed from ADQL.

There are two ways a circle is specified: either with (x, y, radius) or as (center, radius). In the second case, center is an spoint-valued column reference. Cases with a point-valued literal are turned into the first variant during parsing.

classmethod fromCastArgument(arg)[source]
sqlType = 'scircle'
stcArgs = ('center', 'radius')
type = 'circle'
xtype = 'circle'
class gavo.adql.nodes.CoalesceExpression(children=())[source]

Bases: FieldInfoedNode, TransparentMixin

addFieldInfo(context)[source]
type = 'coalesceExpression'
class gavo.adql.nodes.ColumnBearingNode[source]

Bases: ADQLNode

A Node types defining selectable columns.

These are tables, subqueries, etc. This class is the basis for the annotation of tables and subqueries.

Their getFieldInfo(name)->fi method gives annotation.FieldInfos objects for their columns, None for unknown columns.

These keep their fieldInfos on a change()

change(**kwargs)[source]

returns a shallow copy of self with constructor arguments in kwargs changed.

fieldInfos = None
getAllNames()[source]

yields all relation names mentioned in this node.

getFieldInfo(name)[source]
originalTable = None
class gavo.adql.nodes.ColumnReference(name=None, refName=None)[source]

Bases: _BaseColumnReference

class gavo.adql.nodes.ColumnReferenceByUCD(name=None, refName=None, ucdWanted=None)[source]

Bases: _BaseColumnReference

addFieldInfo(context)[source]
bindings = ['columnReferenceByUCD']
class gavo.adql.nodes.CombiningFINode[source]

Bases: FieldInfoedNode

addFieldInfo(context)[source]
class gavo.adql.nodes.Comparison(op1=None, op2=None, opr=None)[source]

Bases: ADQLNode

is required when we want to morph the braindead contains(…)=1 into a true boolean function call.

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'comparisonPredicate'
class gavo.adql.nodes.CoosysMixin[source]

Bases: object

is a mixin that works cooSys into FieldInfos for ADQL geometries.

class gavo.adql.nodes.DerivedColumn(alias=None, expr=None, tainted=True)[source]

Bases: FieldInfoedNode

A column within a select list.

addFieldInfo(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

property name
type = 'derivedColumn'
class gavo.adql.nodes.DerivedTable(query=None, tableName=None)[source]

Bases: ColumnBearingNode

property fieldInfos
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

getAllNames()[source]

yields all relation names mentioned in this node.

getAllTables()[source]
getFieldInfo(name)[source]
makeUpId()[source]
type = 'derivedTable'
class gavo.adql.nodes.Distance(args=(), funName=None)[source]

Bases: FunctionNode

addFieldInfo(context)[source]
optimize(stack)[source]
type = 'distanceFunction'
class gavo.adql.nodes.Factor(children=())[source]

Bases: FieldInfoedNode, TransparentMixin

a factor within an SQL expression.

factors may have only one (direct) child with a field info and copy this. They can have no child with a field info, in which case they’re simply numeric (about the weakest assumption: They’re doubles).

addFieldInfo(context)[source]
collapsible = True
type = 'factor'
class gavo.adql.nodes.FieldInfoedNode[source]

Bases: ADQLNode

An ADQL node that carries a FieldInfo.

This is true for basically everything in the tree below a derived column. This class is the basis for column annotation.

You’ll usually have to override addFieldInfo. The default implementation just looks in its immediate children for anything having a fieldInfo, and if there’s exactly one such child, it adopts that fieldInfo as its own, not changing anything.

FieldInfoedNode, when change()d, keep their field info. This is usually what you want when morphing, but sometimes you might need adjustments.

addFieldInfo(context)[source]
change(**kwargs)[source]

returns a shallow copy of self with constructor arguments in kwargs changed.

fieldInfo = None
class gavo.adql.nodes.FromClause(tableReference=(), tables=())[source]

Bases: ADQLNode

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

getAllFields()[source]

returns all fields from all tables in this FROM.

These will be qualified names. Columns taking part in joins are resolved here.

This will only work for annotated tables.

getAllNames()[source]

returns the names of all tables taking part in this from clause.

getAllTables()[source]
getFieldsForTable(srcTableName)[source]

returns the fields in srcTable.

srcTableName is a TableName.

resolveField(name)[source]
type = 'fromClause'
class gavo.adql.nodes.FunctionNode(args=(), funName=None)[source]

Bases: FieldInfoedNode

An ADQLNodes having a function name and arguments.

The rules having this as action must use the Arg “decorator” in grammar.py around their arguments and must have a string-valued result “fName”.

FunctionNodes have attributes args (unflattened arguments), and funName (a string containing the function name, all upper case).

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

class gavo.adql.nodes.GenericValueExpression(children=())[source]

Bases: CombiningFINode, TransparentMixin

A container for value expressions that we don’t want to look at closer.

It is returned by the makeValueExpression factory below to collect stray children.

collapsible = True
type = 'genericValueExpression'
class gavo.adql.nodes.GeometryCast(argument=None, cast_function=None, cooSys=None, origArgs=None)[source]

Bases: GeometryNode

A cast to a geometry type.

For these, we defer to functions built into the database.

addFieldInfo(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

resultingTypes = {'cast_to_circle': 'scircle', 'cast_to_point': 'spoint', 'cast_to_polygon': 'spoly'}
class gavo.adql.nodes.GeometryNode(cooSys=None, origArgs=None)[source]

Bases: CoosysMixin, FieldInfoedNode

Nodes for geometry constructors.

In ADQL 2.1, most of these became polymorphous. For instance, circles can be constructed with a point as the first (or second, if a coosys is present) argument; that point can also be a column reference.

Also, these will always get morphed in some way (as the database certainly doesn’t understand ADQL geometries). So, we’re trying to give the morphers a fair chance of not getting confused despite the wild variety of argument forms and types.

stcArgs is a list of symbolic names that might contain stc (or similar) information. Some of the actual attributes will be None.

Flatten is only there for debugging; it’ll return invalid SQL. OrigArgs is not for client consumption; clients must go through the symbolic names.

If you want your geometry to support casts, give it a fromCastArgs(args) method that will, in general, probably replace the node with a GeometryCast node. You’ll then have to teach GeometryCast how to annotate your geometry and add the type name to the geometryConstructors dictionary in CastSpecification.

addFieldInfo(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

class gavo.adql.nodes.GeometryValue(name=None, refName=None)[source]

Bases: _BaseColumnReference

bindings = ['geometryValue']
class gavo.adql.nodes.Grouping(children=())[source]

Bases: TransparentNode

type = 'groupByClause'
class gavo.adql.nodes.Having(children=())[source]

Bases: TransparentNode

type = 'havingClause'
class gavo.adql.nodes.InUnitFunction(expr=None, unit=None)[source]

Bases: FieldInfoedNode

addFieldInfo(context)[source]
change(**kwargs)[source]

returns a shallow copy of self with constructor arguments in kwargs changed.

conversionFactor = None
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'inUnitFunction'
class gavo.adql.nodes.JoinOperator(children=())[source]

Bases: ADQLNode, TransparentMixin

the complete join operator (including all LEFT, RIGHT, “,”, and whatever).

isCrossJoin()[source]
type = 'joinOperator'
class gavo.adql.nodes.JoinSpecification(children=(), predicate=None, usingColumns=())[source]

Bases: ADQLNode, TransparentMixin

A join specification (“ON” or “USING”).

type = 'joinSpecification'
class gavo.adql.nodes.JoinedTable(joinSpecification=None, leftOperand=None, operator=None, rightOperand=None)[source]

Bases: ColumnBearingNode

A joined table.

These aren’t made directly by the parser since parsing a join into a binary structure is very hard using pyparsing. Instead, there’s the helper function makeJoinedTableTree handling the joinedTable symbol that manually creates a binary tree.

addFieldInfos(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

getAllNames()[source]

iterates over all fully qualified table names mentioned in this (possibly joined) table reference.

getAllTables()[source]

returns all actual tables and subqueries (not sub-joins) within this join.

getJoinType()[source]

returns a keyword indicating how result rows are formed in this join.

This can be NATURAL (all common columns are folded into one), USING (check the joinSpecification what columns are folded), CROSS (no columns are folded).

getTableForName(name)[source]
makeUpId()[source]
originalTable = None
qName = None
tableName = <ADQL Node tableName>
type = None
class gavo.adql.nodes.MOC(cooSys=None, geometry=None, literal=None, order=None, origArgs=None)[source]

Bases: GeometryNode

a MOC in an ADQL syntax tree.

This can be constructed from an ASCII-MOC string or from an order and a geometry value expression.

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

sqlType = 'smoc'
stcArgs = ()
type = 'moc'
xtype = 'moc'
class gavo.adql.nodes.NumericValueExpression(children=())[source]

Bases: CombiningFINode, TransparentMixin

collapsible = True
type = 'numericValueExpression'
class gavo.adql.nodes.NumericValueFunction(args=(), funName=None)[source]

Bases: FunctionNode

A numeric function.

This is really a mixed bag. We work through handlers here. See table in class def. Unknown functions result in dimlesses.

addFieldInfo(context)[source]
collapsible = True
funcDefs = {'ABS': (None, None, 'keepMeta'), 'ACOS': ('rad', '', None), 'ASIN': ('rad', '', None), 'ATAN': ('rad', '', None), 'ATAN2': ('rad', '', None), 'CEILING': (None, None, 'keepMeta'), 'DEGREES': ('deg', None, 'keepMeta'), 'EXP': ('', '', None), 'FLOOR': (None, None, 'keepMeta'), 'LOG': ('', '', None), 'LOG10': ('', '', None), 'PI': ('', '', None), 'POWER': ('', '', None), 'RADIANS': ('rad', None, 'keepMeta'), 'RAND': ('', '', None), 'ROUND': (None, None, 'keepMeta'), 'SQRT': ('', '', None), 'SQUARE': ('', '', None), 'TRUNCATE': (None, None, 'keepMeta')}
type = 'numericValueFunction'
class gavo.adql.nodes.OffsetSpec(offset=None)[source]

Bases: ADQLNode

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'offsetSpec'
class gavo.adql.nodes.OrderBy(children=())[source]

Bases: TransparentNode

type = 'sortSpecification'
class gavo.adql.nodes.PlainTableRef(originalTable=None, sampling=None, tableName=None)[source]

Bases: ColumnBearingNode

A reference to a simple table.

The tableName is the name this table can be referenced as from within SQL, originalName is the name within the database; they are equal unless a correlationSpecification has been given.

addFieldInfos(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

getAllNames()[source]

yields all relation names mentioned in this node.

getAllTables()[source]
makeUpId()[source]
type = 'possiblyAliasedTable'
class gavo.adql.nodes.Point(cooSys=None, origArgs=None, x=None, y=None)[source]

Bases: GeometryNode

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

classmethod fromCastArgument(arg)[source]
sqlType = 'spoint'
stcArgs = ('x', 'y')
type = 'point'
xtype = 'point'
class gavo.adql.nodes.PointFunction(args=(), funName=None)[source]

Bases: FunctionNode

addFieldInfo(context)[source]
type = 'pointFunction'
class gavo.adql.nodes.Polygon(cooSys=None, coos=None, origArgs=None, points=None)[source]

Bases: GeometryNode

addFieldInfo(name)[source]
classmethod fromCastArgument(arg)[source]
sqlType = 'spoly'
stcArgs = ('coos', 'points')
type = 'polygon'
xtype = 'polygon'
class gavo.adql.nodes.PolygonCoos(args=None)[source]

Bases: FieldInfoedNode

a base class for the various argument forms of polygons.

We want to tell them apart to let the grammar tell the tree builder what it thinks the arguments were. Polygon may have to reconsider this when it learns the types of its arguments, but we don’t want to discard the information coming from the grammar.

addFieldInfo(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

class gavo.adql.nodes.PolygonPointCooArgs(args=None)[source]

Bases: PolygonCoos

type = 'polygonPointCooArgs'
class gavo.adql.nodes.PolygonSplitCooArgs(args=None)[source]

Bases: PolygonCoos

type = 'polygonSplitCooArgs'
class gavo.adql.nodes.PredicateGeometryFunction(args=(), funName=None)[source]

Bases: FunctionNode

addFieldInfo(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

optimize(stack)[source]
type = 'predicateGeometryFunction'
class gavo.adql.nodes.QualifiedStar(sourceTable=None)[source]

Bases: ADQLNode

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'qualifiedStar'
class gavo.adql.nodes.QuerySpecification(children=())[source]

Bases: TransparentNode

The toplevel query objects including CTEs.

Apart from any CTEs, that’s just a SelectExpression (which is always the last child), and we hand through essentially all attribute access to it.

property setLimit
type = 'querySpecification'
exception gavo.adql.nodes.ReplaceNode(replacingNode)[source]

Bases: ExecutiveAction

can be raised by code in the constructor of an ADQLNode to replace itself.

It is constructed with the (single) ADQLNode that should stand in its stead.

This is intended as a special service for ufuncs that want to insert complex, annotatable expressions. We also use that in certain situations when casting.

class gavo.adql.nodes.STCSRegion(tapstcObj=None)[source]

Bases: FieldInfoedNode

addFieldInfo(context)[source]
bindings = []
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'stcsRegion'
xtype = 'adql:REGION'
class gavo.adql.nodes.ScalarArrayFunction(args=(), funName=None)[source]

Bases: FunctionNode

All of these are functions somehow aggregating array elements.

For those that we know we try to infer units and UCDs.

addFieldInfo(context)[source]
funcDefs = {'ARR_AVG': ('{u};stat.mean', None, 1), 'ARR_COUNT': ('meta.number;{u}', '', 1), 'ARR_DOT': (None, None, 2), 'ARR_MAX': ('stat.max;{u}', None, 1), 'ARR_MIN': ('stat.min;{u}', None, 1), 'ARR_STDDEV': ('stat.stdev;{u}', None, 1), 'ARR_SUM': ('{u};arith.sum', None, 1)}
type = 'scalarArrayFunction'
class gavo.adql.nodes.SelectExpression(children=(), offset=None, setLimit=None)[source]

Bases: SetOperationNode

A complete query excluding CTEs.

The main ugly thing here is the set limit; the querySpecification has max of the limits of the children, if existing, otherwise to None.

Other than that, we hand through attribute access to our first child.

If there is a set expression on the top level, this will have a complex structure; the first-child thing still ought to work since after annotation we’ll have errored out if set operator arguments aren’t reasonably congurent.

getSelectClauses()[source]
type = 'selectExpression'
class gavo.adql.nodes.SelectList(allFieldsQuery=False, selectFields=())[source]

Bases: ADQLNode

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'selectList'
class gavo.adql.nodes.SelectQuery(fromClause=None, groupby=None, having=None, orderBy=None, selectList=None, setLimit=None, setQuantifier=None, whereClause=None)[source]

Bases: ColumnBearingNode

addFieldInfos(context)[source]
flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

getAllNames()[source]

yields all relation names mentioned in this node.

getContributingNames()[source]

returns a set of table names mentioned below this node.

getSelectFields()[source]
resolveField(fieldName)[source]
suggestAName()[source]

returns a string that may or may not be a nice name for a table resulting from this query.

Whatever is being returned here, it’s a regular SQL identifier.

type = 'selectQuery'
class gavo.adql.nodes.SetExpression(children=())[source]

Bases: SetOperationNode

collapsible = True
property fromClause
getContributingNames()[source]
type = 'querySetExpression'
class gavo.adql.nodes.SetFunction(children=())[source]

Bases: TransparentMixin, FieldInfoedNode

An aggregate function.

These typically amend the ucd by a word from the stat family and copy over the unit. There are exceptions, however, see table in class def.

addFieldInfo(context)[source]
funcDefs = {'AVG': ('{u};stat.mean', None, 'double precision'), 'COUNT': ('meta.number;{u}', '', 'integer'), 'MAX': ('stat.max;{u}', None, None), 'MIN': ('stat.min;{u}', None, None), 'STDDEV': ('stat.stdev;{u}', None, 'double precision'), 'SUM': (None, None, None)}
type = 'setFunctionSpecification'
class gavo.adql.nodes.SetGeneratingFunction(args=None, children=(), functionName=None, name=None)[source]

Bases: ColumnBearingNode, TransparentMixin

a function that can stand instead of a table.

For starters, we only do generate_series here. Let’s see where this leads.

addFieldInfos(context)[source]
getAllNames()[source]

yields all relation names mentioned in this node.

getAllTables()[source]
getFieldInfo(name)[source]
makeUpId()[source]
type = 'setGeneratingFunction'
class gavo.adql.nodes.SetOperationNode(children=())[source]

Bases: ColumnBearingNode, TransparentMixin

A node containing a set expression.

This is UNION, INTERSECT, or EXCEPT. In all cases, we need to check all contributing sub-expressions have compatible degree. For now, in violation of SQL1992, we require identical names on all operands – sql92 in 7.10 says

[if column names are unequal], the <column name> of the i-th column of TR is implementation-dependent and different from the <column name> of any column, other than itself, of any table referenced by any <table reference> contained in the SQL-statement.

Yikes.

These collapse to keep things simple in the typical case.

addFieldInfos(context)[source]
getAllNames()[source]

yields all relation names mentioned in this node.

getSelectClauses()[source]
class gavo.adql.nodes.SetTerm(children=())[source]

Bases: SetOperationNode

collapsible = True
type = 'querySetTerm'
class gavo.adql.nodes.StringValueExpression(children=())[source]

Bases: FieldInfoedNode, TransparentMixin

addFieldInfo(context)[source]
collapsible = True
type = 'stringValueExpression'
class gavo.adql.nodes.StringValueFunction(args=(), funName=None)[source]

Bases: FunctionNode

addFieldInfo(context)[source]
type = 'stringValueFunction'
class gavo.adql.nodes.SubJoin(joinedTable=None)[source]

Bases: ADQLNode

A sub join (JoinedTable surrounded by parens).

The parse result is just the parens and a joinedTable; we need to camouflage as that joinedTable.

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

type = 'subJoin'
class gavo.adql.nodes.TableName(cat=None, name=None, schema=None)[source]

Bases: ADQLNode

flatten()[source]

returns a string representation of the text content of the tree.

This default implementation will only work if you returned all parsed elements as children. This, in turn, is something you only want to do if you are sure that the node is question will not be morphed.

Otherwise, override it to create an SQL fragment out of the parsed attributes.

getNormalized()[source]

returns self’s qualified name lowercased for regular identifiers, in original capitalisation otherwise.

lower()[source]

returns self’s qualified name in lower case.

type = 'tableName'
class gavo.adql.nodes.Term(children=())[source]

Bases: CombiningFINode, TransparentMixin

collapsible = True
type = 'term'
class gavo.adql.nodes.TimestampFunction(args=(), funName=None)[source]

Bases: FunctionNode

addFieldInfo(context)[source]
type = 'timestampFunction'
class gavo.adql.nodes.TransparentMixin[source]

Bases: object

a mixin just pulling through the children and serializing them.

class gavo.adql.nodes.TransparentNode(children=())[source]

Bases: ADQLNode, TransparentMixin

An abstract base for Nodes that don’t parse out anything.

type = None
class gavo.adql.nodes.WhereClause(children=())[source]

Bases: TransparentNode

type = 'whereClause'
class gavo.adql.nodes.WithQuery(children=())[source]

Bases: SetOperationNode

A query from a with clause.

This essentially does everything a table does.

addFieldInfos(context)[source]
type = 'withQuery'
gavo.adql.nodes.autocollapse(nodeBuilder, children)[source]

inhibts the construction via nodeBuilder if children consists of a single ADQLNode.

This function will automatically be inserted into the the constructor chain if the node defines an attribute collapsible=True.

gavo.adql.nodes.cleanNamespace(ns)[source]

removes all names starting with an underscore from the dict ns.

This is intended for _getInitKWs methods. ns is changed in place and returned for convenience

gavo.adql.nodes.collectUserData(infoChildren)[source]
gavo.adql.nodes.dispatchColumnReference(parseResult)[source]
gavo.adql.nodes.flatten(arg)[source]

returns the SQL serialized representation of arg.

gavo.adql.nodes.flattenKWs(obj, *fmtTuples)[source]

returns a string built from the obj according to format tuples.

A format tuple is consists of a literal string, and an attribute name. If the corresponding attribute is non-None, the plain string and the flattened attribute value are inserted into the result string, otherwise both are ignored.

Nonexisting attributes are taken to have None values.

To allow unconditional literals, the attribute name can be None. The corresponding literal is always inserted.

All contributions are separated by single blanks.

This is a helper method for flatten methods of parsed-out elements.

gavo.adql.nodes.getChildOfClass(nodeSeq, cls, default=<class 'gavo.adql.nodes.BOMB_OUT'>)[source]

returns the unique node of class in nodeSeq.

See getChildOfType.

gavo.adql.nodes.getChildOfType(nodeSeq, type, default=<class 'gavo.adql.nodes.BOMB_OUT'>)[source]

returns the unique node of type in nodeSeq.

If there is no such node in nodeSeq or more than one, a NoChild or MoreThanOneChild exception is raised, Instead of raising NoChild, default is returned if given.

gavo.adql.nodes.getChildrenOfClass(nodeSeq, cls)[source]
gavo.adql.nodes.getChildrenOfType(nodeSeq, type)[source]

returns a list of children of type typ in the sequence nodeSeq.

gavo.adql.nodes.getNodeClasses()[source]

returns a list of node classes (and standalone parse actions) available for tree building.

This is what needs to be passed to adql.getADQLGrammarCopy to get a proper parse tree out of the parser.

gavo.adql.nodes.getStringLiteral(node, description='Argument')[source]

ensures that node only contains a constant string literal and returns its value if so.

The function raises an adql.Error mentioning description otherwise.

gavo.adql.nodes.getTreeBuildingGrammar()[source]
gavo.adql.nodes.getType(arg)[source]

returns the type of an ADQL node or the value of str if arg is a string.

gavo.adql.nodes.iterFieldInfos(args)[source]

returns fieldInfo objects found within the children of the node list args.

gavo.adql.nodes.makeBinaryJoinTree(children)[source]

takes the parse result for a join and generates a binary tree of JoinedTable nodes from it.

It’s much easier to do this in a separate step than to force a non-left-recursive grammar to spit out the right parse tree in the first place.

gavo.adql.nodes.makeRegion(children)[source]
gavo.adql.nodes.makeSTCSRegion(spec)[source]
gavo.adql.nodes.makeValueExpression(children)[source]
gavo.adql.nodes.parseArgs(parseResult)[source]

returns a sequence of ADQL nodes suitable as function arguments from parseResult.

This is for cleaning up _parseResults[“args”], i.e. stuff from the Args symbol decorator in grammar.

gavo.adql.nodes.registerNode(node)[source]

registers a node class or a symbolAction from a module other than node.

This is a bit of magic – some module can call this to register a node class that is then bound to some parse action as if it were in nodes.

I’d expect this to be messy in the presence of chaotic imports (when classes are not necessarily singletons and a single module can be imported more than once. For now, I ignore this potential bomb.

gavo.adql.nodes.registerRegionMaker(fun)[source]

adds a region maker to the region resolution chain.

region makers are functions taking the argument to REGION and trying to do something with it. They should return either some kind of FieldInfoedNode that will then replace the REGION or None, in which case the next function will be tried.

As a convention, region specifiers here should always start with an identifier (like simbad, siapBbox, etc, basically [A-Za-z]+). The rest is up to the region maker, but whitespace should separate this rest from the identifier.

The entire region functionality will probably disappear with TAP 1.1. Don’t do anything with it any more. Use ufuncs instead.

gavo.adql.nodes.symbolAction(*symbols)[source]

is a decorator to mark functions as being a parseAction for symbol.

This is evaluated by getADQLGrammar below. Be careful not to alter global state in such a handler.