Created
July 3, 2012 17:52
-
-
Save wyldrodney/3041366 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module SDB | |
class Database | |
@@connections = {} | |
def self.define_connection(db_name, &init) | |
@@connections[db_name] = init | |
##Storing db config in proc. | |
end | |
def self.connect(db_name) | |
new(db_name) | |
end | |
def initialize(db_name) | |
@tables = {} | |
@name = db_name | |
instance_eval(&@@connections[db_name]) | |
##Call config's commands: creating columns and other... | |
end | |
attr_reader :name, :tables | |
def select(table_name, *args) | |
@tables[table_name].select(args) | |
##Pass `select` query to proper table | |
end | |
private | |
def table(table_name, ¶ms) | |
t_table = Table.new(table_name, params) | |
@tables[table_name] = t_table if t_table | |
##Top-level config command: table creation | |
##and block arguments' pass | |
end | |
end | |
class Table | |
def initialize(table_name, params) | |
@columns = [] | |
@view = [] | |
@days = 299 | |
@name = table_name | |
instance_eval(¶ms) | |
return false unless parse_data | |
make_table | |
##Run commands from `table` config block | |
##Return error to Database#table caller if file corrupted or not exists | |
##Preparing model data | |
end | |
attr_reader :name, :source, :columns | |
def select(*args) | |
args.flatten! | |
result = [] | |
result = args[0][:where] ? where(args[0][:where]) : where({}) | |
result = limit(result, args[0][:limit]) if args[0][:limit] | |
result | |
##Query arguments' preparing and pass | |
end | |
private | |
def source(type, path) | |
raise "Unsupported file type" unless type == :file | |
@source = path | |
end | |
def column(name, *args) | |
@columns << [name.to_s, args].flatten | |
##Fill column names and properties | |
end | |
def get_unpack_key | |
key = '' | |
@columns.each do |column| | |
case column[1] | |
when :string | |
key += "a#{column[2]}" | |
when :integer, :datetime | |
key += "q" | |
end | |
end | |
key | |
##Read columns configuration and String#unpack key generation | |
##Supports only strings (with defined legth) and integers | |
end | |
def get_column_type(col_name) | |
@columns.each { |column| return column[1] if column[0] == "#{col_name}" } | |
##Return column date type as symbol | |
end | |
def parse_data | |
column_count = @columns.count | |
position = 0 | |
buf = [] | |
begin | |
@raw_table = File.read(@source).unpack(get_unpack_key*@days) | |
##Read data model and unpack it | |
rescue | |
puts "Error loading #{@source}. Skipping." | |
return false | |
end | |
while position < @days*column_count do | |
buf << @raw_table[position...position+column_count] | |
position += column_count | |
end | |
@raw_table = buf | |
##Detect data model lines and convert to table chunks | |
end | |
def make_table | |
@columns.each_with_index do |column, index| | |
eval("@#{column[0]} = {}") | |
@raw_table.each_with_index do |row, counter| | |
eval("@#{column[0]}[:k#{counter}] = column[1] == :string ? row[index].strip : row[index]") | |
end | |
end | |
##Creating instance variables for each column | |
##and fill them with data | |
##Strings (type) are stripped | |
end | |
def grep(column, value) | |
value = case get_column_type(column) | |
when :string | |
"'#{value}'" | |
when :integer | |
"#{value}" | |
when :datetime | |
"#{value.to_time.to_i}" | |
end | |
##Prepare query arguments for searching | |
eval("@#{column}.find_all { |key, val| val == #{value} }") | |
##Simple Hash-search. Hope it faster than Arrays :) | |
end | |
def limit(result, count) | |
result.first(count) | |
##Simple `limit()` handler | |
end | |
def where(*params) | |
keys = {} | |
params[0].each do |param| | |
grep(param[0], param[1]).each do |pair| | |
if keys[pair[0]] | |
keys[pair[0]] += 1 | |
else | |
keys[pair[0]] = 1 | |
end | |
end | |
end | |
##Keys stores matches counter for multiple arguments in queries | |
##It's nessesary for one attribute-value pair to match twice (for ex) if | |
##where sequence contains two attr-val pairs | |
##E.g. `where: { number: 1, name: "Day 1" }` will give | |
##two matches for both attr-value pairs | |
params_count = params[0].count | |
keys.each { |key, val| keys.delete(key) if val < params_count } | |
##Check matches count | |
formatter(params != {} ? keys.keys : nil) | |
end | |
def formatter(keys) | |
result = [] | |
if keys == [] | |
return result | |
elsif keys.nil? | |
keys = @number.keys | |
end | |
@columns.each do |column| | |
keys.each_with_index do |key, index| | |
result[index] = {} unless result[index] | |
result[index][:offset] = key.to_s[1..-1].to_i | |
value = eval("@#{column[0]}[:#{key}]") | |
value = Time.at(value).to_date if get_column_type(column[0]) == :datetime | |
result[index][:"#{column[0]}"] = value | |
end | |
end | |
result | |
##Types transformation and output grouping | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment