/usr/lib/ruby/vendor_ruby/sequel/dataset/misc.rb is in ruby-sequel 4.15.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 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 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 | module Sequel
class Dataset
# ---------------------
# :section: 6 - Miscellaneous methods
# These methods don't fit cleanly into another section.
# ---------------------
NOTIMPL_MSG = "This method must be overridden in Sequel adapters".freeze
ARRAY_ACCESS_ERROR_MSG = 'You cannot call Dataset#[] with an integer or with no arguments.'.freeze
ARG_BLOCK_ERROR_MSG = 'Must use either an argument or a block, not both'.freeze
IMPORT_ERROR_MSG = 'Using Sequel::Dataset#import an empty column array is not allowed'.freeze
# The database related to this dataset. This is the Database instance that
# will execute all of this dataset's queries.
attr_reader :db
# The hash of options for this dataset, keys are symbols.
attr_reader :opts
# Constructs a new Dataset instance with an associated database and
# options. Datasets are usually constructed by invoking the Database#[] method:
#
# DB[:posts]
#
# Sequel::Dataset is an abstract class that is not useful by itself. Each
# database adapter provides a subclass of Sequel::Dataset, and has
# the Database#dataset method return an instance of that subclass.
def initialize(db)
@db = db
@opts = OPTS
end
# Define a hash value such that datasets with the same DB, opts, and SQL
# will be considered equal.
def ==(o)
o.is_a?(self.class) && db == o.db && opts == o.opts && sql == o.sql
end
# An object representing the current date or time, should be an instance
# of Sequel.datetime_class.
def current_datetime
Sequel.datetime_class.now
end
# Alias for ==
def eql?(o)
self == o
end
# Similar to #clone, but returns an unfrozen clone if the receiver is frozen.
def dup
o = clone
o.opts.delete(:frozen)
o
end
# Yield a dataset for each server in the connection pool that is tied to that server.
# Intended for use in sharded environments where all servers need to be modified
# with the same data:
#
# DB[:configs].where(:key=>'setting').each_server{|ds| ds.update(:value=>'new_value')}
def each_server
db.servers.each{|s| yield server(s)}
end
# Returns the string with the LIKE metacharacters (% and _) escaped.
# Useful for when the LIKE term is a user-provided string where metacharacters should not
# be recognized. Example:
#
# ds.escape_like("foo\\%_") # 'foo\\\%\_'
def escape_like(string)
string.gsub(/[\\%_]/){|m| "\\#{m}"}
end
# Sets the frozen flag on the dataset, so you can't modify it. Returns the receiver.
def freeze
@opts[:frozen] = true
self
end
# Whether the object is frozen.
def frozen?
@opts[:frozen]
end
# Alias of +first_source_alias+
def first_source
first_source_alias
end
# The first source (primary table) for this dataset. If the dataset doesn't
# have a table, raises an +Error+. If the table is aliased, returns the aliased name.
#
# DB[:table].first_source_alias
# # => :table
#
# DB[:table___t].first_source_alias
# # => :t
def first_source_alias
source = @opts[:from]
if source.nil? || source.empty?
raise Error, 'No source specified for query'
end
case s = source.first
when SQL::AliasedExpression
s.alias
when Symbol
_, _, aliaz = split_symbol(s)
aliaz ? aliaz.to_sym : s
else
s
end
end
# The first source (primary table) for this dataset. If the dataset doesn't
# have a table, raises an error. If the table is aliased, returns the original
# table, not the alias
#
# DB[:table].first_source_table
# # => :table
#
# DB[:table___t].first_source_table
# # => :table
def first_source_table
source = @opts[:from]
if source.nil? || source.empty?
raise Error, 'No source specified for query'
end
case s = source.first
when SQL::AliasedExpression
s.expression
when Symbol
sch, table, aliaz = split_symbol(s)
aliaz ? (sch ? SQL::QualifiedIdentifier.new(sch, table) : table.to_sym) : s
else
s
end
end
# Define a hash value such that datasets with the same DB, opts, and SQL
# will have the same hash value
def hash
[db, opts, sql].hash
end
# The String instance method to call on identifiers before sending them to
# the database.
def identifier_input_method
if defined?(@identifier_input_method)
@identifier_input_method
else
@identifier_input_method = db.identifier_input_method
end
end
# The String instance method to call on identifiers before sending them to
# the database.
def identifier_output_method
if defined?(@identifier_output_method)
@identifier_output_method
else
@identifier_output_method = db.identifier_output_method
end
end
# Returns a string representation of the dataset including the class name
# and the corresponding SQL select statement.
def inspect
"#<#{visible_class_name}: #{sql.inspect}>"
end
# Whether this dataset is a joined dataset (multiple FROM tables or any JOINs).
def joined_dataset?
!!((opts[:from].is_a?(Array) && opts[:from].size > 1) || opts[:join])
end
# The alias to use for the row_number column, used when emulating OFFSET
# support and for eager limit strategies
def row_number_column
:x_sequel_row_number_x
end
# Splits a possible implicit alias in +c+, handling both SQL::AliasedExpressions
# and Symbols. Returns an array of two elements, with the first being the
# main expression, and the second being the alias.
def split_alias(c)
case c
when Symbol
c_table, column, aliaz = split_symbol(c)
[c_table ? SQL::QualifiedIdentifier.new(c_table, column.to_sym) : column.to_sym, aliaz]
when SQL::AliasedExpression
[c.expression, c.alias]
when SQL::JoinClause
[c.table, c.table_alias]
else
[c, nil]
end
end
# This returns an SQL::Identifier or SQL::AliasedExpression containing an
# SQL identifier that represents the unqualified column for the given value.
# The given value should be a Symbol, SQL::Identifier, SQL::QualifiedIdentifier,
# or SQL::AliasedExpression containing one of those. In other cases, this
# returns nil
def unqualified_column_for(v)
unless v.is_a?(String)
_unqualified_column_for(v)
end
end
# Creates a unique table alias that hasn't already been used in the dataset.
# table_alias can be any type of object accepted by alias_symbol.
# The symbol returned will be the implicit alias in the argument,
# possibly appended with "_N" if the implicit alias has already been
# used, where N is an integer starting at 0 and increasing until an
# unused one is found.
#
# You can provide a second addition array argument containing symbols
# that should not be considered valid table aliases. The current aliases
# for the FROM and JOIN tables are automatically included in this array.
#
# DB[:table].unused_table_alias(:t)
# # => :t
#
# DB[:table].unused_table_alias(:table)
# # => :table_0
#
# DB[:table, :table_0].unused_table_alias(:table)
# # => :table_1
#
# DB[:table, :table_0].unused_table_alias(:table, [:table_1, :table_2])
# # => :table_3
def unused_table_alias(table_alias, used_aliases = [])
table_alias = alias_symbol(table_alias)
used_aliases += opts[:from].map{|t| alias_symbol(t)} if opts[:from]
used_aliases += opts[:join].map{|j| j.table_alias ? alias_alias_symbol(j.table_alias) : alias_symbol(j.table)} if opts[:join]
if used_aliases.include?(table_alias)
i = 0
loop do
ta = :"#{table_alias}_#{i}"
return ta unless used_aliases.include?(ta)
i += 1
end
else
table_alias
end
end
private
# Internal recursive version of unqualified_column_for, handling Strings inside
# of other objects.
def _unqualified_column_for(v)
case v
when Symbol
_, c, a = Sequel.split_symbol(v)
c = Sequel.identifier(c)
a ? c.as(a) : c
when String
Sequel.identifier(v)
when SQL::Identifier
v
when SQL::QualifiedIdentifier
_unqualified_column_for(v.column)
when SQL::AliasedExpression
if expr = unqualified_column_for(v.expression)
SQL::AliasedExpression.new(expr, v.alias)
end
end
end
# Return the class name for this dataset, but skip anonymous classes
def visible_class_name
c = self.class
c = c.superclass while c.name.nil? || c.name == ''
c.name
end
end
end
|