lib/spiderfw/model/storage/db/adapters/sqlite.rb in spiderfw-0.5.7 vs lib/spiderfw/model/storage/db/adapters/sqlite.rb in spiderfw-0.5.9

- old
+ new

@@ -4,34 +4,43 @@ module Spider; module Model; module Storage; module Db class SQLite < DbStorage @reserved_keywords = superclass.reserved_keywords + [] @capabilities = { - :autoincrement => false, + :autoincrement => true, :sequences => true, - :transactions => true + :transactions => true, + :foreign_keys => false } class << self; attr_reader :reserved_kewords; end + def self.max_connections + 1 + end + def self.base_types super << Spider::DataTypes::Binary end def self.new_connection(file) - @db = SQLite3::Database.new(file) - @db.results_as_hash = true - return @db + db = SQLite3::Database.new(file) + db.results_as_hash = true + return db end - def connect - @conn = self.class.new_connection(*@connection_params) unless @conn + def self.connection_alive?(conn) + !conn.closed? end def release - @conn.close if @conn - @conn = nil + begin + #curr[:conn].close + super + rescue + curr[:conn] = nil + end end def parse_url(url) if (url =~ /(.+?):\/\/(.+)/) @@ -41,30 +50,34 @@ raise ArgumentError, "SQLite url '#{url}' is invalid" end @connection_params = [@file] end - def start_transaction + def do_start_transaction + return unless transactions_enabled? connection.transaction end def in_transaction? - @conn && @conn.transaction_active? + return false unless transactions_enabled? + return curr[:conn] && curr[:conn].transaction_active? end - def commit - @conn.commit + def do_commit + return release unless transactions_enabled? + curr[:conn].commit if curr[:conn] release end - - def rollback - @conn.rollback + + def do_rollback + return release unless transactions_enabled? + curr[:conn].rollback release end - + def assigned_key(key) - @last_insert_row_id + curr[:last_insert_row_id] end def value_for_save(type, value, save_mode) case type.name when 'Spider::DataTypes::Binary' @@ -79,13 +92,13 @@ debug_vars = bind_vars.map{|var| var = var.to_s; var && var.length > 50 ? var[0..50]+"...(#{var.length-50} chars more)" : var}.join(', ') end debug("sqlite executing:\n#{sql}\n[#{debug_vars}]") result = connection.execute(sql, *bind_vars) - @last_insert_row_id = connection.last_insert_row_id + curr[:last_insert_row_id] = connection.last_insert_row_id result.extend(StorageResult) - @last_result = result + curr[:last_result] = result if block_given? result.each{ |row| yield row } else return result end @@ -95,50 +108,71 @@ end def prepare(sql) debug("sqlite preparing: #{sql}") - connect unless connected? - return @conn.prepare(sql) + return connection.prepare(sql) end def execute_statement(stmt, *bind_vars) stmt.execute(bind_vars) end def total_rows - return nil unless @last_query - q = @last_query + return nil unless curr[:last_query] + q = curr[:last_query] unless (q[:offset] || q[:limit]) - return @last_result ? @last_result.length : nil + return curr[:last_result] ? curr[:last_result].length : nil end q[:offset] = q[:limit] = nil q[:keys] = ["COUNT(*) AS N"] res = execute(sql_select(q), q[:bind_vars]) return res[0]['N'] end + ############################################################# + # SQL methods # + ############################################################# + ############################################################## # Methods to get information from the db # ############################################################## def list_tables return execute("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name").flatten end def describe_table(table) columns = {} - stmt = prepare("select * from #{table}") - stmt.columns.each_index do |index| - field = stmt.columns[index] - columns[field] ||= {} - if (stmt.types[index] =~ /([^\(]+)(?:\((\d+)\))?/) - columns[field][:type] = $1 - columns[field][:length] = $2.to_i if $2 + primary_keys = [] + res = execute("PRAGMA table_info('#{table}')") + res.each do |row| + name = row['name'] + type = row['type'] + length = nil + precision = nil + if type =~ /(.+)\((.+)\)/ + type = $1 + length = $2 end + if length && length.include?(",") + length, precision = length.split(',') + end + length = length.to_i if length + precision = precision.to_i if length + primary_keys << name if row['pk'] == "1" + columns[name] = {:type => type, :length => length, :precision => precision} end - stmt.close - return {:columns => columns} + # stmt.columns.each_index do |index| + # field = stmt.columns[index] + # columns[field] ||= {} + # if (stmt.types[index] =~ /([^\(]+)(?:\((\d+)\))?/) + # columns[field][:type] = $1 + # columns[field][:length] = $2.to_i if $2 + # end + # end + # stmt.close + return {:columns => columns, :primary_keys => primary_keys} end def table_exists?(table) begin stmt = prepare("select * from #{table}") \ No newline at end of file