Module: ArJdbc::SQLite3

Includes:
MissingFunctionalityHelper
Included in:
ActiveRecord::ConnectionAdapters::SQLite3Adapter
Defined in:
lib/arjdbc/sqlite3/adapter.rb

Defined Under Namespace

Modules: Column

Class Method Summary collapse

Instance Method Summary collapse

Methods included from MissingFunctionalityHelper

#alter_table, #copy_table, #copy_table_contents, #copy_table_indexes, #move_table

Class Method Details

.arel2_visitors(config) ⇒ Object



83
84
85
# File 'lib/arjdbc/sqlite3/adapter.rb', line 83

def self.arel2_visitors(config)
  {}.tap {|v| %w(sqlite3 jdbcsqlite3).each {|x| v[x] = ::Arel::Visitors::SQLite } }
end

.column_selectorObject



9
10
11
# File 'lib/arjdbc/sqlite3/adapter.rb', line 9

def self.column_selector
  [/sqlite/i, lambda {|cfg,col| col.extend(::ArJdbc::SQLite3::Column)}]
end

.jdbc_connection_classObject



13
14
15
# File 'lib/arjdbc/sqlite3/adapter.rb', line 13

def self.jdbc_connection_class
  ::ActiveRecord::ConnectionAdapters::Sqlite3JdbcConnection
end

Instance Method Details

#_execute(sql, name = nil) ⇒ Object



193
194
195
196
# File 'lib/arjdbc/sqlite3/adapter.rb', line 193

def _execute(sql, name = nil)
  result = super
  ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql) ? last_insert_id : result
end

#adapter_nameObject

:nodoc:



79
80
81
# File 'lib/arjdbc/sqlite3/adapter.rb', line 79

def adapter_name #:nodoc:
  'SQLite'
end

#add_column(table_name, column_name, type, options = {}) ⇒ Object

:nodoc:



246
247
248
249
250
251
252
253
254
# File 'lib/arjdbc/sqlite3/adapter.rb', line 246

def add_column(table_name, column_name, type, options = {}) #:nodoc:
  if supports_add_column? && valid_alter_table_options( type, options )
    super(table_name, column_name, type, options)
  else
    alter_table(table_name) do |definition|
      definition.column(column_name, type, options)
    end
  end
end

#add_lock!(sql, options) ⇒ Object

SELECT … FOR UPDATE is redundant since the table is locked.



303
304
305
# File 'lib/arjdbc/sqlite3/adapter.rb', line 303

def add_lock!(sql, options) #:nodoc:
  sql
end

#change_column(table_name, column_name, type, options = {}) ⇒ Object

:nodoc:



281
282
283
284
285
286
287
288
289
290
291
292
293
# File 'lib/arjdbc/sqlite3/adapter.rb', line 281

def change_column(table_name, column_name, type, options = {}) #:nodoc:
  alter_table(table_name) do |definition|
    include_default = options_include_default?(options)
    definition[column_name].instance_eval do
      self.type    = type
      self.limit   = options[:limit] if options.include?(:limit)
      self.default = options[:default] if include_default
      self.null    = options[:null] if options.include?(:null)
      self.precision = options[:precision] if options.include?(:precision)
      self.scale   = options[:scale] if options.include?(:scale)
    end
  end
end

#change_column_default(table_name, column_name, default) ⇒ Object

:nodoc:



266
267
268
269
270
# File 'lib/arjdbc/sqlite3/adapter.rb', line 266

def change_column_default(table_name, column_name, default) #:nodoc:
  alter_table(table_name) do |definition|
    definition[column_name].default = default
  end
end

#change_column_null(table_name, column_name, null, default = nil) ⇒ Object



272
273
274
275
276
277
278
279
# File 'lib/arjdbc/sqlite3/adapter.rb', line 272

def change_column_null(table_name, column_name, null, default = nil)
  unless null || default.nil?
    execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
  end
  alter_table(table_name) do |definition|
    definition[column_name].null = null
  end
end

#empty_insert_statement_valueObject



307
308
309
# File 'lib/arjdbc/sqlite3/adapter.rb', line 307

def empty_insert_statement_value
  "VALUES(NULL)"
end

#indexes(table_name, name = nil) ⇒ Object



