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 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
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.
- #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
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, #match
Methods included from Clause
#match_prep, #quote, #safe_sql
Constructor Details
#initialize(statement, comment = nil) ⇒ Query
Returns a new instance of Query.
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/card/query.rb', line 98 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 = @statement.delete(:vars) || {} @vars.symbolize_keys! @comment = comment || default_comment interpret @statement self end |
Instance Attribute Details
#comment ⇒ Object (readonly)
Returns the value of attribute comment.
84 85 86 |
# File 'lib/card/query.rb', line 84 def comment @comment end |
#conditions ⇒ Object (readonly)
Returns the value of attribute conditions.
84 85 86 |
# File 'lib/card/query.rb', line 84 def conditions @conditions end |
#conditions_on_join ⇒ Object
Returns the value of attribute conditions_on_join.
86 87 88 |
# File 'lib/card/query.rb', line 86 def conditions_on_join @conditions_on_join end |
#joins ⇒ Object
Returns the value of attribute joins.
86 87 88 |
# File 'lib/card/query.rb', line 86 def joins @joins end |
#mods ⇒ Object (readonly)
Returns the value of attribute mods.
84 85 86 |
# File 'lib/card/query.rb', line 84 def mods @mods end |
#statement ⇒ Object (readonly)
Returns the value of attribute statement.
84 85 86 |
# File 'lib/card/query.rb', line 84 def statement @statement end |
#subqueries ⇒ Object (readonly)
Returns the value of attribute subqueries.
84 85 86 |
# File 'lib/card/query.rb', line 84 def subqueries @subqueries end |
#superquery ⇒ Object (readonly)
Returns the value of attribute superquery.
84 85 86 |
# File 'lib/card/query.rb', line 84 def superquery @superquery end |
#table_seq ⇒ Object
Returns the value of attribute table_seq.
86 87 88 |
# File 'lib/card/query.rb', line 86 def table_seq @table_seq end |
#unjoined ⇒ Object
Returns the value of attribute unjoined.
86 87 88 |
# File 'lib/card/query.rb', line 86 def unjoined @unjoined end |
#vars ⇒ Object (readonly)
Returns the value of attribute vars.
84 85 86 |
# File 'lib/card/query.rb', line 84 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)
94 95 96 |
# File 'lib/card/query.rb', line 94 def self.run statement, comment=nil new(statement, comment).run end |
Instance Method Details
#context ⇒ Object
202 203 204 205 206 207 208 |
# File 'lib/card/query.rb', line 202 def context if !@context.nil? @context else @context = @superquery ? @superquery.context : "" end end |
#contextual_name_processor(pattern) ⇒ Object
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
# File 'lib/card/query.rb', line 167 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
117 118 119 120 |
# File 'lib/card/query.rb', line 117 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.
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/card/query.rb', line 136 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 |
#limit ⇒ Object
210 211 212 |
# File 'lib/card/query.rb', line 210 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....
192 193 194 |
# File 'lib/card/query.rb', line 192 def root @root ||= @superquery ? @superquery.root : self end |
#run ⇒ Object
run the current query
124 125 126 127 128 129 130 131 132 133 |
# File 'lib/card/query.rb', line 124 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
157 158 159 160 161 |
# File 'lib/card/query.rb', line 157 def run_sql # puts "\nstatement = #{@statement}" # puts "sql = #{sql}" ActiveRecord::Base.connection.select_all(sql) end |
#sql ⇒ Object
163 164 165 |
# File 'lib/card/query.rb', line 163 def sql @sql ||= SqlStatement.new(self).build.to_s end |