/usr/lib/ruby/vendor_ruby/sequel/adapters/jdbc/derby.rb is in ruby-sequel 4.1.1-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 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 | Sequel.require 'adapters/jdbc/transactions'
module Sequel
module JDBC
# Database and Dataset support for Derby databases accessed via JDBC.
module Derby
# Instance methods for Derby Database objects accessed via JDBC.
module DatabaseMethods
extend Sequel::Database::ResetIdentifierMangling
PRIMARY_KEY_INDEX_RE = /\Asql\d+\z/i.freeze
include ::Sequel::JDBC::Transactions
# Derby doesn't support casting integer to varchar, only integer to char,
# and char(254) appears to have the widest support (with char(255) failing).
# This does add a bunch of extra spaces at the end, but those will be trimmed
# elsewhere.
def cast_type_literal(type)
(type == String) ? 'CHAR(254)' : super
end
# Derby uses the :derby database type.
def database_type
:derby
end
# Derby uses an IDENTITY sequence for autoincrementing columns.
def serial_primary_key_options
{:primary_key => true, :type => :integer, :identity=>true, :start_with=>1}
end
# The SVN version of the database.
def svn_version
@svn_version ||= begin
v = synchronize{|c| c.get_meta_data.get_database_product_version}
v =~ /\((\d+)\)\z/
$1.to_i
end
end
# Derby supports transaction DDL statements.
def supports_transactional_ddl?
true
end
private
# Derby optimizes away Sequel's default check of SELECT NULL FROM table,
# so use a SELECT * FROM table there.
def _table_exists?(ds)
ds.first
end
# Derby-specific syntax for renaming columns and changing a columns type/nullity.
def alter_table_sql(table, op)
case op[:op]
when :rename_column
"RENAME COLUMN #{quote_schema_table(table)}.#{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
when :set_column_type
# Derby is very limited in changing a columns type, so adding a new column and then dropping the existing column is
# the best approach, as mentioned in the Derby documentation.
temp_name = :x_sequel_temp_column_x
[alter_table_sql(table, op.merge(:op=>:add_column, :name=>temp_name)),
from(table).update_sql(temp_name=>::Sequel::SQL::Cast.new(op[:name], op[:type])),
alter_table_sql(table, op.merge(:op=>:drop_column)),
alter_table_sql(table, op.merge(:op=>:rename_column, :name=>temp_name, :new_name=>op[:name]))]
when :set_column_null
"ALTER TABLE #{quote_schema_table(table)} ALTER COLUMN #{quote_identifier(op[:name])} #{op[:null] ? 'NULL' : 'NOT NULL'}"
else
super
end
end
# Derby doesn't allow specifying NULL for columns, only NOT NULL.
def column_definition_null_sql(sql, column)
sql << " NOT NULL" if column.fetch(:null, column[:allow_null]) == false
end
# Add NOT LOGGED for temporary tables to improve performance.
def create_table_sql(name, generator, options)
s = super
s << ' NOT LOGGED' if options[:temp]
s
end
# Insert data from the current table into the new table after
# creating the table, since it is not possible to do it in one step.
def create_table_as(name, sql, options)
super
from(name).insert(sql.is_a?(Dataset) ? sql : dataset.with_sql(sql))
end
# Derby currently only requires WITH NO DATA, with a separate insert
# to import data.
def create_table_as_sql(name, sql, options)
"#{create_table_prefix_sql(name, options)} AS #{sql} WITH NO DATA"
end
# Temporary table creation on Derby uses DECLARE instead of CREATE.
def create_table_prefix_sql(name, options)
if options[:temp]
"DECLARE GLOBAL TEMPORARY TABLE #{quote_identifier(name)}"
else
super
end
end
DATABASE_ERROR_REGEXPS = {
/The statement was aborted because it would have caused a duplicate key value in a unique or primary key constraint or unique index/ => UniqueConstraintViolation,
/violation of foreign key constraint/ => ForeignKeyConstraintViolation,
/The check constraint .+ was violated/ => CheckConstraintViolation,
/cannot accept a NULL value/ => NotNullConstraintViolation,
/A lock could not be obtained due to a deadlock/ => SerializationFailure,
}.freeze
def database_error_regexps
DATABASE_ERROR_REGEXPS
end
# Use IDENTITY_VAL_LOCAL() to get the last inserted id.
def last_insert_id(conn, opts=OPTS)
statement(conn) do |stmt|
sql = 'SELECT IDENTITY_VAL_LOCAL() FROM sysibm.sysdummy1'
rs = log_yield(sql){stmt.executeQuery(sql)}
rs.next
rs.getInt(1)
end
end
# Handle nil values by using setNull with the correct parameter type.
def set_ps_arg_nil(cps, i)
cps.setNull(i, cps.getParameterMetaData.getParameterType(i))
end
# Derby uses RENAME TABLE syntax to rename tables.
def rename_table_sql(name, new_name)
"RENAME TABLE #{quote_schema_table(name)} TO #{quote_schema_table(new_name)}"
end
# Primary key indexes appear to be named sqlNNNN on Derby
def primary_key_index_re
PRIMARY_KEY_INDEX_RE
end
# If an :identity option is present in the column, add the necessary IDENTITY SQL.
def type_literal(column)
if column[:identity]
sql = "#{super} GENERATED BY DEFAULT AS IDENTITY"
if sw = column[:start_with]
sql << " (START WITH #{sw.to_i}"
sql << " INCREMENT BY #{column[:increment_by].to_i}" if column[:increment_by]
sql << ")"
end
sql
else
super
end
end
# Derby uses clob for text types.
def uses_clob_for_text?
true
end
# The SQL query to issue to check if a connection is valid.
def valid_connection_sql
@valid_connection_sql ||= select(1).sql
end
end
# Dataset class for Derby datasets accessed via JDBC.
class Dataset < JDBC::Dataset
PAREN_CLOSE = Dataset::PAREN_CLOSE
PAREN_OPEN = Dataset::PAREN_OPEN
OFFSET = Dataset::OFFSET
CAST_STRING_OPEN = "RTRIM(".freeze
BITCOMP_OPEN = "((0 - ".freeze
BITCOMP_CLOSE = ") - 1)".freeze
BLOB_OPEN = "CAST(X'".freeze
BLOB_CLOSE = "' AS BLOB)".freeze
HSTAR = "H*".freeze
TIME_FORMAT = "'%H:%M:%S'".freeze
DEFAULT_FROM = " FROM sysibm.sysdummy1".freeze
ROWS = " ROWS".freeze
FETCH_FIRST = " FETCH FIRST ".freeze
ROWS_ONLY = " ROWS ONLY".freeze
BOOL_TRUE_OLD = '(1 = 1)'.freeze
BOOL_FALSE_OLD = '(1 = 0)'.freeze
BOOL_TRUE = 'TRUE'.freeze
BOOL_FALSE = 'FALSE'.freeze
SELECT_CLAUSE_METHODS = clause_methods(:select, %w'select distinct columns from join where group having compounds order limit lock')
EMULATED_FUNCTION_MAP = {:char_length=>'length'.freeze}
# Derby doesn't support an expression between CASE and WHEN,
# so remove
# conditions.
def case_expression_sql_append(sql, ce)
super(sql, ce.with_merged_expression)
end
# If the type is String, trim the extra spaces since CHAR is used instead
# of varchar. This can cause problems if you are casting a char/varchar to
# a string and the ending whitespace is important.
def cast_sql_append(sql, expr, type)
if type == String
sql << CAST_STRING_OPEN
super
sql << PAREN_CLOSE
else
super
end
end
def complex_expression_sql_append(sql, op, args)
case op
when :%
sql << complex_expression_arg_pairs(args){|a, b| "MOD(#{literal(a)}, #{literal(b)})"}
when :&, :|, :^, :<<, :>>
raise Error, "Derby doesn't support the #{op} operator"
when :'B~'
sql << BITCOMP_OPEN
literal_append(sql, args.at(0))
sql << BITCOMP_CLOSE
when :extract
sql << args.at(0).to_s << PAREN_OPEN
literal_append(sql, args.at(1))
sql << PAREN_CLOSE
else
super
end
end
# Derby supports GROUP BY ROLLUP (but not CUBE)
def supports_group_rollup?
true
end
# Derby does not support IS TRUE.
def supports_is_true?
false
end
# Derby does not support IN/NOT IN with multiple columns
def supports_multiple_column_in?
false
end
private
JAVA_SQL_CLOB = Java::JavaSQL::Clob
class ::Sequel::JDBC::Dataset::TYPE_TRANSLATOR
def derby_clob(v) v.getSubString(1, v.length) end
end
DERBY_CLOB_METHOD = TYPE_TRANSLATOR_INSTANCE.method(:derby_clob)
# Handle clobs on Derby as strings.
def convert_type_proc(v)
if v.is_a?(JAVA_SQL_CLOB)
DERBY_CLOB_METHOD
else
super
end
end
# Derby needs a hex string casted to BLOB for blobs.
def literal_blob_append(sql, v)
sql << BLOB_OPEN << v.unpack(HSTAR).first << BLOB_CLOSE
end
# Derby needs the standard workaround to insert all default values into
# a table with more than one column.
def insert_supports_empty_values?
false
end
# Derby uses an expression yielding false for false values.
# Newer versions can use the FALSE literal, but the latest gem version cannot.
def literal_false
if db.svn_version >= 1040133
BOOL_FALSE
else
BOOL_FALSE_OLD
end
end
# Derby handles fractional seconds in timestamps, but not in times
def literal_sqltime(v)
v.strftime(TIME_FORMAT)
end
# Derby uses an expression yielding true for true values.
# Newer versions can use the TRUE literal, but the latest gem version cannot.
def literal_true
if db.svn_version >= 1040133
BOOL_TRUE
else
BOOL_TRUE_OLD
end
end
# Derby doesn't support common table expressions.
def select_clause_methods
SELECT_CLAUSE_METHODS
end
# Use a default FROM table if the dataset does not contain a FROM table.
def select_from_sql(sql)
if @opts[:from]
super
else
sql << DEFAULT_FROM
end
end
# Offset comes before limit in Derby
def select_limit_sql(sql)
if o = @opts[:offset]
sql << OFFSET
literal_append(sql, o)
sql << ROWS
end
if l = @opts[:limit]
sql << FETCH_FIRST
literal_append(sql, l)
sql << ROWS_ONLY
end
end
end
end
end
end
|