#!/usr/bin/env ruby #coding: utf-8 require "ezframe" include Ezframe class DBInfo class << self def get_db_info(table_name) typ = get_database_type(Config[:database]) case typ when "postgresql" return get_info_from_postgres(table_name) when "sqlite" return get_info_from_sqlite(table_name) else raise "unknown database" end return nil end def get_info_from_postgres(table_name) dbcol = {} sql = "SELECT column_name,data_type FROM information_schema.columns WHERE table_name = '#{table_name}'" begin data_a = DB.sequel[sql].all rescue return nil end # puts data_a data_a.each do |row| dbcol[row[:column_name].to_s.to_sym] = normalize_dbtype(row[:data_type]) end return dbcol end def get_info_from_sqlite(table_name) sql = "SELECT * from sqlite_master WHERE name = '#{table_name}';" data = DB.sequel[sql].first return nil unless data sql = data[:sql] return parse_create_sql(sql) end def parse_create_sql(sql) sql.gsub(/CREATE TABLE \`\w+\` \(/, "") column_a = sql.split(", ") dbcol = {} column_a.each do |line| if line =~ /\`(\w+)\`\s(\w+)/ colkey, dbtype = $1, $2 dbcol[colkey.to_sym] = dbtype end end return dbcol end def get_database_type(config) return config.split("://")[0] end end end def exec_sql(sql) begin DB.sequel.run(sql) rescue => exception p exception end end def normalize_dbtype(dbtype) return nil unless dbtype return "int" if dbtype == "integer" return "timestamp" if dbtype.index("timestamp") return dbtype end def set_default(column) default_value = column.attribute[:default] if default_value unless %w[int].include?(column.db_type) default_value = "'#{default_value}'" end exec_sql("ALTER TABLE #{column.parent.name} ALTER #{column.key} SET DEFAULT #{default_value}") end end def check_diff(column_set) table_name = column_set.name dbcols = DBInfo.get_db_info(table_name) unless dbcols ColumnSets.create_one_table(table_name, ColumnSets.get(table_name.to_sym)) return end column_set.each do |column| next if %w[id updated_at created_at].include?(column.key.to_s) dbtype = dbcols[column.key] new_type = column.db_type unless dbtype exec_sql("ALTER TABLE #{table_name} ADD #{column.key} #{new_type};") set_default(column) next end if dbtype != new_type exec_sql("ALTER TABLE #{table_name} ALTER COLUMN #{column.key} DROP DEFAULT;") exec_sql("ALTER TABLE #{table_name} ALTER #{column.key} TYPE #{new_type};") set_default(column) end end end Config.init DB.init ColumnSets.init ColumnSets.each do |table_name, column_set| check_diff(column_set) end