Skip to content

Instantly share code, notes, and snippets.

@wyldrodney
Created July 3, 2012 17:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wyldrodney/3041366 to your computer and use it in GitHub Desktop.
Save wyldrodney/3041366 to your computer and use it in GitHub Desktop.
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, &params)
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(&params)
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