class Sequel::SQLite::Database
Attributes
The conversion procs to use for this database
Public Class Methods
Source
# File lib/sequel/adapters/sqlite.rb 115 def initialize(opts = OPTS) 116 super 117 @allow_regexp = typecast_value_boolean(opts[:setup_regexp_function]) 118 end
Sequel::Database::new
Public Instance Methods
Source
# File lib/sequel/adapters/sqlite.rb 172 def allow_regexp? 173 @allow_regexp 174 end
Source
# File lib/sequel/adapters/sqlite.rb 142 def connect(server) 143 opts = server_opts(server) 144 opts[:database] = ':memory:' if blank_object?(opts[:database]) 145 sqlite3_opts = {} 146 sqlite3_opts[:readonly] = typecast_value_boolean(opts[:readonly]) if opts.has_key?(:readonly) 147 # SEQUEL6: Make strict: true the default behavior 148 sqlite3_opts[:strict] = typecast_value_boolean(opts[:disable_dqs]) if opts.has_key?(:disable_dqs) 149 db = ::SQLite3::Database.new(opts[:database].to_s, sqlite3_opts) 150 db.busy_timeout(typecast_value_integer(opts.fetch(:timeout, 5000))) 151 152 if USE_EXTENDED_RESULT_CODES 153 db.extended_result_codes = true 154 end 155 156 connection_pragmas.each{|s| log_connection_yield(s, db){db.execute_batch(s)}} 157 158 if typecast_value_boolean(opts[:setup_regexp_function]) 159 setup_regexp_function(db, opts[:setup_regexp_function]) 160 end 161 162 class << db 163 attr_reader :prepared_statements 164 end 165 db.instance_variable_set(:@prepared_statements, {}) 166 167 db 168 end
Connect to the database. Since SQLite is a file based database, available options are limited:
- :database
-
database name (filename or β:memory:β or file: URI)
- :readonly
-
open database in read-only mode; useful for reading static data that you do not want to modify
- :disable_dqs
-
disable double quoted strings in DDL and DML statements (requires
SQLite3.29.0+ and sqlite3 gem version 1.4.3+). - :timeout
-
how long to wait for the database to be available if it is locked, given in milliseconds (default is 5000)
- :setup_regexp_function
-
enable use of Regexp objects with
SQL
'REGEXP' operator. If the value is :cached or "cached", caches the generated regexps, which can result in a memory leak if dynamic regexps are used. If the value is a Proc, it will be called with a string for the regexp and a string for the value to compare, and should return whether the regexp matches.
- :regexp_function_cache
-
If setting
setup_regexp_functiontocached, this
determines the cache to use. It should either be a proc or a class, and it defaults to +Hash+. You can use +ObjectSpace::WeakKeyMap+ on Ruby 3.3+ to have the VM automatically remove regexps from the cache after they are no longer used.
Source
# File lib/sequel/adapters/sqlite.rb 177 def disconnect_connection(c) 178 c.prepared_statements.each_value{|v| v.first.close} 179 c.close 180 end
Disconnect given connections from the database.
Source
# File lib/sequel/adapters/sqlite.rb 183 def execute(sql, opts=OPTS, &block) 184 _execute(:select, sql, opts, &block) 185 end
Run the given SQL with the given arguments and yield each row.
Source
# File lib/sequel/adapters/sqlite.rb 195 def execute_ddl(sql, opts=OPTS) 196 synchronize(opts[:server]) do |conn| 197 conn.prepared_statements.values.each{|cps, s| cps.close} 198 conn.prepared_statements.clear 199 super 200 end 201 end
Drop any prepared statements on the connection when executing DDL. This is because prepared statements lock the table in such a way that you canβt drop or alter the table while a prepared statement that references it still exists.
Sequel::Database#execute_ddl
Source
# File lib/sequel/adapters/sqlite.rb 188 def execute_dui(sql, opts=OPTS) 189 _execute(:update, sql, opts) 190 end
Run the given SQL with the given arguments and return the number of changed rows.
Source
# File lib/sequel/adapters/sqlite.rb 203 def execute_insert(sql, opts=OPTS) 204 _execute(:insert, sql, opts) 205 end
Source
# File lib/sequel/adapters/sqlite.rb 207 def freeze 208 @conversion_procs.freeze 209 super 210 end
Sequel::SQLite::DatabaseMethods#freeze
Source
# File lib/sequel/adapters/sqlite.rb 213 def to_application_timestamp(s) 214 case s 215 when String 216 super 217 when Integer 218 super(Time.at(s).to_s) 219 when Float 220 super(DateTime.jd(s).to_s) 221 else 222 raise Sequel::Error, "unhandled type when converting to : #{s.inspect} (#{s.class.inspect})" 223 end 224 end
Handle Integer and Float arguments, since SQLite can store timestamps as integers and floats.
Sequel::Database#to_application_timestamp
Private Instance Methods
Source
# File lib/sequel/adapters/sqlite.rb 265 def _execute(type, sql, opts, &block) 266 synchronize(opts[:server]) do |conn| 267 return execute_prepared_statement(conn, type, sql, opts, &block) if sql.is_a?(Symbol) 268 log_args = opts[:arguments] 269 args = {} 270 opts.fetch(:arguments, OPTS).each{|k, v| args[k] = prepared_statement_argument(v)} 271 case type 272 when :select 273 log_connection_yield(sql, conn, log_args){conn.query(sql, args, &block)} 274 when :insert 275 log_connection_yield(sql, conn, log_args){conn.execute(sql, args)} 276 conn.last_insert_row_id 277 when :update 278 log_connection_yield(sql, conn, log_args){conn.execute_batch(sql, args)} 279 conn.changes 280 end 281 end 282 rescue SQLite3::Exception => e 283 raise_error(e) 284 end
Yield an available connection. Rescue any SQLite3::Exceptions and turn them into DatabaseErrors.
Source
# File lib/sequel/adapters/sqlite.rb 228 def adapter_initialize 229 @conversion_procs = SQLITE_TYPES.dup 230 @conversion_procs['datetime'] = @conversion_procs['timestamp'] = method(:to_application_timestamp) 231 set_integer_booleans 232 end
Source
# File lib/sequel/adapters/sqlite.rb 289 def connection_pool_default_options 290 o = super.dup 291 # Default to only a single connection if a memory database is used, 292 # because otherwise each connection will get a separate database 293 o[:max_connections] = 1 if @opts[:database] == ':memory:' || blank_object?(@opts[:database]) 294 o 295 end
The SQLite adapter does not need the pool to convert exceptions. Also, force the max connections to 1 if a memory database is being used, as otherwise each connection gets a separate database.
Sequel::Database#connection_pool_default_options
Source
# File lib/sequel/adapters/sqlite.rb 354 def database_error_classes 355 [SQLite3::Exception, ArgumentError] 356 end
SQLite3 raises ArgumentError in addition to SQLite3::Exception in some cases, such as operations on a closed database.
Source
# File lib/sequel/adapters/sqlite.rb 358 def dataset_class_default 359 Dataset 360 end
Source
# File lib/sequel/adapters/sqlite.rb 315 def execute_prepared_statement(conn, type, name, opts, &block) 316 ps = prepared_statement(name) 317 sql = ps.prepared_sql 318 args = opts[:arguments] 319 ps_args = {} 320 args.each{|k, v| ps_args[k] = prepared_statement_argument(v)} 321 if cpsa = conn.prepared_statements[name] 322 cps, cps_sql = cpsa 323 if cps_sql != sql 324 cps.close 325 cps = nil 326 end 327 end 328 unless cps 329 cps = log_connection_yield("PREPARE #{name}: #{sql}", conn){conn.prepare(sql)} 330 conn.prepared_statements[name] = [cps, sql] 331 end 332 log_sql = String.new 333 log_sql << "EXECUTE #{name}" 334 if ps.log_sql 335 log_sql << " (" 336 log_sql << sql 337 log_sql << ")" 338 end 339 if block 340 log_connection_yield(log_sql, conn, args){cps.execute(ps_args, &block)} 341 else 342 log_connection_yield(log_sql, conn, args){cps.execute!(ps_args){|r|}} 343 case type 344 when :insert 345 conn.last_insert_row_id 346 when :update 347 conn.changes 348 end 349 end 350 end
Execute a prepared statement on the database using the given name.
Source
# File lib/sequel/adapters/sqlite.rb 297 def prepared_statement_argument(arg) 298 case arg 299 when Date, DateTime, Time 300 literal(arg)[1...-1] 301 when SQL::Blob 302 arg.to_blob 303 when true, false 304 if integer_booleans 305 arg ? 1 : 0 306 else 307 literal(arg)[1...-1] 308 end 309 else 310 arg 311 end 312 end
Source
# File lib/sequel/adapters/sqlite.rb 234 def setup_regexp_function(db, how) 235 case how 236 when Proc 237 # nothing 238 when :cached, "cached" 239 cache = @opts[:regexp_function_cache] || Hash 240 cache = cache.is_a?(Proc) ? cache.call : cache.new 241 how = if RUBY_VERSION >= '2.4' 242 lambda do |regexp_str, str| 243 (cache[regexp_str] ||= Regexp.new(regexp_str)).match?(str) 244 end 245 else 246 lambda do |regexp_str, str| 247 (cache[regexp_str] ||= Regexp.new(regexp_str)).match(str) 248 end 249 end 250 else 251 how = if RUBY_VERSION >= '2.4' 252 lambda{|regexp_str, str| Regexp.new(regexp_str).match?(str)} 253 else 254 lambda{|regexp_str, str| Regexp.new(regexp_str).match(str)} 255 end 256 end 257 258 db.create_function("regexp", 2) do |func, regexp_str, str| 259 func.result = how.call(regexp_str, str) ? 1 : 0 260 end 261 end
Source
# File lib/sequel/adapters/sqlite.rb 364 def sqlite_error_code(exception) 365 exception.code if exception.respond_to?(:code) 366 end
Support SQLite exception codes if ruby-sqlite3 supports them.