170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/arjdbc/sqlite3/adapter.rb', line 170

def indexes(table_name, name = nil)
  result = select_rows("SELECT name, sql FROM sqlite_master WHERE tbl_name = #{quote_table_name(table_name)} AND type = 'index'", name)

  result.collect do |row|
    name = row[0]
    index_sql = row[1]
    unique = (index_sql =~ /unique/i)
    cols = index_sql.match(/\((.*)\)/)[1].gsub(/,/,' ').split.map do |c|
      match = /^"(.+)"$/.match(c); match ? match[1] : c
    end
    ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, name, unique, cols)
  end
end

#insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) ⇒ Object

:nodoc:



148
149
150
151
152
# File 'lib/arjdbc/sqlite3/adapter.rb', line 148

def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = []) #:nodoc:
  sql = substitute_binds(sql, binds)
  log(sql, name) { @connection.execute_update(sql) }
  id_value || last_insert_id
end

#jdbc_columns(table_name, name = nil) ⇒ Object

:nodoc:



219
220
221
222
223
# File 'lib/arjdbc/sqlite3/adapter.rb', line 219

def jdbc_columns(table_name, name = nil) #:nodoc:
  table_structure(table_name).map do |field|
    ::ActiveRecord::ConnectionAdapters::SQLite3Column.new(@config, field['name'], field['dflt_value'], field['type'], field['notnull'] == 0)
  end
end

#last_insert_idObject



154
155
156
# File 'lib/arjdbc/sqlite3/adapter.rb', line 154

def last_insert_id
  @connection.last_insert_row_id
end

#modify_types(tp) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/arjdbc/sqlite3/adapter.rb', line 107

def modify_types(tp)
  tp[:primary_key] = "integer primary key autoincrement not null"
  tp[:string] = { :name => "varchar", :limit => 255 }
  tp[:text] = { :name => "text" }
  tp[:float] = { :name => "float" }
  tp[:decimal] = { :name => "decimal" }
  tp[:datetime] = { :name => "datetime" }
  tp[:timestamp] = { :name => "datetime" }
  tp[:time] = { :name => "time" }
  tp[:date] = { :name => "date" }
  tp[:boolean] = { :name => "boolean" }
  tp[:binary] = { :name => "blob" }
  tp
end

#primary_key(table_name) ⇒ Object

:nodoc:



184
185
186
187
# File 'lib/arjdbc/sqlite3/adapter.rb', line 184

def primary_key(table_name) #:nodoc:
  column = table_structure(table_name).find {|field| field['pk'].to_i == 1}
  column ? column['name'] : nil
end

#quote_column_name(name) ⇒ Object

:nodoc:



122
123
124
# File 'lib/arjdbc/sqlite3/adapter.rb', line 122

