Class: Card::Query
- Inherits:
-
Object
- Object
- Card::Query
- Includes:
- Attributes, Clause, Conjunctions, Helpers, Interpretation, RelationalAttributes, Sorting
- Defined in:
- lib/card/query.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 Wagneers, 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, 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" => nil }.stringify_keys )
- DEFAULT_ORDER_DIRS =
{ update: "desc", relevance: "desc" }.freeze
Constants included from Sorting
Sorting::SORT_JOIN_TO_ITEM_MAP
Instance Attribute Summary collapse
-
#comment ⇒ Object
readonly
Returns the value of attribute comment.
-
#conditions ⇒ Object
readonly
Returns the value of attribute conditions.
-
#conditions_on_join ⇒ Object
Returns the value of attribute conditions_on_join.
-
#joins ⇒ Object
Returns the value of attribute joins.
-
#mods ⇒ Object
readonly
Returns the value of attribute mods.
-
#statement ⇒ Object
readonly
Returns the value of attribute statement.
-
#subqueries ⇒ Object
readonly
Returns the value of attribute subqueries.
-
#superquery ⇒ Object
readonly
Returns the value of attribute superquery.
-
#table_seq ⇒ Object
Returns the value of attribute table_seq.
-
#unjoined ⇒ Object
readonly
Returns the value of attribute unjoined.
-
#vars ⇒ Object
readonly
Returns the value of attribute vars.
Class Method Summary collapse
-
.run(statement, comment = nil) ⇒ Object
By default a query returns card objects.
Instance Method Summary collapse
- #context ⇒ Object
- #contextual_name_processor(pattern) ⇒ Object
- #default_comment ⇒ Object
-
#get_results(retrn) ⇒ Object
Integer for :count, otherwise Array of Strings or Integers.
-
#initialize(statement, comment = nil) ⇒ Query
constructor
A new instance of Query.
- #initialize_vars ⇒ Object
- #limit ⇒ Object
-
#root ⇒ Object
Query Hierarchy @root, @subqueries, and @superquery are used to track a hierarchy of query objects.
-
#run ⇒ Object
run the current query.
- #run_sql ⇒ Object
- #sql ⇒ Object
- #subquery(opts = {}) ⇒ Object
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
Methods included from Interpretation
#add_condition, #all_joins, #clause_to_hash, #current_conjunction, #interpret, #interpret_attributes, #interpret_by_key, #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
#match_prep, #quote, #safe_sql
Constructor Details
#initialize(statement, comment = nil) ⇒ Query
Returns a new instance of Query.
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/card/query.rb', line 99 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
#comment ⇒ Object (readonly)
Returns the value of attribute comment.
85 86 87 |
# File 'lib/card/query.rb', line 85 def comment @comment end |
#conditions ⇒ Object (readonly)
Returns the value of attribute conditions.
85 86 87 |
# File 'lib/card/query.rb', line 85 def conditions @conditions end |
#conditions_on_join ⇒ Object
Returns the value of attribute conditions_on_join.
87 88 89 |
# File 'lib/card/query.rb', line 87 def conditions_on_join @conditions_on_join end |
#joins ⇒ Object
Returns the value of attribute joins.
87 88 89 |
# File 'lib/card/query.rb', line 87 def joins @joins end |
#mods ⇒ Object (readonly)
Returns the value of attribute mods.
85 86 87 |
# File 'lib/card/query.rb', line 85 def mods @mods end |
#statement ⇒ Object (readonly)
Returns the value of attribute statement.
85 86 87 |
# File 'lib/card/query.rb', line 85 def statement @statement end |
#subqueries ⇒ Object (readonly)
Returns the value of attribute subqueries.
85 86 87 |
# File 'lib/card/query.rb', line 85 def subqueries @subqueries end |
#superquery ⇒ Object (readonly)
Returns the value of attribute superquery.
85 86 87 |
# File 'lib/card/query.rb', line 85 def superquery @superquery end |
#table_seq ⇒ Object
Returns the value of attribute table_seq.
87 88 89 |
# File 'lib/card/query.rb', line 87 def table_seq @table_seq end |
#unjoined ⇒ Object (readonly)
Returns the value of attribute unjoined.
85 86 87 |
# File 'lib/card/query.rb', line 85 def unjoined @unjoined end |
#vars ⇒ Object (readonly)
Returns the value of attribute vars.
85 86 87 |
# File 'lib/card/query.rb', line 85 def vars @vars end |
Class Method Details
.run(statement, comment = nil) ⇒ Object
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)
95 96 97 |
# File 'lib/card/query.rb', line 95 def self.run statement, comment=nil new(statement, comment).run end |
Instance Method Details
#context ⇒ Object
209 210 211 212 213 214 215 |
# File 'lib/card/query.rb', line 209 def context if !@context.nil? @context else @context = @superquery ? @superquery.context : "" end end |
#contextual_name_processor(pattern) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/card/query.rb', line 174 def contextual_name_processor pattern case pattern.downcase when "_left", "_l" ->(name) { name.to_name.left_name.to_s } when "_right", "_r" ->(name) { name.to_name.right_name.to_s } else chain = "name.to_name" pattern.each_char do |ch| case ch when "l", "L" chain += ".left_name" when "r", "R" chain += ".right_name" end end eval "lambda { |name| #{chain}.to_s }" end end |
#default_comment ⇒ Object
124 125 126 127 |
# File 'lib/card/query.rb', line 124 def default_comment return if @superquery || !Card.config.sql_comments statement.to_s end |
#get_results(retrn) ⇒ Object
Returns Integer for :count, otherwise Array of Strings or Integers.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 |
# File 'lib/card/query.rb', line 143 def get_results retrn rows = run_sql if retrn =~ /_\w+/ name_processor = contextual_name_processor retrn rows.map do |row| name_processor.call row["name"] end elsif retrn == "name" && (statement[:prepend] || statement[:append]) rows.map do |row| [statement[:prepend], row["name"], statement[:append]].compact * "+" end else case retrn when "count" then rows.first["count"].to_i when "raw" then rows when /id$/ then rows.map { |row| row[retrn].to_i } else rows.map { |row| row[retrn] } end end end |
#initialize_vars ⇒ Object
117 118 119 120 121 122 |
# File 'lib/card/query.rb', line 117 def initialize_vars if (v = @statement.delete :vars) then v.symbolize_keys elsif @superquery then @superquery.vars else {} end end |
#limit ⇒ Object
217 218 219 |
# File 'lib/card/query.rb', line 217 def limit @mods[:limit].to_i end |
#root ⇒ Object
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....
199 200 201 |
# File 'lib/card/query.rb', line 199 def root @root ||= @superquery ? @superquery.root : self end |
#run ⇒ Object
run the current query
131 132 133 134 135 136 137 138 139 140 |
# File 'lib/card/query.rb', line 131 def run retrn ||= statement[:return].present? ? statement[:return].to_s : "card" if retrn == "card" get_results("name").map do |name| Card.fetch name, new: {} end else get_results retrn end end |
#run_sql ⇒ Object
164 165 166 167 168 |
# File 'lib/card/query.rb', line 164 def run_sql # puts "\nstatement = #{@statement}" # puts "sql = #{sql}" ActiveRecord::Base.connection.select_all(sql) end |
#sql ⇒ Object
170 171 172 |
# File 'lib/card/query.rb', line 170 def sql @sql ||= SqlStatement.new(self).build.to_s end |