/usr/lib/ruby/vendor_ruby/sequel/adapters/shared/firebird.rb is in ruby-sequel 3.33.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 | module Sequel
module Firebird
module DatabaseMethods
AUTO_INCREMENT = ''.freeze
TEMPORARY = 'GLOBAL TEMPORARY '.freeze
def clear_primary_key(*tables)
tables.each{|t| @primary_keys.delete(dataset.send(:input_identifier, t))}
end
def create_trigger(*args)
self << create_trigger_sql(*args)
end
def database_type
:firebird
end
def drop_sequence(name)
self << drop_sequence_sql(name)
end
# Return primary key for the given table.
def primary_key(table)
t = dataset.send(:input_identifier, table)
@primary_keys.fetch(t) do
pk = fetch("SELECT RDB$FIELD_NAME FROM RDB$INDEX_SEGMENTS NATURAL JOIN RDB$RELATION_CONSTRAINTS WHERE RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' AND RDB$RELATION_NAME = ?", t).single_value
@primary_keys[t] = dataset.send(:output_identifier, pk.rstrip) if pk
end
end
def restart_sequence(*args)
self << restart_sequence_sql(*args)
end
def sequences(opts={})
ds = self[:"rdb$generators"].server(opts[:server]).filter(:"rdb$system_flag" => 0).select(:"rdb$generator_name")
block_given? ? yield(ds) : ds.map{|r| ds.send(:output_identifier, r[:"rdb$generator_name"])}
end
def tables(opts={})
tables_or_views(0, opts)
end
def views(opts={})
tables_or_views(1, opts)
end
private
# Use Firebird specific syntax for add column
def alter_table_sql(table, op)
case op[:op]
when :add_column
"ALTER TABLE #{quote_schema_table(table)} ADD #{column_definition_sql(op)}"
when :drop_column
"ALTER TABLE #{quote_schema_table(table)} DROP #{column_definition_sql(op)}"
when :rename_column
"ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TO #{quote_identifier(op[:new_name])}"
when :set_column_type
"ALTER TABLE #{quote_schema_table(table)} ALTER #{quote_identifier(op[:name])} TYPE #{type_literal(op)}"
else
super(table, op)
end
end
def auto_increment_sql()
AUTO_INCREMENT
end
def create_sequence_sql(name, opts={})
"CREATE SEQUENCE #{quote_identifier(name)}"
end
# Firebird gets an override because of the mess of creating a
# sequence and trigger for auto-incrementing primary keys.
def create_table_from_generator(name, generator, options)
drop_statement, create_statements = create_table_sql_list(name, generator, options)
(execute_ddl(drop_statement) rescue nil) if drop_statement
create_statements.each{|sql| execute_ddl(sql)}
end
def create_table_sql_list(name, generator, options={})
statements = [create_table_sql(name, generator, options)]
drop_seq_statement = nil
generator.columns.each do |c|
if c[:auto_increment]
c[:sequence_name] ||= "seq_#{name}_#{c[:name]}"
unless c[:create_sequence] == false
drop_seq_statement = drop_sequence_sql(c[:sequence_name])
statements << create_sequence_sql(c[:sequence_name])
statements << restart_sequence_sql(c[:sequence_name], {:restart_position => c[:sequence_start_position]}) if c[:sequence_start_position]
end
unless c[:create_trigger] == false
c[:trigger_name] ||= "BI_#{name}_#{c[:name]}"
c[:quoted_name] = quote_identifier(c[:name])
trigger_definition = <<-END
begin
if ((new.#{c[:quoted_name]} is null) or (new.#{c[:quoted_name]} = 0)) then
begin
new.#{c[:quoted_name]} = next value for #{c[:sequence_name]};
end
end
END
statements << create_trigger_sql(name, c[:trigger_name], trigger_definition, {:events => [:insert]})
end
end
end
[drop_seq_statement, statements]
end
def create_trigger_sql(table, name, definition, opts={})
events = opts[:events] ? Array(opts[:events]) : [:insert, :update, :delete]
whence = opts[:after] ? 'AFTER' : 'BEFORE'
inactive = opts[:inactive] ? 'INACTIVE' : 'ACTIVE'
position = opts.fetch(:position, 0)
sql = <<-end_sql
CREATE TRIGGER #{quote_identifier(name)} for #{quote_identifier(table)}
#{inactive} #{whence} #{events.map{|e| e.to_s.upcase}.join(' OR ')} position #{position}
as #{definition}
end_sql
sql
end
def drop_sequence_sql(name)
"DROP SEQUENCE #{quote_identifier(name)}"
end
def remove_cached_schema(table)
clear_primary_key(table)
super
end
def restart_sequence_sql(name, opts={})
seq_name = quote_identifier(name)
"ALTER SEQUENCE #{seq_name} RESTART WITH #{opts[:restart_position]}"
end
def tables_or_views(type, opts)
ds = self[:"rdb$relations"].server(opts[:server]).filter(:"rdb$relation_type" => type, Sequel::SQL::Function.new(:COALESCE, :"rdb$system_flag", 0) => 0).select(:"rdb$relation_name")
ds.map{|r| ds.send(:output_identifier, r[:"rdb$relation_name"].rstrip)}
end
def type_literal_generic_string(column)
column[:text] ? :"BLOB SUB_TYPE TEXT" : super
end
end
module DatasetMethods
BOOL_TRUE = '1'.freeze
BOOL_FALSE = '0'.freeze
NULL = LiteralString.new('NULL').freeze
SELECT_CLAUSE_METHODS = Dataset.clause_methods(:select, %w'with select distinct limit columns from join where group having compounds order')
INSERT_CLAUSE_METHODS = Dataset.clause_methods(:insert, %w'insert into columns values returning')
FIRST = " FIRST ".freeze
SKIP = " SKIP ".freeze
# Insert given values into the database.
def insert(*values)
if @opts[:sql] || @opts[:returning]
super
else
returning(insert_pk).insert(*values){|r| return r.values.first}
end
end
# Insert a record returning the record inserted
def insert_select(*values)
returning.insert(*values){|r| return r}
end
def requires_sql_standard_datetimes?
true
end
def supports_insert_select?
true
end
# Firebird does not support INTERSECT or EXCEPT
def supports_intersect_except?
false
end
private
def insert_clause_methods
INSERT_CLAUSE_METHODS
end
def insert_pk(*values)
pk = db.primary_key(opts[:from].first)
pk ? Sequel::SQL::Identifier.new(pk) : NULL
end
def literal_false
BOOL_FALSE
end
def literal_true
BOOL_TRUE
end
# The order of clauses in the SELECT SQL statement
def select_clause_methods
SELECT_CLAUSE_METHODS
end
def select_limit_sql(sql)
if l = @opts[:limit]
sql << FIRST
literal_append(sql, l)
end
if o = @opts[:offset]
sql << SKIP
literal_append(sql, o)
end
end
end
end
end
|