15,534
edits
Changes
ha different travis!
{{Third-party plugin}}
The Query Gramplet takes SQL-like queries and produces a Quick View.
= Examples = The QueryGramplet in gramps-addons/trunk for gramps/master can nowSELECT, UPDATE, and DELETE. Some examples (keywords are showncapitalized, but the SQL parser is case-insensitive; fields that are capitalized are ''macros'', see below for more information): <pre>DELETE FROM person WHERE GIVEN == "Travis";
SELECT gramps_id FROM person LIMIT 5; SELECT gramps_id FROM person LIMIT 20,30; SELECT gramps_id, father_handle.SURNAME, mother_handle.SURNAME from family; </pre>This API is made possible through the generic struct/json interface.It is very little code, because it relies on these generic structures.It should be able to be made solid enough to expose to users (say as ageneric filter). The parser can be made more user friendly... it mayjust throw an error currently.
I'd be interested in any limitations you find, or enhancement ideas.
= SQL =
Here is the grammar for the subset of SQL supported. The SELECT, UPDATE, DELETE, and LIMIT clauses may be in any order. The WHERE clause (if used) must be last.
<pre>
SELECT expr1 [as var1][, expr2 [as var2], ...] FROM table [LIMIT number1[, number2]] [WHERE expression];
UPDATE table SET field1=expr1[, field2=expr2, ...] [LIMIT number1[, number2]] [WHERE expression];
DELETE FROM table [LIMIT number1[, number2]] [WHERE expression];
... [FLAT | EXPAND] ...
... [RAW | NORAW] ...
</pre>
'''table''' is one of:
* person
* place
* repository
* event
* citation
* source
* tag
* media
* family
Other items:
* '''expr''' is a field, *, or expression
* '''var''' is an alias
* '''number1''' by itself is maximum number of rows to select
* '''number1''' with '''number2''' is start, stop (first row is zero)
* '''expression''' is any valid Python expression
'''expression''' and '''expr''' may use:
* random.random() (or other random method)
* ROWNUM (zero-based counter)
* col[N] (alias to column)
* aliases
* '''object''' - the primitive gen.lib object (such as Person, Family, etc)
RAW/NORAW: does not turn the results into strings, but leaves the selected values as raw Python. The default is NORAW. Once set, the new setting will remain the default for this session.
FLAT/EXPAND: if FLAT, then the rows are not cross-product JOINED with other multi-valued columns, but rather left as LISTS. Default is EXPAND. Once set, the new setting will remain the default for this session.
The following shortcuts (also called "macros") can be used in expressions and as a field:
* '''SURNAME''', short for "primary_name.surname_list[0].surname"
* '''GIVEN''', short for "primary_name.first_name"
A ''macro'' is a low-level text replacement system. We could add other macros, and even allow users to define their own.
== Pre-Defined Functions and Libraries ==
The following are defined for use in your queries:
* Tag(name) - Create or lookup a tag by its name
* re - The Python regular expression library
* random - The Python random library
* db - the current Gramps database
* sdb - Simple Database API to the database
* Today() - a Gramps Date object set to today's date
* Date() - creates a Gramps Date object
* lib - to access gramps.gen.lib object definitions
* _(text) - for translations
Examples:
<pre>
SELECT gramps_id, primary_name.surname_list.surname
FROM person
WHERE any([re.match("Sm.*th", name) for name in col[1]]);
</pre>
Searches all primary_name surnames to find names that start with "Sm" and end in "th". col[1] is primary_name.surname_list.surname, which is a list of surnames.
UPDATE person SET tag_list=Tag("Smith") WHERE SURNAME == "Smith";
== Lists ==
When a attribute is a list, you can select elements from items in the list, and also filter the list. For example, consider a person's parent_family_list. You can select only a single component, say private, of the parent family like:
SELECT parent_family_list("private") FROM person;
This would select only the private component from the parent families.
Likewise, you can filter the list to, say, only show those families that are private:
SELECT parent_family_list(private=True) FROM person;
This will only show (in the finally selected people) the parent families that are private.
Finally, you can both limit, and select from a list:
SELECT parent_family_list("gramps_id", private=True) FROM person;
That will limit the list to be a list of family gramps_id for private families.
You can delete an entire list by assigning None to it:
UPDATE note_list=None from person;
You can delete an item in a list by assigning None to it:
UPDATE note_list[0]=None from person;
= Notes =
Some notes on use:
1) Most SQL clauses (UPDATE table, FROM table, SELECT ..., SETfield=value, ..., LIMIT ...) can appear in any position, any order
2) ...except the WHERE clause: it must be last; this is because theWHERE clause is not parsed, because:
3) The WHERE clause uses any valid Python expressions. (May need toimport It imports some libraries (such as random), to have ready any possibleexpression needed).
4) The SELECT fields use the bracketed notation for list references. Use "event_ref_list[0]". 5) JOINS are not necessary, because it automatically looks up all relations through the handles. In a SELECT, columns with multiple values in a list will appear as an outer-join with other values in the row. 6) UPDATE currently only works will work on the primary any field, through a joined object, not or on thejoined primary object. For example, you can't update the birth date of anevent through the person's referenced events. I think this can befixed.
7) Tables are lowercase, single (not plural) form (eg, person, tag, event).
8) Need to implement Implemented "LIMIT number; ", "LIMIT start, stop; ", and "WHERE ROWNUM < number" (ROWNUM can be used in any expression).
9) Field names are the actual names of the fields of thegramps.gen.lib objects, verbatim, no differences. You might need tolook up what you need... no help yet from this interface (although Iam working on defining a built-in Schema that could help)
10) .handle or .ref automatically look up their references.
11) Shortcut: you can use col[N] in the WHERE clause to reference acolumn selected. N is zero-based.
That will select all people where private is not True. That would include None (non-existent record) and False values. To select only False values, use: SELECT gramps_id, private FROM person WHERE col[1] == False; That will not select None values. 12) If an object doesn't match any selected field, it just doesn'tshow. For example, to find all of the people with at least two
surnames on their primary name, use:
or
= Older documentation for the QueryGramplet in Gramps 3.4 =
This has different table names (people rather than person), and other names that are different (surname vs primary_name.surname_list[0].surname).
[[Image:QueryGramplet.jpg|thumb|400px|left]]
[[Image:QuerySmith.png|thumb|left|400px]]
{{-}}
<pre> $ select given_name, surname from people;
$ select * from families;
</pre>
[[Category:Plugins]]
[[Category:Developers/General]]
[[Category:Reports]]
[[Category:Gramplets]]
[[Category:Views]]