lib/micro_sql.rb in micro_sql-0.2.0 vs lib/micro_sql.rb in micro_sql-0.3.0
- old
+ new
@@ -1,17 +1,25 @@
require "uri"
+require "logger"
class MicroSql
end
require_relative "micro_sql/pg_adapter"
require_relative "micro_sql/sqlite_adapter"
require_relative "micro_sql/table"
-require_relative "micro_sql/settings"
+require_relative "micro_sql/key_value_table"
class MicroSql
+ class Error < RuntimeError; end
+
+ (class << self; self; end).class_eval do
+ attr :logger, true
+ end
+ self.logger = Logger.new(STDERR)
+
(class << self; self; end).class_eval do
private :new
def create(url)
scheme = URI.parse(url).scheme
@@ -24,46 +32,136 @@
eval(klass_name).send(:new, url)
end
end
def ask(sql, *args)
- r = exec(sql, *args)
- return r unless r.is_a?(Array)
-
- r = r.first
- return r unless r.is_a?(Array)
- return r unless r.length == 1
- r.first
+ results = execute :ask, sql, *args
+ format_results_for_ask(results)
end
-
+
def exec!(sql, *args)
execute :no_prepare, sql, *args
end
def exec(sql, *args)
execute :prepare, sql, *args
end
+ private
+
+ def format_results_for_ask(results)
+ return results unless results.is_a?(Array)
+
+ results = results.first
+
+ return results unless results.is_a?(Array)
+ return results if results.length != 1
+
+ results.first
+ end
+
+ public
+
def transaction(&block)
- @impl.transaction(&block)
+ r = nil
+ @impl.transaction do
+ r = yield
+ end
+ r
+ rescue RollbackException
+ nil
end
- def settings
- @settings ||= MicroSql::SettingsTable.new(self)
+ def rollback!
+ raise RollbackException
end
+ public
+
+ def insert(table, *values)
+ hashes, arrays = values.partition do |value| value.is_a?(Hash) end
+
+ id1 = insert_array_values(table, arrays)
+ id2 = insert_hash_values(table, hashes)
+
+ id1 || id2
+ end
+
private
+ def insert_array_values(table, values)
+ width = values.map(&:length).max
+ return if width == 0 || width == nil
+
+ sql = insert_sql(table, width, nil)
+ values.inject(0) do |r, value|
+ exec sql, *value
+ end
+ end
+
+ def insert_hash_values(table, values)
+ keys = values.map(&:keys).flatten.uniq
+ return if keys.empty?
+
+ sql = insert_sql(table, keys.length, keys)
+ values.inject(0) do |r, rec|
+ exec sql, *rec.values_at(*keys)
+ end
+ end
+
+ def insert_sql(table, width, keys = nil)
+ sql = "INSERT INTO #{table}"
+ sql += "(#{keys.join(",")})" if keys
+ sql += " VALUES(" + ([ "?" ] * width).join(",") + ")"
+ end
+
+ public
+
+ def tables
+ raise "Implementation missing: #{self.class}#tables"
+ end
+
+ def table(sql_or_name)
+ @tables ||= {}
+
+ return table_from_name(sql_or_name) if sql_or_name !~ /\s/
+
+ table = Table.new(self, sql_or_name)
+ @tables[table.table_name] = table
+ end
+
+ private
+
+ def table_from_name(name)
+ @tables[name] ||= Table.new(self, name)
+ rescue RuntimeError
+ end
+
+ public
+
+ def key_value_table(name)
+ @key_value_tables ||= Hash.new { |hash, key|
+ hash[key] = MicroSql::KeyValueTable.new(self, key)
+ }
+
+ @key_value_tables[name]
+ end
+
+ private
+
+ class RollbackException < RuntimeError; end
+
def prepared_queries
@prepared_queries ||= {}
end
+ def unprepare(key)
+ @prepared_queries.delete key
+ end
+
def prepare(sql)
- key = sql.to_uid.to_s
- prepared_queries.fetch(key)
+ key = sql
+ prepared_queries.fetch(key)
rescue KeyError
prepared_queries[key] = prepare_query(key, sql)
end
end
-
-# url = "pg://sqdb:sqdb@localhost:5433/sqdb"
-# MicroSql.create(url)