diff -r f4127c4d1018 -r 95a215337b53 libidav/davqlparser.h --- a/libidav/davqlparser.h Sat May 02 10:59:02 2015 +0200 +++ b/libidav/davqlparser.h Sat May 02 11:00:28 2015 +0200 @@ -46,7 +46,8 @@ * Enumeration of possible expression types. */ typedef enum { - DAVQL_LITERAL, DAVQL_IDENTIFIER, + DAVQL_UNDEFINED_TYP, + DAVQL_NUMBER, DAVQL_STRING, DAVQL_TIMESTAMP, DAVQL_IDENTIFIER, DAVQL_UNARY, DAVQL_BINARY, DAVQL_LOGICAL, DAVQL_FUNCCALL } davqlexprtype_t; @@ -54,12 +55,12 @@ * Enumeration of possible expression operators. */ typedef enum { - DAVQL_NOOP, + DAVQL_NOOP, DAVQL_CALL, DAVQL_ARGLIST, // internal representations DAVQL_ADD, DAVQL_SUB, DAVQL_MUL, DAVQL_DIV, - DAVQL_AND, DAVQL_OR, DAVQL_XOR, DAVQL_NEG, - DAVQL_NOT, DAVQL_LAND, DAVQL_LOR, DAVQL_LXOR, + DAVQL_AND, DAVQL_OR, DAVQL_XOR, DAVQL_NEG, // airthmetic + DAVQL_NOT, DAVQL_LAND, DAVQL_LOR, DAVQL_LXOR, // logical DAVQL_EQ, DAVQL_NEQ, DAVQL_LT, DAVQL_GT, DAVQL_LE, DAVQL_GE, - DAVQL_LIKE, DAVQL_UNLIKE + DAVQL_LIKE, DAVQL_UNLIKE // comparisons } davqloperator_t; /** @@ -82,7 +83,6 @@ davqlexprtype_t type; /** * Operator. - * */ davqloperator_t op; /** @@ -97,6 +97,42 @@ DavQLExpression *right; }; +/** + * A tuple representing an order criterion. + */ +typedef struct { + /** + * The column. + */ + DavQLExpression *column; + /** + * True, if the result shall be sorted descending, false otherwise. + * Default is false (ascending). + */ + _Bool descending; +} DavQLOrderCriterion; + +/** + * A tuple representing a field. + */ +typedef struct { + /** + * The field name. + * + */ + sstr_t name; + /** + * The field expression. + * + */ + DavQLExpression *expr; +} DavQLField; /** * Query statement object. @@ -110,13 +146,15 @@ * | FunctionCall | Identifier | Literal * | "(", Expression, ")"; * - * FunctionCall = Identifier, "(", Expression, ")"; + * FunctionCall = Identifier, "(", ArgumentList, ")"; + * ArgumentList = Expression, {",", Expression}; * Identifier = IdentifierChar - ?Digit?, {IdentifierChar} - * | "`", ?Character?, {?Character?}, "`"; - * IdentifierChar = ?Character - (" "|",")?; - * Literal = Number | String; + * | "`", ?Character? - "`", {?Character? - "`"}, "`"; + * IdentifierChar = ?Character? - (" "|","); + * Literal = Number | String | Timestamp; * Number = ?Digit?, {?Digit?} | "%d"; - * String = "'", {?Character - "'"? | "'''"} , "'"; + * String = "'", {?Character? - "'" | "'''"} , "'" | "%s"; + * Timestamp = "%t"; // TODO: maybe introduce a real literal * * LogicalExpression = LogicalExpression, LogicalOperator, LogicalExpression * | "not ", LogicalExpression @@ -129,16 +167,23 @@ * LogicalOperator = " and " | " or " | " xor "; * Comparison = | "=" | "<" | ">" | "<=" | ">=" | "!="; * - * FieldExpressions = "*", {",", Expression, " as ", String} + * FieldExpressions = "*", {",", Expression, " as ", Identifier} * | FieldExpression, {",", FieldExpression} * | "-"; * FieldExpression = Identifier - * | Expression, " as ", String; - * SetExpressions = SetExpression, {",", {SetExpressions}; + * | Expression, " as ", Identifier; + * SetExpressions = SetExpression, {",", SetExpressions}; * SetExpression = Identifier, "=", Expression; * + * Path = "%s" + * | "/", {?Character? - " "} + * | "'/", {?Character?}, "'"; + * * WithClause = "depth", "=", (Number | "infinity"); * + * OrderByClause = OrderByCriterion, {",", OrderByCriterion}; + * OrderByCriterion = (Identifier | Number), [" asc"|" desc"]; + * * * * Note: mandatory spaces are part of the grammar. But you may also insert an @@ -148,17 +193,18 @@ * GET: *
  * GetStatement = "get ", FieldExpressions,
- * " from ", Identifier,
+ * " from ", Path,
+ * [" with ", WithClause],
  * [" where ", LogicalExpression],
- * [" with ", WithClause];
+ * [" order by ", OrderByClause];
   * 
* * SET: *
  * "set ",SetExpressions,
- * " at ", Identifier,
- * (" where ", LogicalExpression) | " anywhere",
- * [" with ", WithClause];
+ * " at ", Path,
+ * [" with ", WithClause],
+ * (" where ", LogicalExpression) | " anywhere";
  * 
* */ @@ -180,15 +226,10 @@ */ char* errormessage; /** - * The list of field expressions. + * The list of DavQLFields. */ UcxList* fields; /** - * The list of DavQLExpressions for the new DAV property values. - * This is NULL for GET queries. - */ - UcxList* setvalues; - /** * A string that denotes the queried path. */ sstr_t path; @@ -198,8 +239,16 @@ */ DavQLExpression* where; /** + * The list of DavQLOrderCriterions. + * This is NULL for SET queries and may be NULL + * if the result doesn't need to be sorted. + */ + UcxList* orderby; + /** * The recursion depth for the statement. * Defaults to 1. + * Magic numbers are DAV_DEPTH_INFINITY for infinity and + * DAV_DEPTH_PLACEHOLDER for a placeholder. */ int depth; } DavQLStatement; @@ -207,6 +256,45 @@ /** Infinity recursion depth for a DavQLStatement. */ #define DAV_DEPTH_INFINITY -1 +/** Depth needs to be specified at runtime. */ +#define DAV_DEPTH_PLACEHOLDER -2 + +/** Invalid path. */ +#define DAVQL_ERROR_INVALID_PATH 1 + +/** Expected an identifier, but found something else. */ +#define DAVQL_ERROR_IDENTIFIER_EXPECTED 10 + +/** Expected an identifier or literal, but found something else. */ +#define DAVQL_ERROR_IDORLIT_EXPECTED 11 + +/** Expected an identifier or number, but found something else. */ +#define DAVQL_ERROR_IDORNUM_EXPECTED 12 + +/** Expected an identifier or string, but found something else. */ +#define DAVQL_ERROR_IDORSTR_EXPECTED 13 + +/** Expected an identifier or timestamp, but found something else. */ +#define DAVQL_ERROR_IDORTS_EXPECTED 14 + +/** The with-clause contains an unknown attribute. */ +#define DAVQL_ERROR_UNKNOWN_ATTRIBUTE 20 + +/** Depth must be greater than zero or infinity. */ +#define DAVQL_ERROR_INVALID_DEPTH 21 + +/** The with-clause contains an attribute more than once. */ +#define DAVQL_ERROR_DUPLICATED_ATTRIBUTE 29 + +/** The format specifier is missing. */ +#define DAVQL_ERROR_MISSING_FMTSPEC 30 + +/** The format specifier is unknown. */ +#define DAVQL_ERROR_UNKNOWN_FMTSPEC 31 + +/** The format specifier is invalid. */ +#define DAVQL_ERROR_INVALID_FMTSPEC 39 + /** A quote symbol (' or `) is missing. */ #define DAVQL_ERROR_MISSING_QUOTE 50