Skip to content

Commit 821f936

Browse files
committed
Update CHANGELOG and documentation
Also fixed a bug with tsql.query()
1 parent b6d2ac4 commit 821f936

File tree

5 files changed

+168
-11
lines changed

5 files changed

+168
-11
lines changed

CHANGELOG.md

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,33 @@ these changes are prefixed with "**BREAKING**"
4848
* `delphin.util.LookaheadIterator` for parsing with arbitrary lookahead
4949
* `delphin.commands` module to contain logic for `delphin` commands (#140)
5050
* `tests/commands_test.py` to test invocation of commands (but not results)
51+
* `delphin.tsql` module for TSQL queries of testsuites
52+
* `delphin.exceptions.TSQLSyntaxError`
53+
* `delphin.itsdb`
54+
- `Relations.find()` returns the names of tables defining a field
55+
- `Relations.path()` returns a path of `(table, shared_field)` tuples
56+
describing how to get from one table to another via shared keys
57+
- `TestSuite.write()` takes an optional `relations` parameter to write
58+
a profile with an updated relations file (#150)
59+
- `TestSuite.exists()` (#150)
60+
- `TestSuite.size()` (#150)
61+
- `Record.get()` takes a `cast` parameter; when `True`, values are cast
62+
to the field's datatype
63+
- `select_rows()` takes a `cast` parameter as with `Record.get()`
5164

5265
### Changed
5366

5467
* `delphin.tdl` now parses triple-quoted docstrings (#167); note that it
5568
no longer parses the old-style docstrings
5669
* `delphin.tdl.TdlDefinition` inherits from `delphin.tfs.FeatureStructure`
70+
* `delphin.itsdb.TestSuite` no longer casts values by default (see note on
71+
`Record.get()` above)
72+
* `delphin.itsdb.TestSuite.process()` can take a `Table` as the `source`
73+
instead of just `TestSuite`.
74+
* **BREAKING** The `delphin` commands have all replaced the previous
75+
method of filtering testsuites with the new TSQL queries. Applicators
76+
are no longer available to commands. Please see `delphin <cmd> -h` for
77+
updated usage notes. (#138, #179)
5778

5879
### Deprecated
5980

@@ -65,6 +86,9 @@ these changes are prefixed with "**BREAKING**"
6586

6687
* **BREAKING** `delphin.tdl.TdlDefinition.comment`; replaced by
6788
`TdlType.docstring`
89+
* **BREAKING** `--filter` option on all commands
90+
* **BREAKING** `--apply` option on all commands
91+
* **BREAKING** `--join` option on the `select` command
6892

6993

7094
## [v0.8.0][]

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ The following packages/modules are available:
7070

7171
- `derivation`: [Derivation trees](http://moin.delph-in.net/ItsdbDerivations)
7272
- `itsdb`: [incr tsdb()] profiles
73+
- `tsql`: TSQL testsuite queries
7374
- `mrs`: [Minimal Recursion Semantics](http://moin.delph-in.net/MrsRfc)
7475
- `tdl`: [Type-Description Language](http://moin.delph-in.net/TdlRfc)
7576
- `tfs`: Typed-Feature Structures

delphin/tsql.py

Lines changed: 126 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,90 @@
33
TSQL -- Test Suite Query Language
44
55
This module implements a subset of TSQL, namely the 'select' (or
6-
'retrieve') queries for extracting data from test suites.
7-
8-
PyDelphin differences to standard TSQL:
9-
10-
* `select *` requires a `from` statement
11-
* `select * from item result` does not also include `parse` columns
6+
'retrieve') queries for extracting data from test suites. The general
7+
form of a select query is::
8+
9+
[select] <projection> [from <tables>] [where <condition>]*
10+
11+
For example, the following selects item identifiers that took more
12+
than half a second to parse::
13+
14+
select i-id from item where total > 500
15+
16+
The `select` string is necessary when querying with the generic
17+
:func:`query` function, but is implied and thus disallowed when using
18+
the :func:`select` function.
19+
20+
The `<projection>` is a list of space-separated field names (e.g.,
21+
`i-id i-input mrs`), or the special string `*` which selects all
22+
columns from the joined tables.
23+
24+
The optional `from` clause provides a list of table names (e.g.,
25+
`item parse result`) that are joined on shared keys. The `from`
26+
clause is required when `*` is used for the projection, but it can
27+
also be used to select columns from non-standard tables (e.g., `i-id
28+
from output`). Alternatively, `delphin.itsdb`-style data specifiers
29+
(see :func:`delphin.itsdb.get_data_specifier`) may be used to specify
30+
the table on the column name (e.g., `item:i-id`).
31+
32+
The `where` clause provide conditions for filtering the list of
33+
results. Conditions are binary operations that take a column or data
34+
specifier on the left side and an integer (e.g., `10`), a date (e.g.,
35+
`2018-10-07`), or a string (e.g., `"sleep"`) on the right side of the
36+
operator. The allowed conditions are:
37+
38+
================ ======================================
39+
Condition Form
40+
================ ======================================
41+
Regex match ``<field> ~ "regex"``
42+
Regex fail ``<field> !~ "regex"``
43+
Equality ``<field> = (integer|date|"string")``
44+
Inequality ``<field> != (integer|date|"string")``
45+
Less-than ``<field> < (integer|date)``
46+
Less-or-equal ``<field> <= (integer|date)``
47+
Greater-than ``<field> > (integer|date)``
48+
Greater-or-equal ``<field> >= (integer|date)``
49+
================ ======================================
50+
51+
Boolean operators can be used to join multiple conditions or for
52+
negation:
53+
54+
=========== =====================================
55+
Operation Form
56+
=========== =====================================
57+
Disjunction ``X | Y``, ``X || Y``, or ``X or Y``
58+
Conjunction ``X & Y``, ``X && Y``, or ``X and Y``
59+
Negation ``!X`` or ``not X``
60+
=========== =====================================
61+
62+
Normally, disjunction scopes over conjunction, but parentheses may be
63+
used to group clauses, so the following are equivalent::
64+
65+
... where i-id = 10 or i-id = 20 and i-input ~ "[Dd]og"
66+
... where i-id = 10 or (i-id = 20 and i-input ~ "[Dd]og")
67+
68+
Multiple `where` clauses may also be used as a conjunction that scopes
69+
over disjunction, so the following are equivalent::
70+
71+
... where (i-id = 10 or i-id = 20) and i-input ~ "[Dd]og"
72+
... where i-id = 10 or i-id = 20 where i-input ~ "[Dd]og"
73+
74+
This facilitates query construction, where a user may want to apply
75+
additional global constraints by appending new conditions to the query
76+
string.
77+
78+
PyDelphin has several differences to standard TSQL:
79+
80+
* `select *` requires a `from` clause
81+
* `select * from item result` does not also include columns from the
82+
intervening `parse` table
1283
* `select i-input from result` returns a matching `i-input` for every
1384
row in `result`, rather than only the unique rows
1485
15-
PyDelphin additions to standard TSQL:
86+
PyDelphin also adds some features to standard TSQL:
1687
1788
* optional table specifications on columns (e.g., `item:i-id`)
18-
* multiple `where` clauses (e.g., `where X where Y` is the same as
19-
`where (X) and (Y)`); this helps when appending to queries
89+
* multiple `where` clauses (as described above)
2090
"""
2191

2292
import operator
@@ -31,11 +101,38 @@
31101
### QUERY INSPECTION ##########################################################
32102

33103
def inspect_query(query):
104+
"""
105+
Parse *query* and return the interpreted query object.
106+
107+
Example:
108+
>>> from delphin import tsql
109+
>>> from pprint import pprint
110+
>>> pprint(tsql.inspect_query(
111+
... 'select i-input from item where i-id < 100'))
112+
{'querytype': 'select',
113+
'projection': ['i-input'],
114+
'tables': ['item'],
115+
'where': ('<', ('i-id', 100))}
116+
"""
34117
return _parse_query(query)
35118

36119
### QUERY PROCESSING ##########################################################
37120

38121
def query(query, ts, **kwargs):
122+
"""
123+
Perform *query* on the testsuite *ts*.
124+
125+
Note: currently only 'select' queries are supported.
126+
127+
Args:
128+
query (str): TSQL query string
129+
ts (:class:`delphin.itsdb.TestSuite`): testsuite to query over
130+
kwargs: keyword arguments passed to the more specific query
131+
function (e.g., :func:`select`)
132+
Example:
133+
>>> list(tsql.query('select i-id where i-length < 4', ts))
134+
[[142], [1061]]
135+
"""
39136
queryobj = _parse_query(query)
40137

41138
if queryobj['querytype'] in ('select', 'retrieve'):
@@ -44,7 +141,8 @@ def query(query, ts, **kwargs):
44141
queryobj['tables'],
45142
queryobj['where'],
46143
ts,
47-
**kwargs)
144+
mode=kwargs.get('mode', 'list'),
145+
cast=kwargs.get('cast', True))
48146
else:
49147
# not really a syntax error; replace with TSQLError or something
50148
# when the proper exception class exists
@@ -53,6 +151,23 @@ def query(query, ts, **kwargs):
53151

54152

55153
def select(query, ts, mode='list', cast=True):
154+
"""
155+
Perform the TSQL selection query *query* on testsuite *ts*.
156+
157+
Note: The `select`/`retrieve` part of the query is not included.
158+
159+
Args:
160+
query (str): TSQL select query
161+
ts (:class:`delphin.itsdb.TestSuite`): testsuite to query over
162+
mode (str): how to return the results (see
163+
:func:`delphin.itsdb.select_rows` for more information
164+
about the *mode* parameter; default: `list`)
165+
cast (bool): if `True`, values will be cast to their datatype
166+
according to the testsuite's relations (default: `True`)
167+
Example:
168+
>>> list(tsql.select('i-id where i-length < 4', ts))
169+
[[142], [1061]]
170+
"""
56171
queryobj = _parse_select(query)
57172
return _select(
58173
queryobj['projection'],
@@ -264,7 +379,7 @@ def _parse_select(query):
264379

265380
if projection == '*' and not tables:
266381
raise TSQLSyntaxError(
267-
"'select *' requires a 'from' statement",
382+
"'select *' requires a 'from' clause",
268383
lineno=lineno, text=token)
269384

270385
# verify we're at the end of the query (the '.' may have been

docs/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ PyDelphin
3838
api/delphin.tdl.rst
3939
api/delphin.tfs.rst
4040
api/delphin.tokens.rst
41+
api/delphin.tsql.rst
4142

4243

4344
Indices and tables

docs/tutorials/walkthrough.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,22 @@ testsuites:
336336
- :mod:`delphin.itsdb` module
337337
- :doc:`itsdb` tutorial
338338

339+
340+
TSQL Queries
341+
------------
342+
343+
Partial support of the Test Suite Query Language (TSQL) allows for
344+
easy selection of [incr tsdb()] TestSuite data.
345+
346+
>>> from delphin import itsdb, tsql
347+
>>> ts = itsdb.TestSuite('erg/tsdb/gold/mrs')
348+
>>> next(tsql.select('i-id i-input where i-length > 5 && readings > 0', ts))
349+
[61, 'Abrams handed the cigarette to Browne.']
350+
351+
.. seealso::
352+
- TSQL documentation: http://www.delph-in.net/tsnlp/ftp/manual/volume2.ps.gz
353+
- :mod:`delphin.tsql` module
354+
339355
Regular Expression Preprocessors (REPP)
340356
---------------------------------------
341357

0 commit comments

Comments
 (0)