From 993e8c55ca24f0d41364614a0ae3a7d42e216e94 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Fri, 20 May 2011 13:09:32 +0900 Subject: No "t." for the migration DSL! Now you can omit |t| block parameter and all the t. from your migration code, that means, the syntax looks more Rails-3-ish, like the routes DSL and ActionMailer DSL. Also, this change won't break any of your existing migration files, since the traditional syntax is still available. --- .../connection_adapters/sqlite_adapter.rb | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index d2785b234a..4b25384664 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -394,27 +394,29 @@ module ActiveRecord drop_table(from) end - def copy_table(from, to, options = {}) #:nodoc: - options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s)) + def copy_table(from, to, options = {}, &block) #:nodoc: + from_columns, from_primary_key = columns(from), primary_key(from) + options = options.merge(:id => (!from_columns.detect {|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s)) + table_definition = nil create_table(to, options) do |definition| - @definition = definition - columns(from).each do |column| + table_definition = definition + from_columns.each do |column| column_name = options[:rename] ? (options[:rename][column.name] || options[:rename][column.name.to_sym] || column.name) : column.name - @definition.column(column_name, column.type, + table_definition.column(column_name, column.type, :limit => column.limit, :default => column.default, :null => column.null) end - @definition.primary_key(primary_key(from)) if primary_key(from) - yield @definition if block_given? + table_definition.primary_key from_primary_key if from_primary_key + table_definition.instance_eval(&block) if block end copy_table_indexes(from, to, options[:rename] || {}) copy_table_contents(from, to, - @definition.columns.map {|column| column.name}, + table_definition.columns.map {|column| column.name}, options[:rename] || {}) end -- cgit v1.2.3 From cdb49fc2f3f66bbae81be837424dcb45602ea5e2 Mon Sep 17 00:00:00 2001 From: Gustavo Delfino Date: Sat, 6 Aug 2011 16:05:45 -0430 Subject: sqlite transactions now logged motivation: http://stackoverflow.com/questions/6892630/sqlite-transactions-not-showing-in-test-log --- .../lib/active_record/connection_adapters/sqlite_adapter.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index e2a0f63393..ba65ff4357 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -238,15 +238,15 @@ module ActiveRecord end def begin_db_transaction #:nodoc: - @connection.transaction + log('begin transaction',nil) { @connection.transaction } end def commit_db_transaction #:nodoc: - @connection.commit + log('commit transaction',nil) { @connection.commit } end def rollback_db_transaction #:nodoc: - @connection.rollback + log('rollback transaction',nil) { @connection.rollback } end # SCHEMA STATEMENTS ======================================== -- cgit v1.2.3 From 7db90aa7c7dfe5033ad012b8ee13e6f15d1c66f0 Mon Sep 17 00:00:00 2001 From: Jon Leighton Date: Mon, 8 Aug 2011 23:27:54 +0100 Subject: Make it the responsibility of the connection to hold onto an ARel visitor for generating SQL. This improves the code architecture generally, and solves some problems with marshalling. Adapter authors please take note: you now need to define an Adapter.visitor_for method, but it degrades gracefully with a deprecation warning for now. --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index ba65ff4357..486efc5ba0 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -53,6 +53,10 @@ module ActiveRecord @config = config end + def self.visitor_for(pool) # :nodoc: + Arel::Visitors::SQLite.new(pool) + end + def adapter_name #:nodoc: 'SQLite' end -- cgit v1.2.3 From 8a39f411dc3c806422785b1f4d5c7c9d58e4bf85 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 16 Aug 2011 15:17:17 -0700 Subject: prevent sql injection attacks by escaping quotes in column names --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 486efc5ba0..da86957028 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -148,7 +148,7 @@ module ActiveRecord end def quote_column_name(name) #:nodoc: - %Q("#{name}") + %Q("#{name.to_s.gsub('"', '""')}") end # Quote date/time values for use in SQL input. Includes microseconds -- cgit v1.2.3 From 42a7979cf1810c75343b18007858b81718b90678 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 25 Aug 2011 16:07:44 -0700 Subject: Force binary data inserted for a string data type to utf-8 and log an error. Strings tagged as binary will be stored in sqlite3 as blobs. It is an error to insert binary data to a string column, so an error is emitted in the log file. People are highly encouraged to track down the source of the binary strings and make sure that the encoding is set correctly before inserting to the database. --- .../connection_adapters/sqlite_adapter.rb | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index da86957028..1996e49296 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -161,10 +161,25 @@ module ActiveRecord end end - def type_cast(value, column) # :nodoc: - return super unless BigDecimal === value + if "<3".encoding_aware? + def type_cast(value, column) # :nodoc: + return value.to_f if BigDecimal === value + return super unless String === value + return super unless column && value + + value = super + if column.type == :string && value.encoding == Encoding::ASCII_8BIT + @logger.error "Binary data inserted for `string` type on column `#{column.name}`" + value.encode! 'utf-8' + end + value + end + else + def type_cast(value, column) # :nodoc: + return super unless BigDecimal === value - value.to_f + value.to_f + end end # DATABASE STATEMENTS ====================================== -- cgit v1.2.3 From 8b9ddbd8f912d4aac475bcbcbd3e3d39b9b73bf9 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 1 Sep 2011 14:06:20 -0700 Subject: make sure encoding_aware? is available --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 1996e49296..7d793e3cb8 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,4 +1,6 @@ require 'active_record/connection_adapters/abstract_adapter' +require 'active_support/core_ext/kernel/requires' +require 'active_support/core_ext/string/encoding' module ActiveRecord module ConnectionAdapters #:nodoc: -- cgit v1.2.3 From 6f3c6992c529a09c8f8bfdb1f714bb8ff1e23300 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 1 Sep 2011 15:00:31 -0700 Subject: * Psych errors with poor yaml formatting are proxied. Fixes #2645, #2731 --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 1 - 1 file changed, 1 deletion(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 7d793e3cb8..a90c675bf6 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,5 +1,4 @@ require 'active_record/connection_adapters/abstract_adapter' -require 'active_support/core_ext/kernel/requires' require 'active_support/core_ext/string/encoding' module ActiveRecord -- cgit v1.2.3 From a4fa6eab396e703eb70b70ed708220a6405f2899 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 6 Sep 2011 16:06:27 -0700 Subject: adding a statement pool for mysql and sqlite3 --- .../connection_adapters/sqlite_adapter.rb | 38 +++++++++++++++++++--- 1 file changed, 33 insertions(+), 5 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index a90c675bf6..a4e21b714b 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -1,4 +1,5 @@ require 'active_record/connection_adapters/abstract_adapter' +require 'active_record/connection_adapters/statement_pool' require 'active_support/core_ext/string/encoding' module ActiveRecord @@ -48,9 +49,40 @@ module ActiveRecord end end + class StatementPool < ConnectionAdapters::StatementPool + def initialize(connection, max = 1000) + super + @cache = {} + end + + def each(&block); @cache.each(&block); end + def key?(key); @cache.key?(key); end + def [](key); @cache[key]; end + def length; @cache.length; end + + def []=(sql, key) + while @max <= @cache.size + dealloc(@cache.shift.last[:stmt]) + end + @cache[sql] = key + end + + def clear + @cache.values.each do |hash| + dealloc hash[:stmt] + end + @cache.clear + end + + private + def dealloc(stmt) + stmt.close unless stmt.closed? + end + end + def initialize(connection, logger, config) super(connection, logger) - @statements = {} + @statements = StatementPool.new(@connection) @config = config end @@ -107,10 +139,6 @@ module ActiveRecord # Clears the prepared statements cache. def clear_cache! - @statements.values.map { |hash| hash[:stmt] }.each { |stmt| - stmt.close unless stmt.closed? - } - @statements.clear end -- cgit v1.2.3 From 54b7e783ef202d022a57dcdd54f7edf021c1df78 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Tue, 6 Sep 2011 16:47:34 -0700 Subject: Database adapters use a statement pool. Database adapters use a statement pool for limiting the number of open prepared statments on the database. The limit defaults to 1000, but can be adjusted in your database config by changing 'statement_limit'. --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index a4e21b714b..7c7e762c19 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -50,7 +50,7 @@ module ActiveRecord end class StatementPool < ConnectionAdapters::StatementPool - def initialize(connection, max = 1000) + def initialize(connection, max) super @cache = {} end @@ -82,7 +82,8 @@ module ActiveRecord def initialize(connection, logger, config) super(connection, logger) - @statements = StatementPool.new(@connection) + @statements = StatementPool.new(@connection, + config.fetch(:statement_limit) { 1000 }) @config = config end -- cgit v1.2.3 From e1b500ec96987de595da1541a73a7d5fb9eece9c Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Wed, 7 Sep 2011 15:26:26 -0700 Subject: LRU cache in mysql and sqlite are now per-process caches. --- .../connection_adapters/sqlite_adapter.rb | 24 +++++++++++++--------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 7c7e762c19..1932a849ee 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -52,29 +52,33 @@ module ActiveRecord class StatementPool < ConnectionAdapters::StatementPool def initialize(connection, max) super - @cache = {} + @cache = Hash.new { |h,pid| h[pid] = {} } end - def each(&block); @cache.each(&block); end - def key?(key); @cache.key?(key); end - def [](key); @cache[key]; end - def length; @cache.length; end + def each(&block); cache.each(&block); end + def key?(key); cache.key?(key); end + def [](key); cache[key]; end + def length; cache.length; end def []=(sql, key) - while @max <= @cache.size - dealloc(@cache.shift.last[:stmt]) + while @max <= cache.size + dealloc(cache.shift.last[:stmt]) end - @cache[sql] = key + cache[sql] = key end def clear - @cache.values.each do |hash| + cache.values.each do |hash| dealloc hash[:stmt] end - @cache.clear + cache.clear end private + def cache + @cache[$$] + end + def dealloc(stmt) stmt.close unless stmt.closed? end -- cgit v1.2.3 From f092be821db4a2e8f142e8f0b9d08e497ccf2eb2 Mon Sep 17 00:00:00 2001 From: Greg Reinacker Date: Fri, 21 Oct 2011 17:30:39 -0600 Subject: preserve decimal column attributes after migration --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 3 +++ 1 file changed, 3 insertions(+) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 1932a849ee..e0e957a12c 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -413,6 +413,8 @@ module ActiveRecord 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 @@ -467,6 +469,7 @@ module ActiveRecord @definition.column(column_name, column.type, :limit => column.limit, :default => column.default, + :precision => column.precision, :scale => column.scale, :null => column.null) end @definition.primary_key(primary_key(from)) if primary_key(from) -- cgit v1.2.3 From 69dcd45aea770ca90bb3e1f8ce4e944dfb37e766 Mon Sep 17 00:00:00 2001 From: Vlad Jebelev Date: Fri, 4 Nov 2011 15:45:24 -0500 Subject: AR changes to support creating ordered (asc, desc) indexes --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index f74f3e6ec8..caecbc9b3a 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -157,6 +157,10 @@ module ActiveRecord sqlite_version >= '3.1.0' end + def supports_index_sort_order? + sqlite_version >= '3.3.0' + end + def native_database_types #:nodoc: { :primary_key => default_primary_key_type, -- cgit v1.2.3 From e7b7b4412380e7ce2d8e6ae402cb7fe02d7666b8 Mon Sep 17 00:00:00 2001 From: Xavier Noria Date: Tue, 20 Sep 2011 10:50:08 -0700 Subject: implements AR::Relation#explain This is a first implementation, EXPLAIN is highly dependent on the database and I have made some compromises. On one hand, the method allows you to run the most common EXPLAIN and that's it. If you want EXPLAIN ANALYZE in PostgreSQL you need to do it by hand. On the other hand, I've tried to construct a string as close as possible to the ones built by the respective shells. The rationale is that IMO the user should feel at home with the output and recognize it at first sight. Per database. I don't know whether this implementation is going to work well. Let's see whether people like it. --- .../connection_adapters/sqlite_adapter.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index caecbc9b3a..35df0a1542 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -222,6 +222,25 @@ module ActiveRecord # DATABASE STATEMENTS ====================================== + def explain(arel) + sql = "EXPLAIN QUERY PLAN #{to_sql(arel)}" + ExplainPrettyPrinter.new.pp(exec_query(sql, 'EXPLAIN')) + end + + class ExplainPrettyPrinter + # Pretty prints the result of a EXPLAIN QUERY PLAN in a way that resembles + # the output of the SQLite shell: + # + # 0|0|0|SEARCH TABLE users USING INTEGER PRIMARY KEY (rowid=?) (~1 rows) + # 0|1|1|SCAN TABLE posts (~100000 rows) + # + def pp(result) # :nodoc: + result.rows.map do |row| + row.join('|') + end.join("\n") + "\n" + end + end + def exec_query(sql, name = nil, binds = []) log(sql, name, binds) do -- cgit v1.2.3 From a2f14e23441ec016f9643b9054f409006b0e16b3 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 17 Nov 2011 10:28:23 -0800 Subject: Revert "Merge pull request #1163 from amatsuda/sexier_migration_31" This reverts commit 0e407a90413d8a19002b85508d811ccdf2190783, reversing changes made to 533a9f84b035756eedf9fdccf0c494dc9701ba72. Conflicts: activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb activerecord/test/cases/migration_test.rb --- .../connection_adapters/sqlite_adapter.rb | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 35df0a1542..bc3804b3d9 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -480,30 +480,28 @@ module ActiveRecord drop_table(from) end - def copy_table(from, to, options = {}, &block) #:nodoc: - from_columns, from_primary_key = columns(from), primary_key(from) - options = options.merge(:id => (!from_columns.detect {|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s)) - table_definition = nil + def copy_table(from, to, options = {}) #:nodoc: + options = options.merge(:id => (!columns(from).detect{|c| c.name == 'id'}.nil? && 'id' == primary_key(from).to_s)) create_table(to, options) do |definition| - table_definition = definition - from_columns.each do |column| + @definition = definition + columns(from).each do |column| column_name = options[:rename] ? (options[:rename][column.name] || options[:rename][column.name.to_sym] || column.name) : column.name - table_definition.column(column_name, column.type, + @definition.column(column_name, column.type, :limit => column.limit, :default => column.default, :precision => column.precision, :scale => column.scale, :null => column.null) end - table_definition.primary_key from_primary_key if from_primary_key - table_definition.instance_eval(&block) if block + @definition.primary_key(primary_key(from)) if primary_key(from) + yield @definition if block_given? end copy_table_indexes(from, to, options[:rename] || {}) copy_table_contents(from, to, - table_definition.columns.map {|column| column.name}, + @definition.columns.map {|column| column.name}, options[:rename] || {}) end -- cgit v1.2.3 From bd2f5c062da011e092c1f122567f24bd5fc6d9b5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sat, 19 Nov 2011 20:19:53 -0800 Subject: pushing caching and visitors down to the connection --- activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb') diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index bc3804b3d9..c11f82a33f 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -89,10 +89,7 @@ module ActiveRecord @statements = StatementPool.new(@connection, config.fetch(:statement_limit) { 1000 }) @config = config - end - - def self.visitor_for(pool) # :nodoc: - Arel::Visitors::SQLite.new(pool) + @visitor = Arel::Visitors::SQLite.new self end def adapter_name #:nodoc: -- cgit v1.2.3