def quote_column_name(name) #:nodoc:
  %Q("#{name.to_s.gsub('"', '""')}")
end

#quote_string(str) ⇒ Object



126
127
128
# File 'lib/arjdbc/sqlite3/adapter.rb', line 126

def quote_string(str)
  str.gsub(/'/, "''")
end

#quoted_date(value) ⇒ Object

Quote date/time values for use in SQL input. Includes microseconds if the value is a Time responding to usec.



140
141
142
143
144
145
146
# File 'lib/arjdbc/sqlite3/adapter.rb', line 140

def quoted_date(value) #:nodoc:
  if value.respond_to?(:usec)
    "#{super}.#{sprintf("%06d", value.usec)}"
  else
    super
  end
end

#quoted_falseObject



134
135
136
# File 'lib/arjdbc/sqlite3/adapter.rb', line 134

def quoted_false
  %Q{'f'}
end

#quoted_trueObject



130
131
132
# File 'lib/arjdbc/sqlite3/adapter.rb', line 130

def quoted_true
  %Q{'t'}
end

#recreate_database(name) ⇒ Object



189
190
191
# File 'lib/arjdbc/sqlite3/adapter.rb', line 189

def recreate_database(name)
  tables.each{ |table| drop_table(table) }
end

#remove_column(table_name, *column_names) ⇒ Object Also known as: remove_columns

:nodoc:

Raises:

  • (ArgumentError)


256
257
258
259
260
261
262
263
# File 'lib/arjdbc/sqlite3/adapter.rb', line 256

def remove_column(table_name, *column_names) #:nodoc:
  raise ArgumentError.new("You must specify at least one column name.  Example: remove_column(:people, :first_name)") if column_names.empty?
  column_names.flatten.each do |column_name|
    alter_table(table_name) do |definition|
      definition.columns.delete(definition[column_name])
    end
  end
end

#remove_index!(table_name, index_name) ⇒ Object

:nodoc:



232
233
234
# File 'lib/arjdbc/sqlite3/adapter.rb', line 232

def remove_index!(table_name, index_name) #:nodoc:
  execute "DROP INDEX #{quote_column_name(index_name)}"
end

#rename_column(table_name, column_name, new_column_name) ⇒ Object

:nodoc:



295
296
297
298
299
300
# File 'lib/arjdbc/sqlite3/adapter.rb', line 295

def rename_column(table_name, column_name, new_column_name) #:nodoc:
  unless columns(table_name).detect{|c| c.name == column_name.to_s }
    raise ActiveRecord::ActiveRecordError, "Missing column #{table_name}.#{column_name}"
  end
  alter_table(table_name, :rename => {column_name.to_s => new_column_name.to_s})
end

#rename_table(name, new_name) ⇒ Object



236
237
238
# File 'lib/arjdbc/sqlite3/adapter.rb', line 236

def rename_table(name, new_name)
  execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
end

#select(sql, name = nil, binds = []) ⇒ Object



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/arjdbc/sqlite3/adapter.rb', line 198

def select(sql, name=nil, binds = [])
  execute(sql, name, binds).map do |row|
    record = {}
    row.each_key do |key|
      if key.is_a?(String)
        record[key.sub(/^"?\w+"?\./, '')] = row[key]
      end
    end
    record
  end
end

#sqlite_versionObject



103
104
105
# File 'lib/arjdbc/sqlite3/adapter.rb', line 103

def sqlite_version
  @sqlite_version ||= select_value('select sqlite_version(*)')
end

#supports_add_column?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/arjdbc/sqlite3/adapter.rb', line 91

def supports_add_column?
  sqlite_version >= '3.1.6'
end

#supports_autoincrement?Boolean

:nodoc:

Returns:

  • (Boolean)


99
100
101
# File 'lib/arjdbc/sqlite3/adapter.rb', line 99

def supports_autoincrement? #:nodoc:
  sqlite_version >= '3.1.0'
end

#supports_count_distinct?Boolean

:nodoc:

Returns:

  • (Boolean)


95
96
97
# File 'lib/arjdbc/sqlite3/adapter.rb', line 95

def supports_count_distinct? #:nodoc:
  sqlite_version >= '3.2.6'
end

#supports_ddl_transactions?Boolean

Returns:

  • (Boolean)


87
88
89
# File 'lib/arjdbc/sqlite3/adapter.rb', line 87

def supports_ddl_transactions?
  true # sqlite_version >= '2.0.0'
end

#table_structure(table_name) ⇒ Object



210
211
212
213
214
215
216
217
# File 'lib/arjdbc/sqlite3/adapter.rb', line 210

def table_structure(table_name)
  sql = "PRAGMA table_info(#{quote_table_name(table_name)})"
  log(sql, 'SCHEMA') { @connection.execute_query(sql) }
rescue ActiveRecord::JDBCError => error
  e = ActiveRecord::StatementInvalid.new("Could not find table '#{table_name}'")
  e.set_backtrace error.backtrace
  raise e
end

#tables(name = nil) ⇒ Object

:nodoc:



158
159
160
161
162
163
164
165
166
167
168
# File 'lib/arjdbc/sqlite3/adapter.rb', line 158

def tables(name = nil) #:nodoc:
  sql = <<-SQL
    SELECT name
    FROM sqlite_master
    WHERE type = 'table' AND NOT name = 'sqlite_sequence'
  SQL

  select_rows(sql, name).map do |row|
    row[0]
  end
end

#valid_alter_table_options(type, options) ⇒ Object

See: www.sqlite.org/lang_altertable.html SQLite has an additional restriction on the ALTER TABLE statement



242
243
244
# File 'lib/arjdbc/sqlite3/adapter.rb', line 242

def valid_alter_table_options( type, options)
  type.to_sym != :primary_key
end