lib/csvsql.rb in csvsql-0.1.5 vs lib/csvsql.rb in csvsql-0.2.0
- old
+ new
@@ -2,24 +2,94 @@
require "csvsql/version"
require 'csv'
require 'sqlite3'
+require 'digest'
+require 'fileutils'
require 'csvsql/db'
require 'csvsql/tracker'
+require 'csvsql/command_runner'
module Csvsql
- def self.execute(sql, csv_data, opts = {})
- encoding = opts.delete(:encoding)
- csvdb = Csvsql::Db.new(opts)
- csvdb.import(csv_data, encoding: encoding)
+ extend self
+
+ CACHE_DIR = File.join(Dir.home, '.csvsql_cache')
+ FileUtils.mkdir_p(CACHE_DIR) unless Dir.exists?(CACHE_DIR)
+
+ def execute(sql, csv_data, opts = {})
+ csvdb = init_data(csv_data, opts)
pst = Csvsql::Tracker.commit(:execute_query_sql) do
csvdb.prepare(sql)
end
Csvsql::Tracker.commit(:output_format)
CSV.generate do |csv|
csv << pst.columns.zip(pst.types).map { |c| c.compact.join(':') }
pst.each { |line| csv << line }
end.tap { Csvsql::Tracker.commit(:output_format) }
+ end
+
+ def self.clear_cache!
+ FileUtils.rm_f(Dir.glob(File.join(CACHE_DIR, '*')))
+ end
+
+ private
+
+ def init_data(csv_data, opts)
+ encoding = opts.delete(:encoding)
+ use_cache = opts.delete(:use_cache)
+ csvdb = Csvsql::Db.new(opts)
+
+ unless use_cache
+ csvdb.import(csv_data, encoding: encoding)
+ return csvdb
+ end
+
+ case csv_data
+ when StringIO, IO
+ # nothing
+ when Hash
+ dbs = []
+ csv_data.each do |dbname, csv_path|
+ dbs << [dbname, csvdb.init_db(get_db_cache_path(csv_path) || '')]
+ csvdb.import(csv_path, encoding: encoding)
+ end
+ dbs.each do |dbname, db|
+ csvdb.execute("ATTACH DATABASE '#{db.filename}' AS #{dbname};")
+ end
+ else
+ csvdb.init_db(get_db_cache_path(csv_data) || '')
+ csvdb.import(csv_data, encoding: encoding)
+ end
+
+ csvdb
+ end
+
+ def get_db_cache_path(csv_path)
+ csv_path = csv_path || ''
+ return unless File.exist?(csv_path)
+
+ stat = File.stat(csv_path)
+ filename = Digest::SHA2.hexdigest(File.absolute_path(csv_path)) + '.cache'
+ file_stat = [File.absolute_path(csv_path), stat.size, stat.ctime].join("\n")
+ stat_path = File.join(CACHE_DIR, filename.gsub(/\.cache$/, '.stat'))
+ cache_path = File.join(CACHE_DIR, filename)
+
+ if File.exist?(stat_path)
+ if File.read(stat_path) == file_stat
+ cache_path
+ else
+ if update_cb
+ update_cb.call
+ else
+ FileUtils.rm(cache_path)
+ end
+ File.write(stat_path, file_stat)
+ cache_path
+ end
+ else
+ File.write(stat_path, file_stat)
+ cache_path
+ end
end
end