DIRECTORY IO USING [STREAM], Rope USING [ROPE], LoganBerry, LoganQueryClass; LoganQuery: CEDAR DEFINITIONS ~ BEGIN ROPE: TYPE ~ Rope.ROPE; Cursor: TYPE = LoganQueryClass.Cursor; ComplexCursor: TYPE = LoganQueryClass.Cursor; -- for backward compatibility CursorDirection: TYPE = LoganBerry.CursorDirection; NextEntry: PROC [cursor: Cursor, dir: CursorDirection ¬ increasing] RETURNS [entry: LoganBerry.Entry]; EndGenerate: PROC [cursor: Cursor] RETURNS []; PatternType: TYPE = Rope.ROPE; AttributePattern: TYPE = REF AttributePatternRec; AttributePatternRec: TYPE = RECORD [ attr: LoganBerry.Attribute, ptype: PatternType ¬ NIL ]; AttributePatterns: TYPE = LIST OF AttributePattern; SyntaxError: ERROR [explanation: Rope.ROPE ¬ NIL]; ReadAttributePatterns: PROC [s: IO.STREAM] RETURNS [ap: AttributePatterns]; WriteAttributePatterns: PROC [s: IO.STREAM, ap: AttributePatterns] RETURNS []; PatternsToEntry: PROC [ap: AttributePatterns] RETURNS [entry: LoganBerry.Entry]; EntryToPatterns: PROC [entry: LoganBerry.Entry] RETURNS [ap: AttributePatterns]; QueryPlan: TYPE = LIST OF SubPlan; SubPlan: TYPE = REF SubPlanRec; SubPlanRec: TYPE = RECORD[ attr: LoganBerry.Attribute, -- field type and pattern ptype: PatternType, -- pattern matching used wasDWIM: BOOLEAN ¬ FALSE, -- ptype was DWIM filter: LoganQueryClass.MatchProc ¬ NIL, -- match proc itype: ATOM ¬ $notAnIndex, -- index layout start, end: ROPE ¬ NIL, -- base range cost: REAL ¬ 2.0, -- estimated query cost infoMsg: ROPE ¬ NIL, -- informational message errMsg: ROPE ¬ NIL -- error in pattern if not NIL ]; QueryEntries: PROC [db: LoganBerry.OpenDB, patterns: AttributePatterns, baseIndex: LoganBerry.AttributeType ¬ NIL, defaultPattern: PatternType ¬ "DWIM", planOnly: BOOLEAN ¬ FALSE] RETURNS [cursor: Cursor, plan: QueryPlan]; ParseTree: TYPE = ParseNode; ParseNodeTag: TYPE = {and, or, not, ap}; ParseNode: TYPE = REF ParseNodeRec; ParseNodeRec: TYPE = RECORD [ tag: ParseNodeTag, child1: ParseNode ¬ NIL, -- used if tag in $and .. $not child2: ParseNode ¬ NIL, -- used if tag in $and .. $or ap: AttributePattern ¬ NIL -- used if tag = $ap ]; ParseBooleanQuery: PROC [s: IO.STREAM] RETURNS [tree: ParseTree]; BooleanFilterEntries: PROC [input: Cursor, query: ParseTree, inputOrder: LoganBerry.AttributeType, primaryKey: LoganBerry.AttributeType, defaultPattern: PatternType ¬ "DWIM"] RETURNS [output: Cursor]; AbortQuery: PROC [cursor: Cursor]; END. † LoganQuery.mesa Copyright Σ 1985, 1992 by Xerox Corporation. All rights reserved. Doug Terry, July 21, 1992 10:07 am PDT LoganQuery allows more complicated queries to be performed on a LoganBerry database than the simple retrievals provided by the LoganBerry interface. These include multiple-attribute queries and boolean queries. The results of such queries are obtained by retrieving entries one at a time from a cursor. This interface provides operations that generate cursors for complex queries. See LoganQueryClass.mesa for obtaining more basic cursors. Basic operations The following two operations are syntactically identical and semantically similar to those provided by LoganBerry. Any errors raised by these operations are generated by LoganBerry. Retrieves the next entry relative to the given cursor. The cursor is automatically updated so that NextEntry may be repeatedly called to enumerate entries. NIL is returned if the cursor is at the end of the sequence and dir=increasing or at the start of the sequence and dir=decreasing. Errors: IndexNotOpen, BadIndex, LogNotOpen, BadLogEntry Releases the cursor; no further operations may be performed using the given cursor. This must be called once for every cursor created. Attribute-based queries Following are some operations for dealing with attribute patterns and using them to query a LoganBerry database. Multi-attribute queries are accomplished by cascading one or more filters. Attribute patterns are lists of LoganBerry attributes that may optionally contain a pattern type. The currently supported types of patterns include "exact", "prefix", "wildcard", "re", "soundex", etc. (see PatternMatchersDoc.tioga). The following data structure is the internal representation of an attribute pattern list. In addition, attribute patterns have an external (character string) representation that can be printed or typed in. A basic LoganBerry attribute is represented in the form: : In this case, since a pattern is not explicitly specified, a default pattern is used (currently the default is "DWIM"). The attribute value may be either a token or a rope literal. An explicit pattern type may be given in parenthesis immediately following the attribute type. Thus, an attribute pattern is given in the form (): Several of these may be concatenated together to get a list of attribute patterns. For example, Name: "Douglas B. Terry" Phone(prefix): 494-44 Office(wildcard): 35-2* Reads an externalized list of attribute patterns from the given stream and builds the appropriate data structure. Raises ! SyntaxError if the stream does not contain a validly formed list of attributes. Writes a list of attribute patterns to the given stream. Converts a list of attribute patterns to a LoganBerry entry by ignoring the pattern type. Converts a LoganBerry entry to a list of attribute patterns with ptype=NIL. A query plan is given as a list of alternate subplans. When returned by QueryEntries, a query plan has the chosen subplan at the head of the list. Returns a cursor of class $Query. Retrievals using this new cursor match the attribute patterns against entries in the database. The baseIndex parameter governs which attribute type is used as the base index for the query; for baseIndex=NIL, an index is chosen that attempts to optimize the execution of the query (use this unless you really care about the order in which database entries are retrieved). The defaultPattern parameter indicates which type of pattern matching to use if this is not explictly specified in an attribute pattern. The returned query plan provides information about the query. If planOnly is TRUE, then a query plan is formulated and returned, but a cursor for this query is not created. Boolean attribute-based queries The following operations support boolean queries over a LoganBerry database. The simplest query is a single attribute pattern: (): where the pattern specification is optional. These can be combined using AND, OR, and NOT as well as parenthesis. The AND operator between attribute patterns is optional (for compatibility with the attribute-based queries defined above). The actual grammar for boolean queries is as follows: query ::= boolexpr | boolexpr query boolexpr ::= term | term "OR" boolexpr term ::= factor | factor "AND" term factor ::= attribute-pattern | "NOT" factor | "(" boolexpr ")" attribute-pattern ::= attribute-type ":" attribute-value | attribute-type "(" pattern ")" ":" attribute-value Boolean queries are parsed into a parse tree that is defined as follows: Returns the parse tree for the query read from the given stream. Raises SyntaxError if the query is not a proper boolean query. Returns a cursor of class $BooleanFilter. Retrievals using this new cursor match the boolean query against entries returned by the input cursor. The query tree should be the result of ParseBooleanQuery. The inputOrder specifies the attribute by which entries on the input cursor are ordered, while primaryKey indicates the attribute for which these entries have unique values. The defaultPattern parameter indicates which type of pattern matching to use if this is not explictly specified in an attribute pattern. The input cursor could be obtained from QueryEntries (or a variety of operations in LoganQueryClass such as GenerateEntries). Aborting queries If a process is currently executing a NextEntry operation on the given cursor, the process is aborted and the operation returns NIL; any subsequent calls to NextEntry will also return NIL (i.e. the cursor is no longer useable). This can be used on cursors returned by either QueryEntries or BooleanFilterEntries. Doug Terry November 6, 1985 9:55:44 am PST created Doug Terry, November 6, 1985 5:15:27 pm PST changes to: DIRECTORY, ILQuery, ~, Cursor, CursorDirection, CursorClass, CursorClassRec, RetrieveProc, DestroyProc, NextEntry, EndGenerate, GenerateEntries, FilterEntries, MatchResult, FilterProc, MergeEntries Doug Terry, November 7, 1985 2:59:51 pm PST changes to: ~, QueryClass, QueryClassRec, ComplexCursor, RetrieveProc, DestroyProc, FilterEntries, FilterProc, MergeEntries, Equal, Prefix, Wildcard, RegularExpression, Soundex, DIRECTORY, NextEntry Doug Terry, November 26, 1985 4:12:52 pm PST changes to: DIRECTORY, LoganQuery, RetrieveProc, CursorDirection, NextEntry, GenerateEntries, FilterEntries, MergeEntries Doug Terry, April 14, 1987 3:36:36 pm PDT Moved FilterProcs to PatternMatch; added $Query class from LoganBerryBrowser. changes to: FilterEntries, MergeEntries, SyntaxError, QueryWarning, QueryPlan, QueryPlanRec, QueryEntries, END Doug Terry, April 17, 1987 10:39:35 am PDT Added $Aborter class and AbortQuery for halting operations in mid-execution. changes to: ComplexCursor, EndGenerate, QueryEntries, EnableAborts, AbortQuery Doug Terry, July 16, 1992 12:38:14 pm PDT Added boolean queries. Κ}–(cedarcode) style•NewlineDelimiter ™codešœ™Kšœ Οeœ6™BK™&K˜K™»K™—šΟk ˜ Kšœžœžœ˜Kšœžœžœ˜K˜ K˜—K˜KšΠbl œžœž ˜šœž˜K˜Kšžœžœžœ˜K˜Kšœžœ˜&KšœžœΟc˜LIcode0šœžœ˜3—headšœ™KšœΆ™ΆK˜šΟn œžœ5žœ˜fKšœ ™ Kšœ7™7—K˜š‘ œžœžœ˜.Kšœ‡™‡——™K™ΌK™K™ΈK˜Kšœ žœž˜K˜Kšœžœžœ˜1šœžœžœ˜$Kšœ˜Kšœž˜K˜—Kšœžœžœžœ˜3L˜Lš‘ œžœžœžœ˜2K™š ‘œžœžœžœžœ˜KKšœΛ™ΛK™—š ‘œžœžœžœžœ˜NK™8K™—š‘œžœžœ˜PK™YK™—š‘œžœžœ˜PK™KK™—LšœŽ œ™“Lšœ žœžœžœ ˜"Lšœ žœžœ ˜šœ žœžœ˜Kšœ ˜6Kšœ ˜-Kšœ žœžœ ˜,Kšœ$žœ  ˜7Kšœžœ ˜+Kšœ žœžœ  ˜&Kšœžœ  ˜*Kšœ žœžœ ˜.Kšœžœžœ ˜2L˜—L˜š ‘ œžœ\žœ2žœžœžœ#˜ήK™ΟK™——™K™β™ψ™K™#K™&K™#K™?K™q——K™K™HK™Kšœ žœ ˜Kšœžœ˜(Kšœ žœžœ˜#šœžœžœ˜K˜Kšœžœ ˜9Kšœžœ ˜7Kšœžœ ˜0K˜—L˜š ‘œžœžœžœžœ˜AK™€K™—š‘œžœ•žœ˜ΘK™†—K™—™š‘ œžœ˜"K™ΉK™——Kšžœ˜K™™*K™—™+Kšœ ΟrΕ™Ρ—™+Kšœ ’Ί™Ζ—™,Kšœ ’m™y—™)K™MKšœ ’b™n—™*KšœL™LKšœ ’B™N—™)K™—K™—…— „)‡