gavo.adql.fieldinfo module

Field Infos – annotations to ADQL parse nodes carrying values.

To do this, we have a set of naive heuristics how types, ucds, and units behave when such “fields” are combined. Since right now, we don’t parse out enough and, at least for ucds and units we don’t have enough data to begin with, much of this is conjecture.

class gavo.adql.fieldinfo.Coercions(typeTree)[source]

Bases: object

A tree of types that can be used to infer common types.

The tree is passed in as nested sequences.

>>> c = Coercions(_CoercNode('bar', (_CoercNode('foo'), _CoercNode('baz',
...   (_CoercNode('quux'),)))))
>>> c.getSubsuming([])
>>> c.getSubsuming(['foo'])
>>> c.getSubsuming(['foo', 'foo'])
>>> c.getSubsuming(['foo', 'quux'])
>>> c.getSubsuming(['foo', 'weird'])

returns the least general type being able to represent all types within typeSeq.

The method returns the root type for both an empty typeSeq or a typeSeq containing an unknown type. We don’t want to fail here, and the “all-encompassing” type should handle any crap.

class gavo.adql.fieldinfo.FieldInfo(type, unit, ucd, userData=(), tainted=False, stc=None, sqlName=None, ignoreTableStats=False)[source]

Bases: object

a container for meta information on columns.

It is constructed with a unit, a ucd and userData. UserData is a sequence of opaque objects. A FieldInfo combined from more than one FieldInfo will have all userDatas of the combined FieldInfos in its userData attribute.

There’s an attribute ignoreTableStats that should be set when table statistics on user data is likely to be off; as of this writing, this is only done for CTEs; if we ever do more sophisticated planning, I expect we’ll have to do that whenever there is a SELECT.

There’s also a properties dictionary you can use to set arbitrary keys in. These should in general not be combined but just discarded as a whole when a field info is touched.

  • xtype – where applicable, write an ADQL xtype.

  • src.expression – flattened ADQL this was made from

static combineSTC(fi1, fi2)[source]

tries to find a common STC system for fi1 and fi2.

Two STC systems are compatible if at least one is None or if they are equal.

If this method discovers incompatible systems, it will set the stc attribute to “BROKEN”.

static combineUserData(fi1, fi2)[source]
classmethod fromAddExpression(opr, fi1, fi2, forceType=None)[source]

returns a new FieldInfo built from the addition-like operator opr and the two field infos.

If both UCDs and units are the same, they are kept. Otherwise, they are cleared and the fieldInfo is tainted.

classmethod fromMulExpression(opr, fi1, fi2)[source]

returns a new FieldInfo built from the multiplication-like operator opr and the two field infos.

The unit is unit1 opr unit2 unless we have a dimless (empty unit), in which case we keep the unit but turn the tainted flag on, unless both are empty.

The ucd is always empty unless it’s a simple dimless multiplication, in which case the ucd of the non-dimless is kept (but the info is tainted).


returns an approximate sql type for a value composed of the types mentioned in the sequence sqlTypes.

Basically, we have the coercion sequence int -> float -> text, where earlier types get clobbered by later ones. And then there’s messy stuff like dates. We don’t want to fail here, so if all else fails, we just make it a text.

Since we don’t know what operation is being performed, this can never be accurate; the idea is to come up with something usable to generate VOTables from ADQL results.

We do arrays (and subsume them by subsuming all types and gluing a [] to the result; the char(x) and friends are all subsumed to text.

All input is supposed to be lower case.

>>> getSubsumingType(["smallint", "integer"])
>>> getSubsumingType(["real[]", "double precision[]"])
'double precision[]'
>>> getSubsumingType(["real [  ]", "integer[5]"])
>>> getSubsumingType(["double precision", "integer[5]"])
'double precision[]'