lib/active_groonga/schema.rb in activegroonga-0.0.2 vs lib/active_groonga/schema.rb in activegroonga-0.0.6

- old
+ new

@@ -52,263 +52,166 @@ end end end def initialize_schema_management_tables - initialize_index_management_table - initialize_index_table initialize_migrations_table end - def create_table(name, options={}) - table_definition = TableDefinition.new(name) - yield(table_definition) - table_definition.create + def create_table(name, options={}, &block) + table_file = File.join(Base.tables_directory, "#{name}.groonga") + table_name = Base.groonga_table_name(name) + options = {:path => table_file}.merge(options) + options = default_table_options(options).merge(options) + options = options.merge(:context => Base.context) + Groonga::Schema.create_table(table_name, options) do |table| + block.call(TableDefinitionWrapper.new(table)) + end end - def drop_table(name, options={}) - table = Base.context[Base.groonga_table_name(name)] - table_id = table.id - table.remove - index_management_table.open_cursor do |cursor| - while cursor.next - cursor.delete if cursor.table_id == table_id - end - end + def remove_table(name, options={}) + options = options.merge(:context => Base.context) + Groonga::Schema.remove_table(name, options) end + alias_method :drop_table, :remove_table def add_column(table_name, column_name, type, options={}) - column = ColumnDefinition.new(table_name, column_name) - if type.to_s == "references" - table = options.delete(:to) || column_name.pluralize - column.type = Base.groonga_table_name(table) - else - column.type = type + options_with_context = options.merge(:context => Base.context) + Groonga::Schema.change_table(table_name, options_with_context) do |table| + table = TableDefinitionWrapper.new(table) + table.column(column_name, type, options) end - column.create(options) end def remove_column(table_name, *column_names) - column_names.each do |column_name| - ColumnDefinition.new(table_name, column_name).remove + options_with_context = options.merge(:context => Base.context) + Groonga::Schema.change_table(table_name, options_with_context) do |table| + column_names.each do |column_name| + table.remove_column(column_name) + end end end - def add_index(table_name, column_name, options={}) - groonga_table_name = Base.groonga_table_name(table_name) - table = Base.context[groonga_table_name] - column_name = column_name.to_s - column = table.column(column_name) - - base_dir = File.join(Base.metadata_directory, - index_table_name, - table_name) - FileUtils.mkdir_p(base_dir) - - name = "#{table_name}/#{column_name}" - path = File.join(base_dir, "#{column_name}.groonga") - index_column = index_table.define_index_column(name, table, - :path => path, - :compress => "zlib", - # :with_section => true, - # :with_weight => true, - :with_position => true) - index_column.source = column - - record = index_management_table.add - record["table"] = groonga_table_name - record["column"] = column_name - record["index"] = name + def add_index_column(table_name, target_table_name, target_column_name, + options={}) + options_for_table = options.reject {|key, value| key == :name} + options_for_table = options_for_table.merge(:context => Base.context) + Groonga::Schema.change_table(table_name, options_for_table) do |table| + table = TableDefinitionWrapper.new(table) + table.index(target_table_name, target_column_name, options) + end end - def index_management_table - Base.context[groonga_index_management_table_name] + private + def initialize_migrations_table + table_name = Migrator.schema_migrations_table_name + groonga_table_name = Migrator.groonga_schema_migrations_table_name + if Base.context[groonga_table_name].nil? + table_file = File.join(Base.metadata_directory, + "#{table_name}.groonga") + Groonga::Hash.create(:name => groonga_table_name, + :path => table_file, + :key_type => "ShortText") + end end - def index_table - Base.context[groonga_index_table_name] - end - - def indexes(table_or_table_name) - if table_or_table_name.is_a?(String) - table_name = table_or_table_name - table = Base.context[Base.groonga_table_name(table_name)] - else - table = table_or_table_name - table_name = table.name.gsub(/(?:\A<table:|>\z)/, '') + def default_table_options(options) + default_options = {:sub_records => true} + case options[:type] + when :hash, :patricia_trie + default_options[:default_tokenizer] = "TokenBigram" end - indexes = [] - index_management_table.records.each do |record| - next if record["table"] != table.name - indexes << IndexDefinition.new(table_name, record["index"], - false, record["column"]) - end - indexes + default_options end + end - private - def index_management_table_name - Base.table_name_prefix + 'indexes' + Base.table_name_suffix + class TableDefinitionWrapper + def initialize(definition) + @definition = definition end - def groonga_index_management_table_name - Base.groonga_metadata_table_name(index_management_table_name) + def column(name, type, options={}) + column_file = File.join(Base.columns_directory(@definition.name), + "#{name}.groonga") + options = {:path => column_file}.merge(options) + @definition.column(name, type, options) end - def index_table_name - Base.table_name_prefix + 'index' + Base.table_name_suffix + def remove_column(name, options={}) + @definition.remove_column(name, options) end + alias_method :remove_index, :remove_column - def groonga_index_table_name - Base.groonga_metadata_table_name(index_table_name) + def index(target_table_name, target_column_name, options={}) + column_name = options.delete(:name) + column_name ||= [target_table_name, target_column_name].join("_") + column_dir = Base.index_columns_directory(@definition.name, + target_table_name.to_s) + column_file = File.join(column_dir, "#{column_name}.groonga") + options = { + :with_position => true, + :path => column_file, + :name => column_name, + }.merge(options) + target_table = @definition.context[target_table_name] + target_column = target_table.column(target_column_name) + @definition.index(target_column, options) end - def initialize_index_management_table - table_name = index_management_table_name - groonga_table_name = groonga_index_management_table_name - if Base.context[groonga_table_name].nil? - table_file = File.join(Base.metadata_directory, - "#{table_name}.groonga") - table = Groonga::Array.create(:name => groonga_table_name, - :path => table_file) - - base_dir = File.join(Base.metadata_directory, table_name) - FileUtils.mkdir_p(base_dir) - - column_file = File.join(base_dir, "table.groonga") - table.define_column("table", "<shorttext>", :path => column_file) - - column_file = File.join(base_dir, "column.groonga") - table.define_column("column", "<shorttext>", :path => column_file) - - column_file = File.join(base_dir, "index.groonga") - table.define_column("index", "<shorttext>", :path => column_file) - end + def timestamps(*args) + options = args.extract_options! + column(:created_at, :datetime, options) + column(:updated_at, :datetime, options) end - def initialize_index_table - table_name = index_table_name - groonga_table_name = groonga_index_table_name - if Base.context[groonga_table_name].nil? - table_file = File.join(Base.metadata_directory, - "#{table_name}.groonga") - table = Groonga::PatriciaTrie.create(:name => groonga_table_name, - :key_type => "<shorttext>", - # :key_with_sis => true, - # :key_normalize => true, - :path => table_file) - table.default_tokenizer = "<token:bigram>" - - base_dir = File.join(Base.metadata_directory, table_name) - FileUtils.mkdir_p(base_dir) - end + def string(*args) + columns("ShortText", *args) end - def initialize_migrations_table - table_name = Migrator.schema_migrations_table_name - groonga_table_name = Migrator.groonga_schema_migrations_table_name - if Base.context[groonga_table_name].nil? - table_file = File.join(Base.metadata_directory, - "#{table_name}.groonga") - Groonga::Hash.create(:name => groonga_table_name, - :path => table_file, - :key_type => "<shorttext>") - end + def text(*args) + columns("Text", *args) end - end - class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition - undef_method :primary_key, :to_sql, :native - - def initialize(name) - super(nil) - @name = name - @indexes = [] + def integer(*args) + columns("Int32", *args) end - def create - table_file = File.join(Base.tables_directory, "#{@name}.groonga") - Groonga::Array.create(:name => Base.groonga_table_name(@name), - :path => table_file) - @columns.each(&:create) - @indexes.each do |column_name, options| - Schema.add_index(@name.to_s, column_name, options) - end + def float(*args) + columns("Float", *args) end - def column(name, type, options={}) - column = self[name] || ColumnDefinition.new(@name, name) - column.type = type - @columns << column unless @columns.include?(column) - self + def decimal(*args) + columns("Int64", *args) end - def index(column_name, options={}) - @indexes << [column_name.to_s, options] + def time(*args) + columns("Time", *args) end + alias_method :datetime, :time + alias_method :timestamp, :time - def references(*args) - options = args.extract_options! - args.each do |col| - groonga_table_name = Base.groonga_table_name(col.to_s.pluralize) - table = Base.context[groonga_table_name] - column(col, table, options) - end + def binary(*args) + columns("LongText", *args) end - alias :belongs_to :references - end - class ColumnDefinition - attr_accessor :name, :type - - def initialize(table_name, name) - @table_name = table_name - @name = name - @name = @name.to_s if @name.is_a?(Symbol) - @type = nil + def boolean(*args) + columns("Bool", *args) end - def create(options={}) - column_file = File.join(Base.columns_directory(@table_name), - "#{@name}.groonga") - options = options.merge(:path => column_file) - table = Base.context[Base.groonga_table_name(@table_name)] - table.define_column(@name, - normalize_type(@type), - options) + def reference(name, table=nil, options={}) + table = Base.groonga_table_name(table || name.to_s.pluralize) + column(name, table, options) end + alias_method :references, :reference + alias_method :belongs_to, :references - def remove - Base.context[@name].remove - end - - def normalize_type(type) - return type if type.is_a?(Groonga::Object) - case type.to_s - when "string" - "<shorttext>" - when "text" - "<text>" - when "integer" - "<int>" - when "float" - "<float>" - when "decimal" - "<int64>" - when "datetime", "timestamp", "time", "date" - "<time>" - when "binary" - "<longtext>" - when "boolean" - "<int>" - else - type + private + def columns(type, *args) + options = args.extract_options! + column_names = args + column_names.each do |name| + column(name, type, options) end end - end - - class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition - alias_method :column, :columns - alias_method :column=, :columns= end end end