Methods
Public Instance
- complex_expression_sql_append
- constant_sql_append
- count
- cross_apply
- disable_insert_output
- empty?
- escape_like
- full_text_search
- insert_select
- insert_select_sql
- into
- mssql_unicode_strings
- nolock
- outer_apply
- output
- quoted_identifier_append
- returning
- select_sql
- server_version
- supports_cte?
- supports_group_cube?
- supports_group_rollup?
- supports_grouping_sets?
- supports_insert_select?
- supports_intersect_except?
- supports_is_true?
- supports_join_using?
- supports_merge?
- supports_modifying_joins?
- supports_multiple_column_in?
- supports_nowait?
- supports_offsets_in_correlated_subqueries?
- supports_output_clause?
- supports_returning?
- supports_skip_locked?
- supports_where_true?
- supports_window_functions?
- with_mssql_unicode_strings
- with_ties
Protected Instance
Included modules
Constants
| CONSTANT_MAP | = | {:CURRENT_DATE=>'CAST(CURRENT_TIMESTAMP AS DATE)'.freeze, :CURRENT_TIME=>'CAST(CURRENT_TIMESTAMP AS TIME)'.freeze}.freeze | ||
| EXTRACT_MAP | = | {:year=>"yy", :month=>"m", :day=>"d", :hour=>"hh", :minute=>"n", :second=>"s"}.freeze | ||
| LIMIT_ALL | = | Object.new.freeze |
Public Instance methods
# File lib/sequel/adapters/shared/mssql.rb 604 def complex_expression_sql_append(sql, op, args) 605 case op 606 when :'||' 607 super(sql, :+, args) 608 when :LIKE, :"NOT LIKE" 609 super(sql, op, complex_expression_sql_like_args(args, " COLLATE Latin1_General_CS_AS)")) 610 when :ILIKE, :"NOT ILIKE" 611 super(sql, (op == :ILIKE ? :LIKE : :"NOT LIKE"), complex_expression_sql_like_args(args, " COLLATE Latin1_General_CI_AS)")) 612 when :<<, :>> 613 complex_expression_emulate_append(sql, op, args) 614 when :extract 615 part = args[0] 616 raise(Sequel::Error, "unsupported extract argument: #{part.inspect}") unless format = EXTRACT_MAP[part] 617 if part == :second 618 expr = args[1] 619 sql << "CAST((datepart(" << format.to_s << ', ' 620 literal_append(sql, expr) 621 sql << ') + datepart(ns, ' 622 literal_append(sql, expr) 623 sql << ")/1000000000.0) AS double precision)" 624 else 625 sql << "datepart(" << format.to_s << ', ' 626 literal_append(sql, args[1]) 627 sql << ')' 628 end 629 else 630 super 631 end 632 end
MSSQL doesn’t support the SQL standard CURRENT_DATE or CURRENT_TIME
# File lib/sequel/adapters/shared/mssql.rb 635 def constant_sql_append(sql, constant) 636 if c = CONSTANT_MAP[constant] 637 sql << c 638 else 639 super 640 end 641 end
For a dataset with custom SQL, since it may include ORDER BY, you cannot wrap it in a subquery. Load entire query in this case to get the number of rows. In general, you should avoid calling this method on datasets with custom SQL.
# File lib/sequel/adapters/shared/mssql.rb 647 def count(*a, &block) 648 if (@opts[:sql] && a.empty? && !block) 649 naked.to_a.length 650 else 651 super 652 end 653 end
Uses CROSS APPLY to join the given table into the current dataset.
# File lib/sequel/adapters/shared/mssql.rb 656 def cross_apply(table) 657 join_table(:cross_apply, table) 658 end
Disable the use of INSERT OUTPUT
# File lib/sequel/adapters/shared/mssql.rb 661 def disable_insert_output 662 clone(:disable_insert_output=>true) 663 end
For a dataset with custom SQL, since it may include ORDER BY, you cannot wrap it in a subquery. Run query, and if it returns any records, return true. In general, you should avoid calling this method on datasets with custom SQL.
# File lib/sequel/adapters/shared/mssql.rb 669 def empty? 670 if @opts[:sql] 671 naked.each{return false} 672 true 673 else 674 super 675 end 676 end
MSSQL treats [] as a metacharacter in LIKE expressions.
# File lib/sequel/adapters/shared/mssql.rb 679 def escape_like(string) 680 string.gsub(/[\\%_\[\]]/){|m| "\\#{m}"} 681 end
MSSQL uses the CONTAINS keyword for full text search
# File lib/sequel/adapters/shared/mssql.rb 684 def full_text_search(cols, terms, opts = OPTS) 685 case terms 686 when Array, Set 687 terms = Sequel.array_or_set_join(terms.map{|term| "\"#{term.to_s.gsub('"', '""')}\""}, " OR ") 688 end 689 where(Sequel.lit("CONTAINS (?, ?)", cols, terms)) 690 end
Insert a record, returning the record inserted, using OUTPUT. Always returns nil without running an INSERT statement if disable_insert_output is used. If the query runs but returns no values, returns false.
# File lib/sequel/adapters/shared/mssql.rb 695 def insert_select(*values) 696 return unless supports_insert_select? 697 with_sql_first(insert_select_sql(*values)) || false 698 end
Add OUTPUT clause unless there is already an existing output clause, then return the SQL to insert.
# File lib/sequel/adapters/shared/mssql.rb 702 def insert_select_sql(*values) 703 ds = (opts[:output] || opts[:returning]) ? self : output(nil, [SQL::ColumnAll.new(:inserted)]) 704 ds.insert_sql(*values) 705 end
Specify a table for a SELECT … INTO query.
# File lib/sequel/adapters/shared/mssql.rb 708 def into(table) 709 clone(:into => table) 710 end
Use the database’s mssql_unicode_strings setting if the dataset hasn’t overridden it.
# File lib/sequel/adapters/shared/mssql.rb 595 def mssql_unicode_strings 596 opts.has_key?(:mssql_unicode_strings) ? opts[:mssql_unicode_strings] : db.mssql_unicode_strings 597 end
Allows you to do a dirty read of uncommitted data using WITH (NOLOCK).
# File lib/sequel/adapters/shared/mssql.rb 713 def nolock 714 cached_lock_style_dataset(:_nolock_ds, :dirty) 715 end
Uses OUTER APPLY to join the given table into the current dataset.
# File lib/sequel/adapters/shared/mssql.rb 718 def outer_apply(table) 719 join_table(:outer_apply, table) 720 end
Include an OUTPUT clause in the eventual INSERT, UPDATE, or DELETE query.
The first argument is the table to output into, and the second argument is either an Array of column values to select, or a Hash which maps output column names to selected values, in the style of insert or update.
Output into a returned result set is not currently supported.
Examples:
dataset.output(:output_table, [Sequel[:deleted][:id], Sequel[:deleted][:name]]) dataset.output(:output_table, id: Sequel[:inserted][:id], name: Sequel[:inserted][:name])
# File lib/sequel/adapters/shared/mssql.rb 734 def output(into, values) 735 raise(Error, "SQL Server versions 2000 and earlier do not support the OUTPUT clause") unless supports_output_clause? 736 output = {} 737 case values 738 when Hash 739 output[:column_list], output[:select_list] = values.keys, values.values 740 when Array 741 output[:select_list] = values 742 end 743 output[:into] = into 744 clone(:output => output) 745 end
MSSQL uses [] to quote identifiers.
# File lib/sequel/adapters/shared/mssql.rb 748 def quoted_identifier_append(sql, name) 749 sql << '[' << name.to_s.gsub(/\]/, ']]') << ']' 750 end
Emulate RETURNING using the output clause. This only handles values that are simple column references.
# File lib/sequel/adapters/shared/mssql.rb 753 def returning(*values) 754 values = values.map do |v| 755 unless r = unqualified_column_for(v) 756 raise(Error, "cannot emulate RETURNING via OUTPUT for value: #{v.inspect}") 757 end 758 r 759 end 760 clone(:returning=>values) 761 end
On MSSQL 2012+ add a default order to the current dataset if an offset is used. The default offset emulation using a subquery would be used in the unordered case by default, and that also adds a default order, so it’s better to just avoid the subquery.
# File lib/sequel/adapters/shared/mssql.rb 767 def select_sql 768 if @opts[:offset] 769 raise(Error, "Using with_ties is not supported with an offset on Microsoft SQL Server") if @opts[:limit_with_ties] 770 return order(1).select_sql if is_2012_or_later? && !@opts[:order] 771 end 772 super 773 end
The version of the database server.
# File lib/sequel/adapters/shared/mssql.rb 776 def server_version 777 db.server_version(@opts[:server]) 778 end
# File lib/sequel/adapters/shared/mssql.rb 780 def supports_cte?(type=:select) 781 is_2005_or_later? 782 end
MSSQL 2005+ supports GROUP BY CUBE.
# File lib/sequel/adapters/shared/mssql.rb 785 def supports_group_cube? 786 is_2005_or_later? 787 end
MSSQL 2005+ supports GROUP BY ROLLUP
# File lib/sequel/adapters/shared/mssql.rb 790 def supports_group_rollup? 791 is_2005_or_later? 792 end
MSSQL 2008+ supports GROUPING SETS
# File lib/sequel/adapters/shared/mssql.rb 795 def supports_grouping_sets? 796 is_2008_or_later? 797 end
MSSQL supports insert_select via the OUTPUT clause.
# File lib/sequel/adapters/shared/mssql.rb 800 def supports_insert_select? 801 supports_output_clause? && !opts[:disable_insert_output] 802 end
MSSQL 2005+ supports INTERSECT and EXCEPT
# File lib/sequel/adapters/shared/mssql.rb 805 def supports_intersect_except? 806 is_2005_or_later? 807 end
MSSQL does not support IS TRUE
# File lib/sequel/adapters/shared/mssql.rb 810 def supports_is_true? 811 false 812 end
MSSQL doesn’t support JOIN USING
# File lib/sequel/adapters/shared/mssql.rb 815 def supports_join_using? 816 false 817 end
MSSQL 2008+ supports MERGE
# File lib/sequel/adapters/shared/mssql.rb 820 def supports_merge? 821 is_2008_or_later? 822 end
MSSQL 2005+ supports modifying joined datasets
# File lib/sequel/adapters/shared/mssql.rb 825 def supports_modifying_joins? 826 is_2005_or_later? 827 end
MSSQL does not support multiple columns for the IN/NOT IN operators
# File lib/sequel/adapters/shared/mssql.rb 830 def supports_multiple_column_in? 831 false 832 end
MSSQL supports NOWAIT.
# File lib/sequel/adapters/shared/mssql.rb 835 def supports_nowait? 836 true 837 end
MSSQL 2005+ supports the OUTPUT clause.
# File lib/sequel/adapters/shared/mssql.rb 845 def supports_output_clause? 846 is_2005_or_later? 847 end
MSSQL 2005+ can emulate RETURNING via the OUTPUT clause.
# File lib/sequel/adapters/shared/mssql.rb 850 def supports_returning?(type) 851 supports_insert_select? 852 end
MSSQL uses READPAST to skip locked rows.
# File lib/sequel/adapters/shared/mssql.rb 855 def supports_skip_locked? 856 true 857 end
MSSQL cannot use WHERE 1.
# File lib/sequel/adapters/shared/mssql.rb 865 def supports_where_true? 866 false 867 end
MSSQL 2005+ supports window functions
# File lib/sequel/adapters/shared/mssql.rb 860 def supports_window_functions? 861 true 862 end
Return a cloned dataset with the mssql_unicode_strings option set.
# File lib/sequel/adapters/shared/mssql.rb 600 def with_mssql_unicode_strings(v) 601 clone(:mssql_unicode_strings=>v) 602 end
Use WITH TIES when limiting the result set to also include additional rows matching the last row.
# File lib/sequel/adapters/shared/mssql.rb 871 def with_ties 872 clone(:limit_with_ties=>true) 873 end
Protected Instance methods
If returned primary keys are requested, use OUTPUT unless already set on the dataset. If OUTPUT is already set, use existing returning values. If OUTPUT is only set to return a single columns, return an array of just that column. Otherwise, return an array of hashes.
# File lib/sequel/adapters/shared/mssql.rb 881 def _import(columns, values, opts=OPTS) 882 if opts[:return] == :primary_key && !@opts[:output] 883 output(nil, [SQL::QualifiedIdentifier.new(:inserted, first_primary_key)])._import(columns, values, opts) 884 elsif @opts[:output] 885 # no transaction: our multi_insert_sql_strategy should guarantee 886 # that there's only ever a single statement. 887 sql = multi_insert_sql(columns, values)[0].freeze 888 naked.with_sql(sql).map{|v| v.length == 1 ? v.values.first : v} 889 else 890 super 891 end 892 end
If the dataset using a order without a limit or offset or custom SQL, remove the order. Compounds on Microsoft SQL Server have undefined order unless the result is specifically ordered. Applying the current order before the compound doesn’t work in all cases, such as when qualified identifiers are used. If you want to ensure a order for a compound dataset, apply the order after all compounds have been added.
# File lib/sequel/adapters/shared/mssql.rb 901 def compound_from_self 902 if @opts[:offset] && !@opts[:limit] && !is_2012_or_later? 903 clone(:limit=>LIMIT_ALL).from_self 904 elsif @opts[:order] && !(@opts[:sql] || @opts[:limit] || @opts[:offset]) 905 unordered 906 else 907 super 908 end 909 end