gavo.svcs.pql module

Code to support PQL syntax (as found in various DAL protocols).

PQL range-list syntax is

valSep ::= “,” rangeSep ::= “/” qualSep ::= “;” step ::= somethingMagicallyDefined range ::= [literal] rangeSep literal | literal rangeSep steppedRange ::= range [rangeSep step] qualification ::= qualSep somethingMagicallyDefined listItem ::= steppedRange | literal rangeList ::= listItem {valSep listItem} [qualification]

This defines a regular language, and we’re going to slaughter it using REs and ad hoccing.

Since the actually allowed grammar depends on the type of the parameter (e.g., steps make no sense for strings, and have a special grammar for dates), parsing is done by the specific PQLPar types (fromLiteral). See the PQLPar docstring for further info.

class gavo.svcs.pql.PQLCaselessPar(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL string parameter that’s compared with case folding.

Don’t count on case folding to work outside of ASCII.

covers(value)[source]

returns true if value is within the ranges specified by the PQL expression.

value must be type-true, i.e., you are responsible for converting it into the type the range are in.

getSQL(colName, sqlPars, cmpExpr=None)[source]

Overridden to change cmpExpr.

static valParser(val)

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.

class gavo.svcs.pql.PQLDatePar(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL parameter containing a date.

steps in ranges are allowed.

There’s an additional complication here: in the database, dates can be represented in various forms. To save the day, getSQL takes an additional optional parameter and transforms the input values as appropriate before passing them to the database.

getSQL(colName, sqlPars, convert=None)[source]

returns an SQL condition expressing the PQL constraint for colName.

In addition to the usual parameters, we here accept an additional argument convert with possible values None (meaning timestamp, which is the default) mjd, jd, and jy, which represents how the datetimes are represented in the database.

nullvalue = ''
static stepParser(val)[source]
static valParser(literal: Optional[Union[str, datetime]]) Optional[datetime]

returns a datetime from string or passes through datetimes and Nones.

The function will try to parse a string in various ways; we will try not to drop formats from one minor version to the next.

class gavo.svcs.pql.PQLFloatPar(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL float parameter.

This has a special getSQLForInterval method for cases like SSA’s BAND.

getSQLForInterval(lowerColName, upperColName, sqlPars)[source]

returns an SQL phrase against an interval in a table.

nullvalue = ''
valParser

alias of float

class gavo.svcs.pql.PQLIntPar(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL parameter containing an integer.

steps in ranges are allowed.

nullvalue = ''
stepParser

alias of int

valParser

alias of int

class gavo.svcs.pql.PQLNoRange(value)[source]

Bases: PQLRange

a stand-in for PQLRange when no ranges are to be supported

It seems this is intended for string-typed values. We try to be compatible with PQLRange in the relevant API aspects.

classmethod fromLiteral(literal, destName, valParser, stepParser)[source]

creates a PQLRange from a PQL range literal.

For the meaning of the arguments, see PQLPar.fromLiteral.

class gavo.svcs.pql.PQLNocaseShellPatternPar(ranges, qualifier=None, destName=None)[source]

Bases: PQLShellPatternPar

a shell-pattern matching parameter, ignoring case.

class gavo.svcs.pql.PQLPar(ranges, qualifier=None, destName=None)[source]

Bases: object

a representation for PQL expressions.

PQLPar objects have an attribute qualifier (None or a string), and an attribute ranges, a list of PQLRange objects.

As a client, you will usually construct PQLPar objects using the fromLiteral class method; it takes a PQL literal and a name to be used for LiteralParseErrors it may raise.

The plain PQLPar parses string ranges and does not allow steps.

Inheriting classes must override the valParser and stepParser attributes. Both take a string and have to return a typed value or raise a ValueError if the string does not contain a proper literal. The default for valParser is str, the default for stepParser a function that always raises a ValueError.

PQLPars usually support a covers(value) method that you can pass a value having the required type; it will return whether or not value would be picked up by the condition formulated in PQL. Some advanced PQLPars do not support this method and will raise a ValueError if called.

Since “PQL” is totally crazy, not even the range parser is constant. It seems string ranges were never meant to be supported, and therefore we support RangeClass. PQLRange allows the “/” syntax and is supposed to work for most things but strings. PQLNoRange is just always a simple value.

Note: valParser and stepParser must not be methods of the class but plain functions; since they are function-like class attributes, you will usually have to wrap them in staticmethods

covers(value)[source]

returns true if value is within the ranges specified by the PQL expression.

value must be type-true, i.e., you are responsible for converting it into the type the range are in.

classmethod fromLiteral(val, destName)[source]

returns a parsed representation of a literal in PQL range-list syntax.

val is a string containing the PQL expression, destName is a name to be used for the LiteralParseErrors the function raises when there are syntax errors in val.

getSQL(colName, sqlPars, cmpExpr=None)[source]

returns an SQL condition expressing this PQL constraint for colName.

The parameters necessary are added to sqlPars.

cmpExpr can be used to override the cmpExpr argument to PQLRange.getSQL; this is not really intended for user code, though, but rather for subclasses of PQLPar

getValuesAsSet()[source]

returns a set of all values mentioned within the PQL expression.

This raises a ValueError if this is not possible (e.g., due to non-stepped intervals).

nullvalue = None
rangeClass

alias of PQLRange

static stepParser(val)
valParser

alias of str

class gavo.svcs.pql.PQLPositionPar(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL position parameter, as for SSA.

Cones and intervals or real lists do not mix; we support STC-S identifiers as qualifiers.

The literals here are basically two-float lists.

covers(value)[source]

returns true if value is within the ranges specified by the PQL expression.

value must be type-true, i.e., you are responsible for converting it into the type the range are in.

classmethod fromLiteral(val, destName)[source]

returns a parsed representation of a literal in PQL range-list syntax.

val is a string containing the PQL expression, destName is a name to be used for the LiteralParseErrors the function raises when there are syntax errors in val.

getConeSQL(colName, sqlPars, coneSize)[source]

returns SQL to compute the constraint against a pgsphere point column.

getQ3CSQL(raCol, decCol, sqlPars, coneSize)[source]

returns SQL to compute the constraint against a pgsphere point column.

getSQL(colName, sqlPars)[source]

returns an SQL condition expressing this PQL constraint for colName.

The parameters necessary are added to sqlPars.

cmpExpr can be used to override the cmpExpr argument to PQLRange.getSQL; this is not really intended for user code, though, but rather for subclasses of PQLPar

nullvalue = ''
valParser

alias of float

class gavo.svcs.pql.PQLRange(value=None, start=None, stop=None, step=None)[source]

Bases: object

a representation of a PQL range.

PQLRanges have a value attribute that is non-None when there is only a single value.

For ranges, there is start, stop and step, all of which may be None.

The attributes contain whatever the parent’s valParser (or stepParser) functions return.

covers(value)[source]

returns True if value is covered by this interval.

value must be type-true, i.e. in whatever type value, start, and stop have.

classmethod fromLiteral(literal, destName, valParser, stepParser)[source]

creates a PQLRange from a PQL range literal.

For the meaning of the arguments, see PQLPar.fromLiteral.

getSQL(colName, sqlPars, cmpExpr=None)[source]

returns an SQL boolean expression for representing this constraint.

cmpExpr, if given, will be an expression that is compared against. It defaults to colName, but this is, of course, intended to allow stuff like LOWER(colName).

getSQLForInterval(lowerColName, upperColName, sqlPars)[source]

returns an SQL boolean expression for representing this constraint against an upper, lower interval in the DB table.

This will silently discard any step specification.

getValuesAsSet()[source]

returns a set containing all values matching the PQL condition if they form a discrete set or raises a ValueError if not.

class gavo.svcs.pql.PQLShellPatternPar(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL shell pattern parameter.

These are posix shell patterns, where no PQL metacharacters are evaluated at all.

covers(value)[source]

returns true if value is within the ranges specified by the PQL expression.

value must be type-true, i.e., you are responsible for converting it into the type the range are in.

classmethod fromLiteral(val, destName)[source]

returns a parsed representation of a literal in PQL range-list syntax.

val is a string containing the PQL expression, destName is a name to be used for the LiteralParseErrors the function raises when there are syntax errors in val.

getSQL(colName, sqlPars)[source]

returns an RE-based query equivalent to the input shell pattern.

class gavo.svcs.pql.PQLStringPar(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL normal string parameter.

“normal” means that range expressions are not supported.

rangeClass

alias of PQLNoRange

class gavo.svcs.pql.PQLTextParIR(ranges, qualifier=None, destName=None)[source]

Bases: PQLPar

a PQL string parameter matching “google-like”, “Information Retrieval”.

Basically, this matches the input and the database column as document vectors. Correspondingly, ranges are disallowed.

covers(value)[source]

returns true if value is within the ranges specified by the PQL expression.

value must be type-true, i.e., you are responsible for converting it into the type the range are in.

getSQL(colName, sqlPars)[source]

returns an SQL condition expressing this PQL constraint for colName.

The parameters necessary are added to sqlPars.

cmpExpr can be used to override the cmpExpr argument to PQLRange.getSQL; this is not really intended for user code, though, but rather for subclasses of PQLPar

nullvalue = ''
rangeClass

alias of PQLNoRange

class gavo.svcs.pql.ToPQLTypeConverter[source]

Bases: FromSQLConverter

mapComplex(sqlType, length)[source]
simpleMap = {'bigint': 'pql-int', 'char': 'pql-string', 'date': 'pql-date', 'double': 'pql-float', 'double precision': 'pql-float', 'float': 'pql-float', 'int': 'pql-int', 'integer': 'pql-int', 'pql-date': 'pql-date', 'pql-float': 'pql-float', 'pql-string': 'pql-string', 'real': 'pql-float', 'smallint': 'pql-int', 'text': 'pql-string', 'timestamp': 'pql-date'}
typeSystem = 'pqlexpr'
gavo.svcs.pql.adaptInputKey(inputKey)[source]

returns inputKey changed to generate SQL for PQL-like expressions.

This is used for buildFrom on CondDescs and renderers having parameterStyle pql.

gavo.svcs.pql.getREForShPat(shPat)[source]

returns a POSIX RE for a POSIX shell pattern.

>>> getREForShPat(r"ZU?\*[!A-Z]*")
'ZU.\\*[^A\\-Z].*'
>>> getREForShPat("no[*")
'no\\[.*'