Certain queries need to be implemented if you are going to use SVN as a DB. These are some notes on how that would work. For up-to-date information on how it actually works, consult the source. (FIXME)
Imagine the following DB:
(The first column indicates a type of element: / for directory, f for file, e for element in a file.)
/ /Users / /Users/Ethan f /Users/Ethan/hobbies e /Users/Ethan/hobbies/video games e /Users/Ethan/hobbies/programming f /Users/Ethan/profile / /Users/Chiz f /Users/Chiz/profile
/ /Wiki / /Wiki/Memes / /Wiki/Memes/Fuck my crikey! f /Wiki/Memes/Fuck my crikey!/tags e /Wiki/Memes/Fuck my crikey!/tags/Force Monkeys / /Wiki/Memes/We're having money f /Wiki/Memes/We're having money/tags e /Wiki/Memes/We're having money/tags/Penny Arcade / /Wiki/Culture / /Wiki/Culture/Force Monkeys f /Wiki/Culture/Force Monkeys/tags e /Wiki/Culture/Force Monkeys/tags/Webcomics e /Wiki/Culture/Force Monkeys/tags/Force Monkeys
get-paths
Find all paths matching a certain wildcard.
get-paths /Users/* would return [/Users/Ethan, /Users/Chiz]
Implement "where clauses"?
get-paths /Users/* where has-child(hobbies) would return [/Users/Ethan]
get-paths /Users/* where has-child(hobbies/skating) would return [/Users/Ethan]
get-paths /Users/** would return [/Users/Ethan, /Users/Ethan/hobbies, /Users/Ethan/hobbies/video games, /Users/Ethan/profile, /Users/Chiz, /Users/Chiz/profile]
get-paths /Wiki/** where has-child(tags/Force Monkeys) would return [/Wiki/Memes/Fuck my crikey!, /Wiki/Culture/Force Monkeys]
get-paths /Users/** where newer(2007-04-10) ..?
history
Get all revisions of a file? How will this work?
Syntax
Something like this?
files().matching("Users/Ethan/*").with_child()
i.e. a recordset class that "selector methods" that themselves return recordsets? with_child() takes some kind of "selector method" as an optional argument.
This very naturally allows "and" queries, but no "or" or "not" queries. (Obviously you could use files().not(matching("Users/Ethan/*")) -- is this dumb?)
Should the following be separate or somehow condensed?
match() builtin that does any kind of page matching? glob-based syntax?
grep() which has a regexp syntax?
find() which has some other kind of syntax?
Other builtins?
newer(DATE), older(DATE)?
sort(by=date), sort(by=name), sort(by=key(child("food")))?
tag("meme")?
link(PAGE)?
class(TEXT) [or, NODE, FILE, COMMENT, REVISION, "game"]?
children() or descendent()?
revisions()?
XPath has two path syntaxes: child::para/child::para selects the para children of all para children, but child::para[child::para] selects all para children that have para children. In either case, one must look at all the para grandchildren, but in one case you select their parents, and in another you select the grandchildren themselves.
Perhaps instead of a has_child() construction, you could do something like:
files().has(children().class("para"))
or
files().where(children().class("para"))
versus
files().children().class("para")?
Each "axis" in a location path would be transformed into a selector function, and like XPath's feature of selecting no nodes if none match, a selector could return "no nodes".
In XPath there are things like child::para[position()=3] to select an object's third para child. To do "position()=3" we'd have to do some entirely new craziness.
But the syntax above is much like XPath -- each selector is just like a predicate, and each predicate hones down the list. But we also fold in location paths, which can do crazy things like child::para/child::para/ancestor::* (which doesn't limit the nodeset at all). But if you introduce things like descendant(), a selector obviously need not hone down a list.
I'm not sure position() makes sense for Lockers anyhow. What would it mean? In XPath it's presumably the location relative to a parent, but presumably a sort() selector would alter things. Who cares, for instance, what the first ten games are? More likely is that someone would care what the first ten games are if first you sort by mtime.