lib/og/store/mysql.rb in og-0.23.0 vs lib/og/store/mysql.rb in og-0.24.0
- old
+ new
@@ -1,10 +1,10 @@
begin
require 'mysql'
rescue Object => ex
Logger.error 'Ruby-Mysql bindings are not installed!'
- Logger.error 'Trying to uses the pure-Ruby binding included in Og'
+ Logger.error 'Trying to use the pure-Ruby binding included in Og'
begin
# Attempt to use the included pure ruby version.
require 'vendor/mysql'
require 'vendor/mysql411'
rescue Object => ex
@@ -85,12 +85,23 @@
end
end
end
# A Store that persists objects into a MySQL database.
-# To read documentation about the methods, consult the documentation
-# for SqlStore and Store.
+# To read documentation about the methods, consult
+# the documentation for SqlStore and Store.
+#
+# Here is some useful code to initialize your MySQL
+# RDBMS for development. You probably want to be
+# more careful with provileges on your production
+# environment.
+#
+# mysql> GRANT ALL PRIVELEGES
+# ON keystone.*
+# TO <$sys_dbuser name>@localhost
+# IDENTIFIED BY '(password)'
+# WITH GRANT OPTION;
class MysqlStore < SqlStore
extend MysqlUtils
include MysqlUtils
@@ -107,22 +118,34 @@
"--password=#{options[:password]}", 'drop',
options[:name]
super
end
+ # Initialize the MySQL store.
+ #
+ # === Options
+ #
+ # * :address, the addres where the server is listening.
+ # * :socket, is useful when the pure ruby driver is used.
+ # this is the location of mysql.sock. For Ubuntu/Debian
+ # this is '/var/run/mysqld/mysqld.sock'. You can find
+ # the location for your system in my.cnf
+
def initialize(options)
super
@typemap.update(TrueClass => 'tinyint')
@conn = Mysql.connect(
options[:address] || 'localhost',
options[:user],
options[:password],
- options[:name]
+ options[:name],
+ options[:port],
+ options[:socket]
)
-
+
# You should set recconect to true to avoid MySQL has
# gone away errors.
if @conn.respond_to? :reconnect
options[:reconnect] = true unless options.has_key?(:reconnect)
@@ -141,13 +164,13 @@
def close
@conn.close
super
end
- def enchant(klass, manager)
- if klass.metadata.primary_key.flatten.first == :oid
- unless klass.properties.find { |p| p.symbol == :oid }
+ def enchant(klass, manager)
+ if klass.ann.this.primary_key.symbol == :oid
+ unless klass.properties.include? :oid
klass.property :oid, Fixnum, :sql => 'integer AUTO_INCREMENT PRIMARY KEY'
end
end
super
end
@@ -193,29 +216,38 @@
end
private
def create_table(klass)
+ # rp: fixes problems when user doesn't have
+ # write access to db.
+ # THINK, should a method more like this be
+ # used instead of catching database exceptions
+ # for 'table exists'?
+
+ return if @conn.list_tables.include?(klass::OGTABLE)
+
+
fields = fields_for_class(klass)
sql = "CREATE TABLE #{klass::OGTABLE} (#{fields.join(', ')}"
- # Create table constrains.
+ # Create table constraints.
- if klass.metadata and constrains = klass.metadata.sql_constrain
- sql << ", #{constrains.join(', ')}"
+ if constraints = klass.ann.this[:sql_constraint]
+ sql << ", #{constraints.join(', ')}"
end
if table_type = @options[:table_type]
sql << ") TYPE = #{table_type};"
else
sql << ");"
end
# Create indices.
- if klass.__meta and indices = klass.__meta[:index]
+ if indices = klass.ann.this[:index]
for data in indices
idx, options = *data
idx = idx.to_s
pre_sql, post_sql = options[:pre], options[:post]
idxname = idx.gsub(/ /, "").gsub(/,/, "_").gsub(/\(.*\)/, "")
@@ -238,20 +270,20 @@
end
# Create join tables if needed. Join tables are used in
# 'many_to_many' relations.
- if klass.__meta and join_tables = klass.__meta[:join_tables]
+ if join_tables = klass.ann.this[:join_tables]
for info in join_tables
begin
create_join_table_sql(info).each do |sql|
@conn.query sql
end
Logger.debug "Created jointable '#{info[:table]}'."
rescue => ex
- if ex.respond_to?(:errno) and ex.errno == 1050 # table already exists.
- Logger.debug 'Join table already exists' if $DBG
+ if ex.respond_to?(:errno) and ex.errno == 1050 # table already exists.
+ Logger.debug 'Join table already exists' if $DBG
else
raise
end
end
end
@@ -272,24 +304,24 @@
res.close if res
end
def write_prop(p)
if p.klass.ancestors.include?(Integer)
- return "#\{@#{p.symbol} || 'NULL'\}"
+ return "#\{@#{p} || 'NULL'\}"
elsif p.klass.ancestors.include?(Float)
- return "#\{@#{p.symbol} || 'NULL'\}"
+ return "#\{@#{p} || 'NULL'\}"
elsif p.klass.ancestors.include?(String)
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.escape(@#{p.symbol})\}'" : 'NULL'\}|
+ return %|#\{@#{p} ? "'#\{#{self.class}.escape(@#{p})\}'" : 'NULL'\}|
elsif p.klass.ancestors.include?(Time)
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.timestamp(@#{p.symbol})\}'" : 'NULL'\}|
+ return %|#\{@#{p} ? "'#\{#{self.class}.timestamp(@#{p})\}'" : 'NULL'\}|
elsif p.klass.ancestors.include?(Date)
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.date(@#{p.symbol})\}'" : 'NULL'\}|
+ return %|#\{@#{p} ? "'#\{#{self.class}.date(@#{p})\}'" : 'NULL'\}|
elsif p.klass.ancestors.include?(TrueClass)
- return "#\{@#{p.symbol} ? \"'1'\" : 'NULL' \}"
+ return "#\{@#{p} ? \"'1'\" : 'NULL' \}"
else
# gmosx: keep the '' for nil symbols.
- return %|#\{@#{p.symbol} ? "'#\{#{self.class}.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
+ return %|#\{@#{p} ? "'#\{#{self.class}.escape(@#{p}.to_yaml)\}'" : "''"\}|
end
end
def read_prop(p, col)
if p.klass.ancestors.include?(Integer)
@@ -301,30 +333,29 @@
elsif p.klass.ancestors.include?(Time)
return "#{self.class}.parse_timestamp(res[#{col} + offset])"
elsif p.klass.ancestors.include?(Date)
return "#{self.class}.parse_date(res[#{col} + offset])"
elsif p.klass.ancestors.include?(TrueClass)
- return "('0' != res[#{col} + offset])"
+ return "('1' == res[#{col} + offset])"
else
return "YAML.load(res[#{col} + offset])"
end
end
def eval_og_insert(klass)
- props = klass.properties.dup
+ props = klass.properties.values
values = props.collect { |p| write_prop(p) }.join(',')
- if klass.metadata.superclass or klass.metadata.subclasses
- props << Property.new(:ogtype, String)
+ if klass.schema_inheritance?
+ props << Property.new(:symbol => :ogtype, :klass => String)
values << ", '#{klass}'"
end
sql = "INSERT INTO #{klass::OGTABLE} (#{props.collect {|p| field_for_property(p)}.join(',')}) VALUES (#{values})"
klass.class_eval %{
def og_insert(store)
#{Aspects.gen_advice_code(:og_insert, klass.advices, :pre) if klass.respond_to?(:advices)}
- puts "#{sql}"
store.conn.query_with_result = false
store.conn.query "#{sql}"
@#{klass.pk_symbol} = store.conn.insert_id
#{Aspects.gen_advice_code(:og_insert, klass.advices, :post) if klass.respond_to?(:advices)}
end