Module: Sequel::Dataset::SQL
- Included in:
- Sequel::Dataset
- Defined in:
- lib/sequel/dataset/sql.rb
Overview
The Dataset SQL module implements all the dataset methods concerned with generating SQL statements for retrieving and manipulating records.
Constant Summary collapse
- ALIASED_REGEXP =
/^(.*)\s(.*)$/.freeze
- QUALIFIED_REGEXP =
/^(.*)\.(.*)$/.freeze
- WILDCARD =
'*'.freeze
- COMMA_SEPARATOR =
", ".freeze
- NULL =
"NULL".freeze
- TIMESTAMP_FORMAT =
"TIMESTAMP '%Y-%m-%d %H:%M:%S'".freeze
- DATE_FORMAT =
"DATE '%Y-%m-%d'".freeze
- TRUE =
"'t'".freeze
- FALSE =
"'f'".freeze
- AND_SEPARATOR =
" AND ".freeze
- QUESTION_MARK =
'?'.freeze
- JOIN_TYPES =
{ :left_outer => 'LEFT OUTER JOIN'.freeze, :right_outer => 'RIGHT OUTER JOIN'.freeze, :full_outer => 'FULL OUTER JOIN'.freeze, :inner => 'INNER JOIN'.freeze }
- STOCK_COUNT_OPTS =
{:select => ["COUNT(*)".lit], :order => nil}.freeze
Instance Method Summary collapse
-
#and(*cond, &block) ⇒ Object
Adds an further filter to an existing filter using AND.
-
#column_list(columns) ⇒ Object
Converts an array of column names into a comma seperated string of column names.
-
#count ⇒ Object
Returns the number of records in the dataset.
-
#delete_sql(opts = nil) ⇒ Object
Formats a DELETE statement using the given options and dataset options.
-
#except(dataset, all = false) ⇒ Object
Adds an EXCEPT clause using a second dataset object.
-
#exclude(*cond, &block) ⇒ Object
Performs the inverse of Dataset#filter.
-
#exists(opts = nil) ⇒ Object
Returns an EXISTS clause for the dataset.
-
#expression_list(expr, parenthesize = false) ⇒ Object
Formats a where clause.
-
#filter(*cond, &block) ⇒ Object
Returns a copy of the dataset with the given conditions imposed upon it.
-
#from(*source) ⇒ Object
Returns a copy of the dataset with the source changed.
-
#full_outer_join(table, expr) ⇒ Object
Returns an OUTER joined dataset.
-
#group(*columns) ⇒ Object
(also: #group_by)
Returns a copy of the dataset with the results grouped by the value of the given columns.
-
#having(*cond, &block) ⇒ Object
Returns a copy of the dataset with the having conditions changed.
-
#inner_join(table, expr) ⇒ Object
(also: #join)
Returns an INNER joined dataset.
-
#insert_multiple(array, &block) ⇒ Object
Inserts multiple values.
-
#insert_sql(*values) ⇒ Object
Formats an INSERT statement using the given values.
-
#intersect(dataset, all = false) ⇒ Object
Adds an INTERSECT clause using a second dataset object.
-
#invert_order(order) ⇒ Object
Inverts the given order by breaking it into a list of column references and inverting them.
-
#join_expr(type, table, expr) ⇒ Object
Returns a join clause based on the specified join type and condition.
-
#join_table(type, table, expr) ⇒ Object
Returns a joined dataset with the specified join type and condition.
-
#left_outer_join(table, expr) ⇒ Object
Returns a LEFT OUTER joined dataset.
-
#limit(l, o = nil) ⇒ Object
If given an integer, the dataset will contain only the first l results.
-
#literal(v) ⇒ Object
Returns a literal representation of a value to be used as part of an SQL expression.
-
#or(*cond, &block) ⇒ Object
Adds an alternate filter to an existing filter using OR.
-
#order(*order) ⇒ Object
(also: #order_by)
Returns a copy of the dataset with the order changed.
-
#qualified_column_name(column, table) ⇒ Object
Returns a qualified column name (including a table name) if the column name isn’t already qualified.
-
#quote_column_ref(name) ⇒ Object
Adds quoting to column references.
-
#reverse_order(*order) ⇒ Object
Returns a copy of the dataset with the order reversed.
-
#right_outer_join(table, expr) ⇒ Object
Returns a RIGHT OUTER joined dataset.
-
#select(*columns) ⇒ Object
Returns a copy of the dataset with the selected columns changed.
-
#select_sql(opts = nil) ⇒ Object
(also: #sql)
Formats a SELECT statement using the given options and the dataset options.
-
#source_list(source) ⇒ Object
Converts an array of sources names into into a comma separated list.
-
#to_table_reference(idx = nil) ⇒ Object
Returns a table reference for use in the FROM clause.
-
#union(dataset, all = false) ⇒ Object
Adds a UNION clause using a second dataset object.
-
#uniq(*args) ⇒ Object
(also: #distinct)
Returns a copy of the dataset with the distinct option.
-
#update_sql(values = {}, opts = nil, &block) ⇒ Object
Formats an UPDATE statement using the given values.
-
#where(*cond, &block) ⇒ Object
Returns a copy of the dataset with the where conditions changed.
Instance Method Details
#and(*cond, &block) ⇒ Object
Adds an further filter to an existing filter using AND. If no filter exists an error is raised. This method is identical to #filter except it expects an existing filter.
251 252 253 254 255 256 257 |
# File 'lib/sequel/dataset/sql.rb', line 251 def and(*cond, &block) clause = (@opts[:group] ? :having : :where) unless @opts[clause] raise Error::NoExistingFilter, "No existing filter found." end filter(*cond, &block) end |
#column_list(columns) ⇒ Object
Converts an array of column names into a comma seperated string of column names. If the array is empty, a wildcard (*) is returned.
34 35 36 37 38 39 40 41 42 43 |
# File 'lib/sequel/dataset/sql.rb', line 34 def column_list(columns) if columns.empty? WILDCARD else m = columns.map do |i| i.is_a?(Hash) ? i.map {|kv| "#{literal(kv[0])} AS #{kv[1]}"} : literal(i) end m.join(COMMA_SEPARATOR) end end |
#count ⇒ Object
Returns the number of records in the dataset.
577 578 579 580 581 582 583 |
# File 'lib/sequel/dataset/sql.rb', line 577 def count opts = @opts[:sql] ? \ {:sql => "SELECT COUNT(*) FROM (#{@opts[:sql]}) AS c", :order => nil} : \ STOCK_COUNT_OPTS single_value(opts).to_i end |
#delete_sql(opts = nil) ⇒ Object
Formats a DELETE statement using the given options and dataset options.
dataset.filter {price >= 100}.delete_sql #=>
"DELETE FROM items WHERE (price >= 100)"
524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 |
# File 'lib/sequel/dataset/sql.rb', line 524 def delete_sql(opts = nil) opts = opts ? @opts.merge(opts) : @opts if opts[:group] raise Error::InvalidOperation, "Grouped datasets cannot be deleted from" elsif opts[:from].is_a?(Array) && opts[:from].size > 1 raise Error::InvalidOperation, "Joined datasets cannot be deleted from" end sql = "DELETE FROM #{opts[:from]}" if where = opts[:where] sql << " WHERE #{where}" end sql end |
#except(dataset, all = false) ⇒ Object
Adds an EXCEPT clause using a second dataset object. If all is true the clause used is EXCEPT ALL, which may return duplicate rows.
311 312 313 |
# File 'lib/sequel/dataset/sql.rb', line 311 def except(dataset, all = false) clone_merge(:except => dataset, :except_all => all) end |
#exclude(*cond, &block) ⇒ Object
Performs the inverse of Dataset#filter.
dataset.exclude(:category => 'software').sql #=>
"SELECT * FROM items WHERE NOT (category = 'software')"
263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/sequel/dataset/sql.rb', line 263 def exclude(*cond, &block) clause = (@opts[:group] ? :having : :where) cond = cond.first if cond.size == 1 parenthesize = !(cond.is_a?(Hash) || cond.is_a?(Array)) if @opts[clause] l = expression_list(@opts[clause]) r = expression_list(block || cond, parenthesize) cond = "#{l} AND (NOT #{r})" else cond = "(NOT #{expression_list(block || cond, true)})" end clone_merge(clause => cond) end |
#exists(opts = nil) ⇒ Object
Returns an EXISTS clause for the dataset.
dataset.exists #=> "EXISTS (SELECT 1 FROM items)"
556 557 558 |
# File 'lib/sequel/dataset/sql.rb', line 556 def exists(opts = nil) "EXISTS (#{sql({:select => [1]}.merge(opts || {}))})" end |
#expression_list(expr, parenthesize = false) ⇒ Object
Formats a where clause. If parenthesize is true, then the whole generated clause will be enclosed in a set of parentheses.
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/sequel/dataset/sql.rb', line 123 def expression_list(expr, parenthesize = false) case expr when Hash parenthesize = false if expr.size == 1 fmt = expr.map {|i| compare_expr(i[0], i[1])}.join(AND_SEPARATOR) when Array fmt = expr.shift.gsub(QUESTION_MARK) {literal(expr.shift)} when Proc fmt = proc_to_sql(expr) else # if the expression is compound, it should be parenthesized in order for # things to be predictable (when using #or and #and.) parenthesize |= expr =~ /\).+\(/ fmt = expr end parenthesize ? "(#{fmt})" : fmt end |
#filter(*cond, &block) ⇒ Object
Returns a copy of the dataset with the given conditions imposed upon it.
If the query has been grouped, then the conditions are imposed in the HAVING clause. If not, then they are imposed in the WHERE clause. Filter accepts a Hash (formated into a list of equality expressions), an Array (formatted ala ActiveRecord conditions), a String (taken literally), or a block that is converted into expressions.
dataset.filter(:id => 3).sql #=>
"SELECT * FROM items WHERE (id = 3)"
dataset.filter('price < ?', 100).sql #=>
"SELECT * FROM items WHERE price < 100"
dataset.filter('price < 100').sql #=>
"SELECT * FROM items WHERE price < 100"
dataset.filter {price < 100}.sql #=>
"SELECT * FROM items WHERE (price < 100)"
Multiple filter calls can be chained for scoping:
software = dataset.filter(:category => 'software')
software.filter {price < 100}.sql #=>
"SELECT * FROM items WHERE (category = 'software') AND (price < 100)"
216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 |
# File 'lib/sequel/dataset/sql.rb', line 216 def filter(*cond, &block) clause = (@opts[:group] ? :having : :where) cond = cond.first if cond.size == 1 if cond === true || cond === false raise Error::InvalidFilter, "Invalid filter specified. Did you mean to supply a block?" end parenthesize = !(cond.is_a?(Hash) || cond.is_a?(Array)) filter = cond.is_a?(Hash) && cond if @opts[clause] l = expression_list(@opts[clause]) r = expression_list(block || cond, parenthesize) clone_merge(clause => "#{l} AND #{r}") else clone_merge(:filter => cond, clause => expression_list(block || cond)) end end |
#from(*source) ⇒ Object
Returns a copy of the dataset with the source changed.
142 143 144 |
# File 'lib/sequel/dataset/sql.rb', line 142 def from(*source) clone_merge(:from => source) end |
#full_outer_join(table, expr) ⇒ Object
Returns an OUTER joined dataset.
355 |
# File 'lib/sequel/dataset/sql.rb', line 355 def full_outer_join(table, expr); join_table(:full_outer, table, expr); end |
#group(*columns) ⇒ Object Also known as: group_by
Returns a copy of the dataset with the results grouped by the value of the given columns
189 190 191 |
# File 'lib/sequel/dataset/sql.rb', line 189 def group(*columns) clone_merge(:group => columns) end |
#having(*cond, &block) ⇒ Object
Returns a copy of the dataset with the having conditions changed. Raises if the dataset has not been grouped. See also #filter
289 290 291 292 293 294 295 |
# File 'lib/sequel/dataset/sql.rb', line 289 def having(*cond, &block) unless @opts[:group] raise Error, "Can only specify a HAVING clause on a grouped dataset" else filter(*cond, &block) end end |
#inner_join(table, expr) ⇒ Object Also known as: join
Returns an INNER joined dataset.
358 |
# File 'lib/sequel/dataset/sql.rb', line 358 def inner_join(table, expr); join_table(:inner, table, expr); end |
#insert_multiple(array, &block) ⇒ Object
Inserts multiple values. If a block is given it is invoked for each item in the given array before inserting it.
363 364 365 366 367 368 369 |
# File 'lib/sequel/dataset/sql.rb', line 363 def insert_multiple(array, &block) if block array.each {|i| insert(block[i])} else array.each {|i| insert(i)} end end |
#insert_sql(*values) ⇒ Object
Formats an INSERT statement using the given values. If a hash is given, the resulting statement includes column names. If no values are given, the resulting statement includes a DEFAULT VALUES clause.
dataset.insert_sql() #=> 'INSERT INTO items DEFAULT VALUES'
dataset.insert_sql(1,2,3) #=> 'INSERT INTO items VALUES (1, 2, 3)'
dataset.insert_sql(:a => 1, :b => 2) #=>
'INSERT INTO items (a, b) VALUES (1, 2)'
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 |
# File 'lib/sequel/dataset/sql.rb', line 444 def insert_sql(*values) if values.empty? "INSERT INTO #{@opts[:from]} DEFAULT VALUES" else values = values[0] if values.size == 1 case values when Sequel::Model insert_sql(values.values) when Array if values.empty? "INSERT INTO #{@opts[:from]} DEFAULT VALUES" elsif values.keys fl = values.keys.map {|f| literal(f.to_sym)} vl = @transform ? transform_save(values.values) : values.values vl.map! {|v| literal(v)} "INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})" else "INSERT INTO #{@opts[:from]} VALUES (#{literal(values)})" end when Hash values = transform_save(values) if @transform if values.empty? "INSERT INTO #{@opts[:from]} DEFAULT VALUES" else fl, vl = [], [] values.each {|k, v| fl << literal(k.to_sym); vl << literal(v)} "INSERT INTO #{@opts[:from]} (#{fl.join(COMMA_SEPARATOR)}) VALUES (#{vl.join(COMMA_SEPARATOR)})" end when Dataset "INSERT INTO #{@opts[:from]} #{literal(values)}" else "INSERT INTO #{@opts[:from]} VALUES (#{literal(values)})" end end end |
#intersect(dataset, all = false) ⇒ Object
Adds an INTERSECT clause using a second dataset object. If all is true the clause used is INTERSECT ALL, which may return duplicate rows.
305 306 307 |
# File 'lib/sequel/dataset/sql.rb', line 305 def intersect(dataset, all = false) clone_merge(:intersect => dataset, :intersect_all => all) end |
#invert_order(order) ⇒ Object
Inverts the given order by breaking it into a list of column references and inverting them.
dataset.invert_order([:id.desc]]) #=> [:id]
dataset.invert_order(:category, :price.desc]) #=>
[:category.desc, :price]
176 177 178 179 180 181 182 183 184 185 |
# File 'lib/sequel/dataset/sql.rb', line 176 def invert_order(order) new_order = [] order.map do |f| if f.is_a?(Sequel::SQL::ColumnExpr) && (f.op == Sequel::SQL::ColumnMethods::DESC) f.l else f.desc end end end |
#join_expr(type, table, expr) ⇒ Object
Returns a join clause based on the specified join type and condition.
323 324 325 326 327 328 329 330 331 332 333 334 335 336 |
# File 'lib/sequel/dataset/sql.rb', line 323 def join_expr(type, table, expr) join_type = JOIN_TYPES[type || :inner] unless join_type raise Error::InvalidJoinType, "Invalid join type: #{type}" end join_conditions = {} expr.each do |k, v| k = qualified_column_name(k, table) if k.is_a?(Symbol) v = qualified_column_name(v, @opts[:last_joined_table] || @opts[:from].first) if v.is_a?(Symbol) join_conditions[k] = v end " #{join_type} #{table} ON #{expression_list(join_conditions)}" end |
#join_table(type, table, expr) ⇒ Object
Returns a joined dataset with the specified join type and condition.
339 340 341 342 343 344 345 346 |
# File 'lib/sequel/dataset/sql.rb', line 339 def join_table(type, table, expr) unless expr.is_a?(Hash) expr = {expr => :id} end clause = join_expr(type, table, expr) join = @opts[:join] ? @opts[:join] + clause : clause clone_merge(:join => join, :last_joined_table => table) end |
#left_outer_join(table, expr) ⇒ Object
Returns a LEFT OUTER joined dataset.
349 |
# File 'lib/sequel/dataset/sql.rb', line 349 def left_outer_join(table, expr); join_table(:left_outer, table, expr); end |
#limit(l, o = nil) ⇒ Object
If given an integer, the dataset will contain only the first l results. If given a range, it will contain only those at offsets within that range. If a second argument is given, it is used as an offset.
563 564 565 566 567 568 569 570 571 572 |
# File 'lib/sequel/dataset/sql.rb', line 563 def limit(l, o = nil) if l.is_a? Range lim = (l.exclude_end? ? l.last - l.first : l.last + 1 - l.first) clone_merge(:limit => lim, :offset=>l.first) elsif o clone_merge(:limit => l, :offset => o) else clone_merge(:limit => l) end end |
#literal(v) ⇒ Object
Returns a literal representation of a value to be used as part of an SQL expression. The stock implementation supports literalization of String (with proper escaping to prevent SQL injections), numbers, Symbol (as column references), Array (as a list of literalized values), Time (as an SQL TIMESTAMP), Date (as an SQL DATE), Dataset (as a subquery) and nil (AS NULL).
dataset.literal("abc'def") #=> "'abc''def'"
dataset.literal(:items__id) #=> "items.id"
dataset.literal([1, 2, 3]) => "(1, 2, 3)"
dataset.literal(DB[:items]) => "(SELECT * FROM items)"
If an unsupported object is given, an exception is raised.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/sequel/dataset/sql.rb', line 85 def literal(v) case v when LiteralString v when String "'#{v.gsub(/'/, "''")}'" when Integer, Float v.to_s when BigDecimal v.to_s("F") when NilClass NULL when TrueClass TRUE when FalseClass FALSE when Symbol v.to_column_ref(self) when Sequel::SQL::Expression v.to_s(self) when Array v.empty? ? NULL : v.map {|i| literal(i)}.join(COMMA_SEPARATOR) when Time v.strftime(TIMESTAMP_FORMAT) when Date v.strftime(DATE_FORMAT) when Dataset "(#{v.sql})" else raise Error, "can't express #{v.inspect} as a SQL literal" end end |
#or(*cond, &block) ⇒ Object
Adds an alternate filter to an existing filter using OR. If no filter exists an error is raised.
235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/sequel/dataset/sql.rb', line 235 def or(*cond, &block) clause = (@opts[:group] ? :having : :where) cond = cond.first if cond.size == 1 parenthesize = !(cond.is_a?(Hash) || cond.is_a?(Array)) if @opts[clause] l = expression_list(@opts[clause]) r = expression_list(block || cond, parenthesize) clone_merge(clause => "#{l} OR #{r}") else raise Error::NoExistingFilter, "No existing filter found." end end |
#order(*order) ⇒ Object Also known as: order_by
Returns a copy of the dataset with the order changed.
158 159 160 |
# File 'lib/sequel/dataset/sql.rb', line 158 def order(*order) clone_merge(:order => order) end |
#qualified_column_name(column, table) ⇒ Object
Returns a qualified column name (including a table name) if the column name isn’t already qualified.
16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/sequel/dataset/sql.rb', line 16 def qualified_column_name(column, table) s = literal(column) if s =~ QUALIFIED_REGEXP return column else if (table =~ ALIASED_REGEXP) table = $2 end Sequel::SQL::QualifiedColumnRef.new(table, column) # "#{table}.#{column}" end end |
#quote_column_ref(name) ⇒ Object
Adds quoting to column references. This method is just a stub and can be overriden in adapters in order to provide correct column quoting behavior.
9 |
# File 'lib/sequel/dataset/sql.rb', line 9 def quote_column_ref(name); name.to_s; end |
#reverse_order(*order) ⇒ Object
Returns a copy of the dataset with the order reversed. If no order is given, the existing order is inverted.
166 167 168 |
# File 'lib/sequel/dataset/sql.rb', line 166 def reverse_order(*order) order(*invert_order(order.empty? ? @opts[:order] : order)) end |
#right_outer_join(table, expr) ⇒ Object
Returns a RIGHT OUTER joined dataset.
352 |
# File 'lib/sequel/dataset/sql.rb', line 352 def right_outer_join(table, expr); join_table(:right_outer, table, expr); end |
#select(*columns) ⇒ Object
Returns a copy of the dataset with the selected columns changed.
147 148 149 |
# File 'lib/sequel/dataset/sql.rb', line 147 def select(*columns) clone_merge(:select => columns) end |
#select_sql(opts = nil) ⇒ Object Also known as: sql
Formats a SELECT statement using the given options and the dataset options.
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'lib/sequel/dataset/sql.rb', line 373 def select_sql(opts = nil) opts = opts ? @opts.merge(opts) : @opts if sql = opts[:sql] return sql end columns = opts[:select] select_columns = columns ? column_list(columns) : WILDCARD if distinct = opts[:distinct] distinct_clause = distinct.empty? ? "DISTINCT" : "DISTINCT ON (#{column_list(distinct)})" sql = "SELECT #{distinct_clause} #{select_columns}" else sql = "SELECT #{select_columns}" end if opts[:from] sql << " FROM #{source_list(opts[:from])}" end if join = opts[:join] sql << join end if where = opts[:where] sql << " WHERE #{where}" end if group = opts[:group] sql << " GROUP BY #{column_list(group)}" end if order = opts[:order] sql << " ORDER BY #{column_list(order)}" end if having = opts[:having] sql << " HAVING #{having}" end if limit = opts[:limit] sql << " LIMIT #{limit}" if offset = opts[:offset] sql << " OFFSET #{offset}" end end if union = opts[:union] sql << (opts[:union_all] ? \ " UNION ALL #{union.sql}" : " UNION #{union.sql}") elsif intersect = opts[:intersect] sql << (opts[:intersect_all] ? \ " INTERSECT ALL #{intersect.sql}" : " INTERSECT #{intersect.sql}") elsif except = opts[:except] sql << (opts[:except_all] ? \ " EXCEPT ALL #{except.sql}" : " EXCEPT #{except.sql}") end sql end |
#source_list(source) ⇒ Object
Converts an array of sources names into into a comma separated list.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/sequel/dataset/sql.rb', line 46 def source_list(source) if source.nil? || source.empty? raise Error, 'No source specified for query' end auto_alias_count = 0 m = source.map do |i| case i when Dataset auto_alias_count += 1 i.to_table_reference(auto_alias_count) when Hash i.map {|k, v| "#{k.is_a?(Dataset) ? k.to_table_reference : k} #{v}"}. join(COMMA_SEPARATOR) else i end end m.join(COMMA_SEPARATOR) end |
#to_table_reference(idx = nil) ⇒ Object
Returns a table reference for use in the FROM clause. If the dataset has only a :from option refering to a single table, only the table name is returned. Otherwise a subquery is returned.
545 546 547 548 549 550 551 |
# File 'lib/sequel/dataset/sql.rb', line 545 def to_table_reference(idx = nil) if opts.keys == [:from] && opts[:from].size == 1 opts[:from].first.to_s else idx ? "(#{sql}) t#{idx}" : "(#{sql})" end end |
#union(dataset, all = false) ⇒ Object
Adds a UNION clause using a second dataset object. If all is true the clause used is UNION ALL, which may return duplicate rows.
299 300 301 |
# File 'lib/sequel/dataset/sql.rb', line 299 def union(dataset, all = false) clone_merge(:union => dataset, :union_all => all) end |
#uniq(*args) ⇒ Object Also known as: distinct
Returns a copy of the dataset with the distinct option.
152 153 154 |
# File 'lib/sequel/dataset/sql.rb', line 152 def uniq(*args) clone_merge(:distinct => args) end |
#update_sql(values = {}, opts = nil, &block) ⇒ Object
Formats an UPDATE statement using the given values.
dataset.update_sql(:price => 100, :category => 'software') #=>
"UPDATE items SET price = 100, category = 'software'"
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 |
# File 'lib/sequel/dataset/sql.rb', line 484 def update_sql(values = {}, opts = nil, &block) opts = opts ? @opts.merge(opts) : @opts if opts[:group] raise Error::InvalidOperation, "A grouped dataset cannot be updated" elsif (opts[:from].size > 1) or opts[:join] raise Error::InvalidOperation, "A joined dataset cannot be updated" end sql = "UPDATE #{@opts[:from]} SET " if block sql << proc_to_sql(block, :comma_separated => true) else # check if array with keys values = values.to_hash if values.is_a?(Array) && values.keys if values.is_a?(Hash) # get values from hash values = transform_save(values) if @transform set = values.map do |k, v| # convert string key into symbol k = k.to_sym if String === k "#{literal(k)} = #{literal(v)}" end.join(COMMA_SEPARATOR) else # copy values verbatim set = values end sql << set end if where = opts[:where] sql << " WHERE #{where}" end sql end |
#where(*cond, &block) ⇒ Object
Returns a copy of the dataset with the where conditions changed. Raises if the dataset has been grouped. See also #filter.
279 280 281 282 283 284 285 |
# File 'lib/sequel/dataset/sql.rb', line 279 def where(*cond, &block) if @opts[:group] raise Error, "Can't specify a WHERE clause once the dataset has been grouped" else filter(*cond, &block) end end |