gem "postgres"
require 'postgres'
-
class MysqlReader
class Field
end
fields << desc
end
end
-
+
fields.select {|field| field[:primary_key]}.each do |field|
@reader.mysql.query("SELECT max(`#{field[:name]}`) + 1 FROM `#{name}`") do |res|
field[:maxval] = res.fetch_row[0].to_i
load_indexes unless @indexes
@indexes
end
-
+
def foreign_keys
load_indexes unless @foreign_keys
@foreign_keys
return res.fetch_row[0].to_i
end
end
-
+
def query_for_pager
query = has_id? ? 'WHERE id >= ? AND id < ?' : 'LIMIT ?,?'
"SELECT #{columns.map{|c| "`"+c[:name]+"`"}.join(", ")} FROM `#{name}` #{query}"
counter
end
end
-
+
class Writer
end
-
-
+
+
class PostgresWriter < Writer
def column_description(column)
"#{PGconn.quote_ident(column[:name])} #{column_type_info(column)}"
"text"
when "text"
"text"
+ when "double"
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ "double precision"
+ when /^enum/
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ enum = column[:type].gsub(/enum|\(|\)/, '')
+ max_enum_size = enum.split(',').map{ |check| check.size() -2}.sort[-1]
+ "character varying(#{max_enum_size}), check( #{column[:name]} in (#{enum}))"
when "float"
default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
"real"
end
end
-
+
class PostgresFileWriter < PostgresWriter
def initialize(file)
@f = File.open(file, "w+")
SET standard_conforming_strings = off;
SET check_function_bodies = false;
SET client_min_messages = warning;
-
+
EOF
end
--
-- Name: #{table.name}_#{primary_key}_seq; Type: SEQUENCE; Schema: public
--
-
+
DROP SEQUENCE IF EXISTS #{table.name}_#{primary_key}_seq CASCADE;
-
+
CREATE SEQUENCE #{table.name}_#{primary_key}_seq
INCREMENT BY 1
NO MAXVALUE
SELECT pg_catalog.setval('#{table.name}_#{primary_key}_seq', #{maxval}, true);
-
+
EOF
end
@f << <<-EOF
-- Table: #{table.name}
-
+
-- DROP TABLE #{table.name};
DROP TABLE IF EXISTS #{PGconn.quote_ident(table.name)} CASCADE;
-
+
CREATE TABLE #{PGconn.quote_ident(table.name)} (
EOF
@f << columns
-
+
if primary_index = table.indexes.find {|index| index[:primary]}
@f << ",\n CONSTRAINT #{table.name}_pkey PRIMARY KEY(#{primary_index[:columns].map {|col| PGconn.quote_ident(col)}.join(", ")})"
end
@f << <<-EOF
\n)
WITH (OIDS=FALSE);
-
+
EOF
table.indexes.each do |index|
CREATE #{unique}INDEX #{PGconn.quote_ident(index[:name])} ON #{PGconn.quote_ident(table.name)} (#{index[:columns].map {|col| PGconn.quote_ident(col)}.join(", ")});
EOF
end
-
+
end
def write_indexes(table)
-- Data for Name: #{table.name}; Type: TABLE DATA; Schema: public
--
-COPY #{table.name} (#{table.columns.map {|column| PGconn.quote_ident(column[:name])}.join(", ")}) FROM stdin;
+COPY "#{table.name}" (#{table.columns.map {|column| PGconn.quote_ident(column[:name])}.join(", ")}) FROM stdin;
EOF
reader.paginated_read(table, 1000) do |row, counter|
@f.close
end
end
-
+
class PostgresDbWriter < PostgresWriter
def connection(hostname, login, password, database, port)
database, schema = database.split(":")
raise
end
puts "Created table #{table.name}"
-
+
end
def write_indexes(table)
@conn.close
end
end
-
-
+
+
class Converter
attr_reader :reader, :writer
tables.each do |table|
writer.write_table(table)
end
-
+
_time2 = Time.now
tables.each do |table|
writer.write_contents(table, reader)
end unless @supress_data
-
+
_time3 = Time.now
tables.each do |table|
writer.write_indexes(table)
tables.each do |table|
writer.write_constraints(table)
end
-
-
+
+
writer.close
_time4 = Time.now
puts "Table creation #{((_time2 - _time1) / 60).round} min, loading #{((_time3 - _time2) / 60).round} min, indexing #{((_time4 - _time3) / 60).round} min, total #{((_time4 - _time1) / 60).round} min"
end
end
+
reader = MysqlReader.new('localhost', 'root', nil, 'prophotos')
#writer = PostgresFileWriter.new($ARGV[2] || "output.sql")
writer = PostgresDbWriter.new('localhost', 'prophotos', '123', 'prophotos_development:old')