lib/og/backends/mysql.rb in og-0.8.0 vs lib/og/backends/mysql.rb in og-0.9.3
- old
+ new
@@ -1,41 +1,37 @@
-# code:
# * George Moschovitis <gm@navel.gr>
# * Elias Athanasopoulos <elathan@navel.gr>
-#
-# (c) 2004 Navel, all rights reserved.
-# $Id: mysql.rb 194 2004-12-20 20:23:57Z gmosx $
+# (c) 2004-2005 Navel, all rights reserved.
+# $Id: mysql.rb 248 2005-01-31 13:38:34Z gmosx $
-require "mysql"
+require 'mysql'
-require "og/backend"
+require 'og/backend'
class Og
-# = MysqlBackend
-#
# Implements a MySQL powered backend.
-#
+
class MysqlBackend < Og::Backend
# A mapping between Ruby and SQL types.
- #
+
TYPEMAP = {
- Integer => "integer",
- Fixnum => "integer",
- Float => "float",
- String => "text",
- Time => "timestamp",
- Date => "date",
- TrueClass => "boolean",
- Object => "text",
- Array => "text",
- Hash => "text"
+ Integer => 'integer',
+ Fixnum => 'integer',
+ Float => 'float',
+ String => 'text',
+ Time => 'timestamp',
+ Date => 'date',
+ TrueClass => 'tinyint',
+ Object => 'text',
+ Array => 'text',
+ Hash => 'text'
}
# Intitialize the connection to the RDBMS.
- #
+
def initialize(config)
begin
@conn = Mysql.connect(config[:address], config[:user],
config[:password], config[:database])
rescue => ex
@@ -51,42 +47,42 @@
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Utilities
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Escape an SQL string
- #
+
def self.escape(str)
return nil unless str
return Mysql.quote(str)
end
# Convert a ruby time to an sql timestamp.
# TODO: Optimize this
- #
+
def self.timestamp(time = Time.now)
return nil unless time
return time.strftime("%Y%m%d%H%M%S")
end
# Output YYY-mm-dd
# TODO: Optimize this
- #
+
def self.date(date)
return nil unless date
return "#{date.year}-#{date.month}-#{date.mday}"
end
# Parse sql datetime
# TODO: Optimize this
- #
+
def self.parse_timestamp(str)
return Time.parse(str)
end
# Input YYYY-mm-dd
# TODO: Optimize this
- #
+
def self.parse_date(str)
return nil unless str
return Date.strptime(str)
end
@@ -94,11 +90,11 @@
# No need to optimize this, used only to precalculate code.
# YAML is used to store general Ruby objects to be more
# portable.
#
# FIXME: add extra handling for float.
- #
+
def self.write_prop(p)
if p.klass.ancestors.include?(Integer)
return "#\{@#{p.symbol} || 'NULL'\}"
elsif p.klass.ancestors.include?(Float)
return "#\{@#{p.symbol} || 'NULL'\}"
@@ -107,19 +103,19 @@
elsif p.klass.ancestors.include?(Time)
return %|#\{@#{p.symbol} ? "'#\{Og::MysqlBackend.timestamp(@#{p.symbol})\}'" : 'NULL'\}|
elsif p.klass.ancestors.include?(Date)
return %|#\{@#{p.symbol} ? "'#\{Og::MysqlBackend.date(@#{p.symbol})\}'" : 'NULL'\}|
elsif p.klass.ancestors.include?(TrueClass)
- return "#\{@#{p.symbol} || 'NULL'\}"
+ return "#\{@#{p.symbol} ? 1 : 0 \}"
else
return %|#\{@#{p.symbol} ? "'#\{Og::MysqlBackend.escape(@#{p.symbol}.to_yaml)\}'" : "''"\}|
end
end
# Return an evaluator for reading the property.
# No need to optimize this, used only to precalculate code.
- #
+
def self.read_prop(p, idx)
if p.klass.ancestors.include?(Integer)
return "res[#{idx}].to_i()"
elsif p.klass.ancestors.include?(Float)
return "res[#{idx}].to_f()"
@@ -128,27 +124,27 @@
elsif p.klass.ancestors.include?(Time)
return "Og::MysqlBackend.parse_timestamp(res[#{idx}])"
elsif p.klass.ancestors.include?(Date)
return "Og::MysqlBackend.parse_date(res[#{idx}])"
elsif p.klass.ancestors.include?(TrueClass)
- return "('true' == res[#{idx}])"
+ return "('0' != res[#{idx}])"
else
return "YAML::load(res[#{idx}])"
end
end
# Returns the props that will be included in the insert query.
# The oid property is rejected because it is mapped to an
# AUTO_INCREMENT column.
- #
+
def self.props_for_insert(klass)
klass.__props.reject { |p| :oid == p.symbol }
end
- # Returns the code that actually inserts the object into the
+ # Returns the code that actually inserts the object into the
# database. Returns the code as String.
- #
+
def self.insert_code(klass, sql, pre_cb, post_cb)
%{
#{pre_cb}
conn.exec "#{sql}"
@oid = conn.db.conn.insert_id()
@@ -156,22 +152,22 @@
}
end
# generate the mapping of the database fields to the
# object properties.
- #
+
def self.calc_field_index(klass, og)
res = og.query "SELECT * FROM #{klass::DBTABLE} LIMIT 1"
meta = og.managed_classes[klass]
for idx in (0...res.num_fields)
meta.field_index[res.fetch_field.name] = idx
end
end
- # Generate the property for oid
- #
+ # Generate the property for oid.
+
def self.eval_og_oid(klass)
klass.class_eval %{
prop_accessor :oid, Fixnum, :sql => "integer AUTO_INCREMENT PRIMARY KEY"
}
end
@@ -179,40 +175,40 @@
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Connection methods.
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Create the database.
- #
+
def self.create_db(database, user = nil, password = nil)
Logger.info "Creating database '#{database}'."
`mysqladmin -f --user=#{user} --password=#{password} create #{database}`
end
# Drop the database.
- #
+
def self.drop_db(database, user = nil, password = nil)
Logger.info "Dropping database '#{database}'."
`mysqladmin -f --user=#{user} --password=#{password} drop #{database}`
end
# Execute an SQL query and return the result
- #
+
def query(sql)
Logger.debug sql if $DBG
return @conn.query(sql)
end
# Execute an SQL query, no result returned.
- #
+
def exec(sql)
Logger.debug sql if $DBG
@conn.query(sql)
end
# Execute an SQL query and return the result. Wrapped in a rescue
# block.
- #
+
def safe_query(sql)
Logger.debug sql if $DBG
begin
return @conn.query(sql)
rescue => ex
@@ -222,11 +218,11 @@
end
end
# Execute an SQL query, no result returned. Wrapped in a rescue
# block.
- #
+
def safe_exec(sql)
Logger.debug sql if $DBG
begin
@conn.query(sql)
rescue => ex
@@ -234,37 +230,37 @@
Logger.error ex.backtrace
end
end
# Check if it is a valid resultset.
- #
+
def valid?(res)
return !(res.nil? or 0 == res.num_rows)
end
# Start a new transaction.
- #
+
def start
# no transaction support
end
# Commit a transaction.
- #
+
def commit
# no transaction support
end
# Rollback transaction.
- #
+
def rollback
# no transaction support
end
# Create the managed object table. The properties of the
# object are mapped to the table columns. Additional sql relations
# and constrains are created (indicices, sequences, etc).
- #
+
def create_table(klass)
fields = create_fields(klass, TYPEMAP)
sql = "CREATE TABLE #{klass::DBTABLE} (#{fields.join(', ')}"
@@ -326,11 +322,11 @@
end
end
end
# Deserialize one row of the resultset.
- #
+
def deserialize_one(res, klass)
return nil unless valid?(res)
# gmosx: Managed objects should have no params constructor.
row = res.fetch_row()
@@ -341,13 +337,13 @@
return entity
end
# Deserialize all rows of the resultset.
- #
+
def deserialize_all(res, klass)
- return nil unless valid?(res)
+ return [] unless valid?(res)
entities = []
for tuple in (0...res.num_rows)
row = res.fetch_row()
@@ -362,13 +358,13 @@
return entities
end
# Return a single integer value from the resultset.
- #
+
def get_int(res, idx = 0)
return res.fetch_row[idx].to_i
end
end
-end # module
+end