Releases: cinchapi/ccl
Version 3.1.2
- Fixed a regression that caused parenthetical expressions within a
Condition
containingLIKE
REGEX
,NOT_LIKE
andNOT_REGEX
operators (e.g.,a = b and (email regex email.com)
) to mistakenly throw aSyntaxException
when being parsed by aCompiler
.
Version 3.1.1
- Fixed a regression that caused Conditions with
LIKE
REGEX
,NOT_LIKE
andNOT_REGEX
operators followed by a whitespace containing value to be incorrectly parsed.
Version 3.1.0
- Added support for parsing standalone
function statements
in a compiler. Now, the following forms will parse into aFunctionTree
that contains a symbolic representation of the function expressed in the CCL statement: function(key)
produces a FunctionTree whose root node contains anIndexFunction
function(key, record)
produces a FunctionTree whose root node contains aKeyRecordsFunction
function(key, record1,record2,...,recordN)
produces a FunctionTree whose root node contains aKeyRecordsFunction
function(key, condition)
produces a FunctionTree whose root node contains aKeyConditionFunction
key \| function
produces a FunctionTree whose root node contains anImplicitKeyRecordFunction
- Fixed a bug where the paramaterized type of
KeyRecordsFunction
was aList<String>
instead of aList<Long>
. - Added support for including an optional timestamp within a function value statement.
Version 3.0.0
Function Statements
In version 3.0.0
we added support for function statements.
Background
Functions in Concourse
In Concourse, a function is an operation that is applied to a collection of values; values that can be retrived from a key stored in one or more records. Concourse functions be expressed in the following ways:
function(key)
- applied to every value stored for key in every recordfunction(key, records)
- applied to every value stored for key in each of therecords
function(key, ccl/criteria)
- applied to every value stored for key in each of the records that match theccl
orcriteria
.function(key, record)
- applied to every value stored for key in therecord
Expressions in CCL
In CCL, the notion of an expression
is core. A Condition
is really just one or more expressions that are logically joined together in a manner that expresses clear evaluation precedence.
An expression, generally takes the form:
<key> <operator> <values>
So, in the context of a database query like select(<key1>, "<key2> <operator> <value>")
, key2
and key1
are both keys, but they have different roles in the operation. In this scenario, key2
isn't returned to the caller, but is part of the evaluation expression. So, we call key2
an evaluation key. On the other hand, key1
doesn't play a role in evaluation, but is an artifact of the operation. So, we call this a operation key. As you can imahine, in more complex examples, a key can play both roles.
Similar to an evaluation key, a value that is part of an expression plays the role of evaluation value.
Functions in CCL
The roles evaluation key and evaluation value are important for understanding how functions work in CCL. Conceptually the value(s) of an expression's evaluation key
are retrieved and considered in relation to the expression's operator
and evaluation values
to determine if the record satisfies the expression. And since functions return a value, you can imagine using a function statement as either am evaluation key or an evaluation value.
In a programming language this would be easy, but in CCL it is possible with caveats due to language ambiguity. To understand these challenges, consider the question: who's average score is greater than the average of all scores?.
This question could be answered by issuing a database query of the form find("{evaluation key} > {evaluation value}")
. In this case, we know that the evaluation value should be average(score)
since we want to compare against the average of all scores. Now, our query looks like find("{evaluation key} > average(score)")
.
But confusion abounds when we consider how to express selecting the average score of each record that is being evaluated. Concourse functions support providing an explicit record or records, but, in CCL, we don't know which records are being evaluated. To get around this, we created implicit function syntax that uses the pipe character (e.g. |
) to indicate that an operation should only be applied to the key in the record that is currently being evaluated. So, our complete query would look like find("score | average > average(score)")
.
In an effort to avoid any ambiguity, we've adopted the following conventions:
- An implicit function statement can only be used as an evaluation key and never an evaluation value
- All other function statements can be used as an evaluation value but never as an evlauation key.
Operation Key | Evaluation Key | Evaluation Value | |
---|---|---|---|
function(key) |
NO | NO | YES |
function(key, records) |
NO | NO | YES |
function(key, record) |
NO | NO | YES |
function(key, ccl) |
NO | NO | YES |
key | function |
YES | YES | NO |
Expanded Grammar
- This grammar has been expanded and renamed from Concourse Criteria Language to Concourse Command Language. In addition to supporting the parsing of
Condition
statements, this grammar now supports parsing the following additional statements:- Page
- Order
Page Statements
A Page statement can be parsed from the following forms:
SIZE n
= the first page withn
itemsPAGE n
= then
th page with the default number of itemsPAGE m SIZE n
= them
th page withn
items
Order Statements
An Order statement can be parsed from the following forms:
ORDER BY {key}
= sort by a single keyORDER BY {key1}, {key2}, ... {keyn}
= sort by multiple keysORDER BY {key} {direction}
= sort by a single key withdirection
ORDER BY {key1} {direction}, {key2}, ... {key3} {direction}
= sort by multiple keys, each with an independent and optionaldirection
ORDER BY {key} at {timestamp}
= sort by a single key attimestamp
ORDER BY {key1} at {timestamp}, {key2}, ... {keyn} at {timestamp}
= sort by multiple keys, each with an independent and optionaltimestamp
ORDER BY {key} {direction} at {timestamp}
= sort by a single key attimestamp
with `directionORDER BY {key1} {direction} at {timestamp}, {key2}, ... {keyn} {direction} at {timestamp}
= sort by multiple keys, each with an independent and optionaltimestamp
anddirection
API Breaks
- The
Expression
symbol has been deprecated and renamedExpressionSymbol
for clarity. - The deprecated
ConcourseParser
has been removed. - Renamed the
com.cinchapi.ccl.v2.generated
package tocom.cinchapi.ccl.generated
. - The
Parser
construct has been deprecated in favor of aCompiler
. Compilers are superior to Parsers because they provide a superset of functonality and are stateless.
Bug Fixes
- Fixed a bug that caused erroneous parsing errors in a CCL statement containing the
REGEX
,NREGEX
,LIKE
, orNOT_LIKE
operators followed by a string value with a parenthesis (e.g. a regex grouping character).
Version 2.6.3
- Fixed a bug that caused non-numeric Tags to be erroneously parsed and transformed into symbols containing String values instead of Tag values
- Fixed a bug that caused Strings or String-like values that contained an
=
(equals sign) or whitespace character to not be properly quoted in aValueSymbol
.
Version 2.6.2
- Fixed a bug that cause the
v2
parser to fail when trying to parse a CCL statement that contained unquoted string values with periods.
Version 2.6.1
- Fixed a bug that caused a
ValueSymbol
containing aTimestamp
value to be written in a CCL format that could not be re-parsed by a CCL parser. This bug cased aSyntaxException
to thrown when attempting to tokenize a CCL statement generated by a Criteria that contained anyTimestamp
values.
Version 2.6.0
- Added support for navigation keys. A navigation key is used to traverse the document graph in Concourse. It is made up of multiple keys that are joined by the
.
character (i.e.friends.friends.name
).
Version 2.5.2
- Fixed a bug that caused the CCL parser to fail on certain Unicode quote characters.
Version 2.5.1
- Added context about the CCL statement being processed to the exceptions thrown from operations in the
v2
parser.