class Writer
end
-class PostgresFileWriter < Writer
+
+class PostgresWriter < Writer
+ def column_description(column)
+ "#{PGconn.quote_ident(column[:name])} #{column_type_info(column)}"
+ end
+
+ def column_type(column)
+ column_type_info(column).split(" ").first
+ end
+
+ def column_type_info(column)
+ if column[:primary_key] && column[:name] == "id"
+ return "integer DEFAULT nextval('#{column[:table_name]}_#{column[:name]}_seq'::regclass) NOT NULL"
+ end
+
+ default = column[:default] ? " DEFAULT #{column[:default] == nil ? 'NULL' : "'"+column[:default]+"'"}" : nil
+ null = column[:null] ? "" : " NOT NULL"
+ type =
+ case column[:type]
+ when "var_string"
+ default = default + "::character varying" if default
+ "character varying(#{column[:length]})"
+ when "long"
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ "bigint"
+ when "longlong"
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ "bigint"
+ when "datetime"
+ default = nil
+ "timestamp without time zone"
+ when "date"
+ default = nil
+ "date"
+ when "char"
+ if column[:length] == 1
+ if default
+ default = " DEFAULT #{column[:default].to_i == 1 ? 'true' : 'false'}"
+ end
+ "boolean"
+ else
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ "int"
+ end
+ when "blob"
+ "bytea"
+ when "text"
+ "text"
+ when "float"
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ "numeric(#{column[:length] + column[:decimals]}, #{column[:decimals]})"
+ when "decimal"
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ "numeric(#{column[:length] + column[:decimals]}, #{column[:decimals]})"
+ when "int24"
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
+ "int"
+ else
+ puts "Unknown #{column.inspect}"
+ column[:type].inspect
+ return ""
+ end
+ "#{type}#{default}#{null}"
+ end
+
+end
+
+class PostgresFileWriter < PostgresWriter
def initialize(file)
@f = File.open(file, "w+")
@f << <<-EOF
end
- def column_description(column)
- "#{PGconn.quote_ident(column[:name])} #{column_type(column)}"
- end
-
- def column_type(column)
- case
- when column[:primary_key] && column[:name] == "id"
- "integer DEFAULT nextval('#{column[:table_name]}_#{column[:name]}_seq'::regclass) NOT NULL"
- else
- default = column[:default] ? " DEFAULT #{column[:default] == nil ? 'NULL' : "'"+column[:default]+"'"}" : nil
- null = column[:null] ? "" : " NOT NULL"
- type =
- case column[:type]
- when "var_string"
- default = default + "::character varying" if default
- "character varying(#{column[:length]})"
- when "long"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "bigint"
- when "longlong"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "bigint"
- when "datetime"
- default = nil
- "timestamp without time zone"
- when "date"
- default = nil
- "date"
- when "char"
- if default
- default = " DEFAULT #{column[:default].to_i == 1 ? 'true' : 'false'}"
- end
- "boolean"
- when "blob"
- "bytea"
- when "text"
- "text"
- when "float"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "numeric(#{column[:length] + column[:decimals]}, #{column[:decimals]})"
- when "decimal"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "numeric(#{column[:length] + column[:decimals]}, #{column[:decimals]})"
- else
- puts column.inspect
- column[:type].inspect
- end
- "#{type}#{default}#{null}"
- end
- end
-
def write_contents(table, reader)
@f << <<-EOF
--
end
end
-class PostgresDbWriter < Writer
- def initialize(hostname, login, password, database)
+class PostgresDbWriter < PostgresWriter
+ def connection(hostname, login, password, database)
require 'postgres'
@conn = PGconn.open('host' => hostname, 'user' => login, 'password' => password, 'dbname' => database)
+ end
+
+ def initialize(hostname, login, password, database)
+ @conn = connection(hostname, login, password, database)
@conn.exec("SET client_encoding = 'UTF8'")
@conn.exec("SET standard_conforming_strings = off")
@conn.exec("SET check_function_bodies = false")
end
end
- def column_description(column)
- "#{PGconn.quote_ident(column[:name])} #{column_type(column)}"
- end
-
- def column_type(column)
- case
- when column[:primary_key] && column[:name] == "id"
- "integer DEFAULT nextval('#{column[:table_name]}_#{column[:name]}_seq'::regclass) NOT NULL"
- else
- default = column[:default] ? " DEFAULT #{column[:default] == nil ? 'NULL' : "'"+column[:default]+"'"}" : nil
- null = column[:null] ? "" : " NOT NULL"
- type =
- case column[:type]
- when "var_string"
- default = default + "::character varying" if default
- "character varying(#{column[:length]})"
- when "long"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "bigint"
- when "longlong"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "bigint"
- when "datetime"
- default = nil
- "timestamp without time zone"
- when "date"
- default = nil
- "date"
- when "char"
- if default
- default = " DEFAULT #{column[:default].to_i == 1 ? 'true' : 'false'}"
- end
- "boolean"
- when "blob"
- "bytea"
- when "text"
- "text"
- when "float"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "numeric(#{column[:length] + column[:decimals]}, #{column[:decimals]})"
- when "decimal"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "numeric(#{column[:length] + column[:decimals]}, #{column[:decimals]})"
- when "int24"
- default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
- "int"
- else
- puts column.inspect
- column[:type].inspect
- end
- "#{type}#{default}#{null}"
- end
- end
-
def write_contents(table, reader)
_time1 = Time.now
copy_line = "COPY #{table.name} (#{table.columns.map {|column| PGconn.quote_ident(column[:name])}.join(", ")}) FROM stdin;"
_counter = reader.paginated_read(table, 1000) do |row, counter|
line = []
table.columns.each_with_index do |column, index|
- row[index] = row[index].to_s if row[index].is_a?(Mysql::Time)
- if column[:type] == "char"
+ if !row[index]
+ row[index] = '\N'
+ next
+ end
+ if row[index].is_a?(Mysql::Time)
+ row[index] = row[index].to_s
+ next
+ end
+
+ if column_type(column) == "boolean"
row[index] = row[index] == 1 ? 't' : row[index] == 0 ? 'f' : row[index]
+ next
+ end
+
+ if row[index].is_a?(String)
+ if column_type(column) == "bytea"
+ row[index] = PGconn.quote(row[index])
+ else
+ row[index] = row[index].gsub(/\\/, '\\\\\\').gsub(/\n/,'\n').gsub(/\t/,'\t').gsub(/\r/,'\r')
+ end
end
- row[index] = row[index].gsub(/\\/, '\\\\\\').gsub(/\n/,'\n').gsub(/\t/,'\t').gsub(/\r/,'\r') if row[index].is_a?(String)
- row[index] = '\N' if !row[index]
- row[index]
end
- @conn.putline row.join("\t") + "\n"
+ @conn.putline(row.join("\t") + "\n")
if counter % 5000 == 0
print "*"