Class: Card::Query

Inherits:
Object
  • Object
show all
Includes:
Attributes, Clause, Conjunctions, Helpers, Interpretation, RelationalAttributes, Run, Sorting
Defined in:
lib/card/query.rb,
lib/card/query/run.rb,
lib/card/query/join.rb,
lib/card/query/value.rb,
lib/card/query/helpers.rb,
lib/card/query/sorting.rb,
lib/card/query/reference.rb,
lib/card/query/attributes.rb,
lib/card/query/conjunctions.rb,
lib/card/query/sql_statement.rb,
lib/card/query/interpretation.rb,
lib/card/query/relational_attributes.rb

Overview

Card::Query is for finding implicit lists (or counts of lists) of cards.

Search and Set cards use Card::Query to query the database, and it's also frequently used directly in code.

Query "statements" (objects, really) are made in WQL (Wagn Query Language). Because WQL is used by Deckers, the primary language documentation is on wagn.org. (http://wagn.org/WQL_Syntax). Note that the examples there are in JSON, like Search card content, but statements in Card::Query are in ruby form.

In Wagn's current form, Card::Query generates and executes SQL statements. However, the SQL generation is largely (not yet fully) separated from the WQL statement interpretation.

The most common way to use Card::Query is as follows: list_of_cards = Card::Query.run(statement)

This is equivalent to: query = Card::Query.new(statement) list_of_cards = query.run

Upon initiation, the query is interpreted, and the following key objects are populated:

  • @join - an Array of Card::Query::Join objects
  • @conditions - an Array of conditions
  • @mod - a Hash of other query-altering keys
  • @subqueries - a list of other queries nested within this one

Each condition is either a SQL-ready string (boo) or an Array in this form: [ field_string_or_sym, Card::Value::Query object ]

Defined Under Namespace

Modules: Attributes, Clause, Conjunctions, Helpers, Interpretation, RelationalAttributes, Run, Sorting Classes: Join, Reference, SqlStatement, Value

Constant Summary collapse

ATTRIBUTES =
{
  basic:           %w( id name key type_id content left_id right_id
                       creator_id updater_id codename read_rule_id        ),
  relational:      %w( type part left right
                       editor_of edited_by last_editor_of last_edited_by
                       creator_of created_by member_of member
                       updater_of updated_by),
  plus_relational: %w(plus left_plus right_plus),
  ref_relational:  %w( refer_to referred_to_by
                       link_to linked_to_by
                       include included_by                                ),
  conjunction:     %w(and or all any),
  special:         %w(found_by not sort match name_match complete junction_complete
                      extension_type),
  ignore:          %w(prepend append view params vars size)
}.each_with_object({}) do |pair, h|
  pair[1].each { |v| h[v.to_sym] = pair[0] }
end
CONJUNCTIONS =
{ any: :or, in: :or, or: :or, all: :and, and: :and }.freeze
MODIFIERS =
%w(conj return sort sort_as group dir limit offset)
.each_with_object({}) { |v, h| h[v.to_sym] = nil }
OPERATORS =
%w(!= = =~ < > in ~).each_with_object({}) { |v, h| h[v] = v }.merge(
  {
    eq: "=", gt: ">", lt: "<", match: "~", ne: "!=", "not in": "not in"
  }.stringify_keys
)
DEFAULT_ORDER_DIRS =
{ update: "desc", relevance: "desc" }.freeze

Constants included from Sorting

Sorting::SORT_BY_ITEM_JOIN_MAP

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Run

#alter_result, #alter_results?, #card_result, #count_result, #default_result, #fetch_or_instantiate, #id_result, #large_list, #name_result, #process_name, #raw_result, #result_method, #return_list, #return_simple, #run, #run_sql, #simple_result?

Methods included from Helpers

#id_from_val, #join_cards, #join_references, #restrict, #restrict_reference, #table_alias, #table_id, #tick_table_seq!

Methods included from Conjunctions

#all, #any, #conjoin, #conjunction, #not

Methods included from Sorting

#sort, #sort_by_count, #sort_by_count_referred_to, #sort_by_item_join, #sort_by_item_join_field, #sort_method_not_implemented

Methods included from Interpretation

#add_condition, #all_joins, #clause_to_hash, #current_conjunction, #interpret, #interpret_attributes, #interpret_by_key, #normalize_array_value, #normalize_clause, #normalize_string_value, #normalize_value, #relate, #relate_compound, #relate_multi_value

Methods included from RelationalAttributes

#created_by, #creator_of, #edited_by, #editor_of, #junction, #last_edited_by, #last_editor_of, #left, #left_plus, #member, #member_of, #part, #plus, #right, #right_plus, #type, #updated_by, #updater_of

Methods included from Attributes

#complete, #extension_type, #found_by, #found_by_cards, #junction_complete, #match, #name_match

Methods included from Clause

#connection, #quote, #safe_sql

Constructor Details

#initialize(statement, comment = nil) ⇒ Query

By default a query returns card objects. This is accomplished by returning a card identifier from SQL and then hooking into our caching system (see Card::Fetch)



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/card/query.rb', line 97

def initialize statement, comment=nil
  @subqueries = []
  @conditions = []
  @joins = []
  @mods = {}
  @statement = statement.clone

  @context    = @statement.delete(:context) || nil
  @unjoined   = @statement.delete(:unjoined) || nil
  @superquery = @statement.delete(:superquery) || nil
  @vars       = initialize_vars

  @comment = comment || default_comment

  interpret @statement
  self
end

Instance Attribute Details

#commentObject (readonly)

Returns the value of attribute comment.



87
88
89
# File 'lib/card/query.rb', line 87

def comment
  @comment
end

#conditionsObject (readonly)

Returns the value of attribute conditions.



87
88
89
# File 'lib/card/query.rb', line 87

def conditions
  @conditions
end

#conditions_on_joinObject

Returns the value of attribute conditions_on_join.



89
90
91
# File 'lib/card/query.rb', line 89

def conditions_on_join
  @conditions_on_join
end

#joinsObject

Returns the value of attribute joins.



89
90
91
# File 'lib/card/query.rb', line 89

def joins
  @joins
end

#modsObject (readonly)

Returns the value of attribute mods.



87
88
89
# File 'lib/card/query.rb', line 87

def mods
  @mods
end

#statementObject (readonly)

Returns the value of attribute statement.



87
88
89
# File 'lib/card/query.rb', line 87

def statement
  @statement
end

#subqueriesObject (readonly)

Returns the value of attribute subqueries.



87
88
89
# File 'lib/card/query.rb', line 87

def subqueries
  @subqueries
end

#superqueryObject (readonly)

Returns the value of attribute superquery.



87
88
89
# File 'lib/card/query.rb', line 87

def superquery
  @superquery
end

#table_seqObject

Returns the value of attribute table_seq.



89
90
91
# File 'lib/card/query.rb', line 89

def table_seq
  @table_seq
end

#unjoinedObject (readonly)

Returns the value of attribute unjoined.



87
88
89
# File 'lib/card/query.rb', line 87

def unjoined
  @unjoined
end

#varsObject (readonly)

Returns the value of attribute vars.



87
88
89
# File 'lib/card/query.rb', line 87

def vars
  @vars
end

Class Method Details

.run(statement, comment = nil) ⇒ Object



4
5
6
# File 'lib/card/query/run.rb', line 4

def self.run statement, comment=nil
  new(statement, comment).run
end

Instance Method Details

#contextObject



146
147
148
149
150
151
152
# File 'lib/card/query.rb', line 146

def context
  if !@context.nil?
    @context
  else
    @context = @superquery ? @superquery.context : ""
  end
end

#default_commentObject



122
123
124
125
# File 'lib/card/query.rb', line 122

def default_comment
  return if @superquery || !Card.config.sql_comments
  statement.to_s
end

#full?Boolean

Returns:

  • (Boolean)


158
159
160
# File 'lib/card/query.rb', line 158

def full?
  !superquery && mods[:return] != "count"
end

#initialize_varsObject



115
116
117
118
119
120
# File 'lib/card/query.rb', line 115

def initialize_vars
  if (v = @statement.delete :vars) then v.symbolize_keys
  elsif @superquery                then @superquery.vars
  else                                  {}
  end
end

#limitObject



154
155
156
# File 'lib/card/query.rb', line 154

def limit
  mods[:limit].to_i
end

#rootObject

Query Hierarchy @root, @subqueries, and @superquery are used to track a hierarchy of query objects. This nesting allows to find, for example, cards that link to cards that link to cards....



136
137
138
# File 'lib/card/query.rb', line 136

def root
  @root ||= @superquery ? @superquery.root : self
end

#sqlObject



127
128
129
# File 'lib/card/query.rb', line 127

def sql
  @sql ||= SqlStatement.new(self).build.to_s
end

#subquery(opts = {}) ⇒ Object



140
141
142
143
144
# File 'lib/card/query.rb', line 140

def subquery opts={}
  subquery = Query.new opts.merge(superquery: self)
  @subqueries << subquery
  subquery
end