Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rename column fix #120

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/main/java/cz/startnet/utils/pgdiff/PgDiffTables.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import cz.startnet.utils.pgdiff.schema.PgColumnUtils;
import cz.startnet.utils.pgdiff.schema.PgSchema;
import cz.startnet.utils.pgdiff.schema.PgTable;
import cz.startnet.utils.pgdiff.util.ColumnComparator;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.ArrayList;
Expand Down Expand Up @@ -246,8 +247,9 @@ private static void addAlterStorage(final PrintWriter writer,
private static void addCreateTableColumns(final List<String> statements,
final PgDiffArguments arguments, final PgTable oldTable,
final PgTable newTable, final List<PgColumn> dropDefaultsColumns) {
ColumnComparator comparator = new ColumnComparator(oldTable, newTable);
for (final PgColumn column : newTable.getColumns()) {
if (!oldTable.containsColumn(column.getName())) {
if (comparator.hasNotColumn(column.getName())) {
statements.add("\tADD COLUMN "
+ column.getFullDefinition(arguments.isAddDefaults()));

Expand All @@ -269,8 +271,9 @@ private static void addCreateTableColumns(final List<String> statements,
*/
private static void addDropTableColumns(final List<String> statements,
final PgTable oldTable, final PgTable newTable) {
ColumnComparator comparator = new ColumnComparator(newTable, oldTable);
for (final PgColumn column : oldTable.getColumns()) {
if (!newTable.containsColumn(column.getName())) {
if (comparator.hasNotColumn(column.getName())) {
statements.add("\tDROP COLUMN "
+ PgDiffUtils.getQuotedName(column.getName()));
}
Expand All @@ -290,15 +293,26 @@ private static void addDropTableColumns(final List<String> statements,
private static void addModifyTableColumns(final List<String> statements,
final PgDiffArguments arguments, final PgTable oldTable,
final PgTable newTable, final List<PgColumn> dropDefaultsColumns) {
ColumnComparator comparator = new ColumnComparator(oldTable, newTable);
for (final PgColumn newColumn : newTable.getColumns()) {
if (!oldTable.containsColumn(newColumn.getName())) {
if (comparator.hasNotColumn(newColumn.getName())) {
continue;
}

final PgColumn oldColumn = oldTable.getColumn(newColumn.getName());
final PgColumn oldColumn = comparator.getColumn(newColumn.getName());
final String oldColumnName =
PgDiffUtils.getQuotedName(oldColumn.getName());
final String newColumnName =
PgDiffUtils.getQuotedName(newColumn.getName());

if (!oldColumn.getName().equals(newColumn.getName())) {
statements.add("\tRENAME COLUMN " + oldColumnName + " TO " + newColumnName + " /* "
+ MessageFormat.format(
Resources.getString("RenameColumn"),
newTable.getName(), oldColumn.getName(),
newColumn.getName()) + " */");
}

if (!oldColumn.getType().equals(newColumn.getType())) {
statements.add("\tALTER COLUMN " + newColumnName + " TYPE "
+ newColumn.getType() + " /* "
Expand All @@ -307,6 +321,7 @@ private static void addModifyTableColumns(final List<String> statements,
newTable.getName(), oldColumn.getType(),
newColumn.getType()) + " */");
}


final String oldDefault = (oldColumn.getDefaultValue() == null) ? ""
: oldColumn.getDefaultValue();
Expand Down
131 changes: 131 additions & 0 deletions src/main/java/cz/startnet/utils/pgdiff/util/ColumnComparator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* Copyright 2006 StartNet s.r.o.
*
* Distributed under MIT license
*/
package cz.startnet.utils.pgdiff.util;

import cz.startnet.utils.pgdiff.schema.PgColumn;
import cz.startnet.utils.pgdiff.schema.PgTable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
* Compare column tables
*
* @author byorty
*/
public class ColumnComparator {

private HashMap<String, PgColumn> columns;

public ColumnComparator(PgTable oldTable, PgTable newTable) {
this.columns = new HashMap<String, PgColumn>();
HashMap<Integer, PgColumn> diffOldColumns = new HashMap<Integer, PgColumn>();
HashMap<Integer, PgColumn> diffNewColumns = new HashMap<Integer, PgColumn>();
List<PgColumn> newColumns = newTable.getColumns();
for (int i = 0;i < newColumns.size();++i) {
PgColumn newColumn = newTable.getColumns().get(i);
PgColumn oldColumn = oldTable.getColumn(newColumn.getName());
if (null == oldColumn && false == diffNewColumns.containsKey(i)) {
diffNewColumns.put(i, newColumn);
} else {
this.columns.put(newColumn.getName(), oldColumn);
}
}
List<PgColumn> oldColumns = oldTable.getColumns();
for (int i = 0;i < oldColumns.size();++i) {
PgColumn oldColumn = oldColumns.get(i);
if (false == this.columns.containsKey(oldColumn.getName())) {
diffOldColumns.put(i, oldColumn);
}
}
for (Map.Entry<Integer, PgColumn> oldEntry : diffOldColumns.entrySet()) {
Integer oldColumnNumber = oldEntry.getKey();
PgColumn oldColumn = oldEntry.getValue();
String oldColumnName = oldColumn.getName();
char[] oldColumnChars = oldColumnName.toCharArray();
int containsCount = 0;
int diffCount = -1;
HashMap<Integer, HashMap<Integer, PgColumn>> variants = new HashMap<Integer, HashMap<Integer, PgColumn>>();
for (Map.Entry<Integer, PgColumn> newEntry : diffNewColumns.entrySet()) {
Integer newColumnNumber = newEntry.getKey();
PgColumn newColumn = newEntry.getValue();
String newColumnName = newColumn.getName();
char[] newColumnChars = newColumnName.toCharArray();
HashMap<Character, Integer> findChars = new HashMap<Character, Integer>();
for (int i = 0;i < oldColumnChars.length;++i) {
findChars.put(oldColumnChars[i], 0);
for (int j = 0;j < newColumnChars.length;++j) {
if (oldColumnChars[i] == newColumnChars[j]
&& findChars.containsKey(newColumnChars[j])
&& 0 == findChars.get(newColumnChars[j])) {
findChars.put(newColumnChars[j], 1);
}
}
}
int currentContainsCount = 0;
for (Map.Entry<Character, Integer> findChar : findChars.entrySet()) {
currentContainsCount += findChar.getValue();
}
if ((double)currentContainsCount >= (oldColumnName.length() + newColumnName.length()) / 4) {
if (containsCount < currentContainsCount) {
variants.remove(containsCount);
containsCount = currentContainsCount;
HashMap<Integer, PgColumn> map = new HashMap<Integer, PgColumn>();
map.put(newColumnNumber, newColumn);
variants.put(containsCount, map);
} else if (containsCount == currentContainsCount) {
variants.get(containsCount).put(newColumnNumber, newColumn);
}
}
}

for (Map.Entry<Integer, HashMap<Integer, PgColumn>> variantEntry : variants.entrySet()) {
HashMap<Integer, PgColumn> map = variantEntry.getValue();

if (1 == map.size()) {
for (Map.Entry<Integer, PgColumn> entry : map.entrySet()) {
PgColumn pgColumn = entry.getValue();
this.columns.put(pgColumn.getName(), oldTable.getColumn(oldColumnName));
}
} else {
for (Map.Entry<Integer, PgColumn> entry : map.entrySet()) {
Integer pgColumnNumber = entry.getKey();
PgColumn pgColumn = entry.getValue();
if (oldColumnNumber == pgColumnNumber) {
this.columns.put(pgColumn.getName(), oldTable.getColumn(oldColumnName));
} else {
int currentContainsCount = 0;
if (oldColumn.getNullValue() == pgColumn.getNullValue()) {
++currentContainsCount;
}
if (oldColumn.getDefaultValue() == null ? pgColumn.getDefaultValue() == null : oldColumn.getDefaultValue().equals(pgColumn.getDefaultValue())) {
++currentContainsCount;
}
if (oldColumn.getType() == null ? pgColumn.getType() == null : oldColumn.getType().equals(pgColumn.getType())) {
++currentContainsCount;
}
if (3 == currentContainsCount) {
this.columns.put(pgColumn.getName(), oldTable.getColumn(oldColumnName));
}
}
}
}
}
}
}

public boolean hasNotColumn(String name) {
return null == this.getColumn(name);
}

public PgColumn getColumn(String name) {
if (this.columns.containsKey(name)) {
return this.columns.get(name);
} else {
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ NewDatabaseIgnoredStatements=New database ignored statements
ErrorUnknownOption=ERROR: Unknown option
WarningUnableToDetermineStorageType=WARNING: Column {0} in new table has no STORAGE set but in old table storage was set. Unable to determine STORAGE type.
TypeParameterChange=TYPE change - table: {0} original: {1} new: {2}
RenameColumn=RENAME column - table: {0} original: {1} new: {2}
UnsupportedEncoding=Unsupported encoding
CannotReadFile=Cannot read file
FileNotFound=File ''{0}'' not found
Expand Down
4 changes: 3 additions & 1 deletion src/test/java/cz/startnet/utils/pgdiff/PgDiffTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,9 @@ public static Collection<?> parameters() {
// Tests adding new sequence that is owned by table
{"add_owned_sequence", false, true, false, false},
// Tests adding empty table
{"add_empty_table", false, false, false, false}
{"add_empty_table", false, false, false, false},
// Tests rename column
{"modify_column_name", false, false, false, false}
});
}
/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ALTER TABLE testtable
DROP COLUMN meta_title,
RENAME COLUMN filed10 TO filed_11 /* RENAME column - table: testtable original: filed10 new: filed_11 */,
RENAME COLUMN field1 TO field_1 /* RENAME column - table: testtable original: field1 new: field_1 */,
RENAME COLUMN field2 TO field_21 /* RENAME column - table: testtable original: field2 new: field_21 */,
RENAME COLUMN meta_discription TO seo_description /* RENAME column - table: testtable original: meta_discription new: seo_description */,
RENAME COLUMN field_3 TO field3 /* RENAME column - table: testtable original: field_3 new: field3 */;
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
--
-- PostgreSQL database dump
--

SET client_encoding = 'UTF8';
SET check_function_bodies = false;
SET client_min_messages = warning;

--
-- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: postgres
--

COMMENT ON SCHEMA public IS 'Standard public schema';


SET search_path = public, pg_catalog;

SET default_tablespace = '';

SET default_with_oids = false;

--
-- Name: testtable; Type: TABLE; Schema: public; Owner: fordfrog; Tablespace:
--

CREATE TABLE testtable (
filed_11 character varying(100),
field_1 integer,
field_21 integer,
description text,
short_description text,
seo_description text,
field3 character varying(100) DEFAULT 'none'::character varying,
field4 double precision
);


ALTER TABLE public.testtable OWNER TO fordfrog;

--
-- Name: public; Type: ACL; Schema: -; Owner: postgres
--

REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM postgres;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO PUBLIC;


--
-- PostgreSQL database dump complete
--

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
--
-- PostgreSQL database dump
--

SET client_encoding = 'UTF8';
SET check_function_bodies = false;
SET client_min_messages = warning;

--
-- Name: SCHEMA public; Type: COMMENT; Schema: -; Owner: postgres
--

COMMENT ON SCHEMA public IS 'Standard public schema';


SET search_path = public, pg_catalog;

SET default_tablespace = '';

SET default_with_oids = false;

--
-- Name: testtable; Type: TABLE; Schema: public; Owner: fordfrog; Tablespace:
--

CREATE TABLE testtable (
filed10 character varying(100),
field1 integer,
field2 integer,
meta_title text,
description text,
short_description text,
meta_discription text,
field_3 character varying(100) DEFAULT 'none'::character varying,
field4 double precision
);


ALTER TABLE public.testtable OWNER TO fordfrog;

--
-- Name: public; Type: ACL; Schema: -; Owner: postgres
--

REVOKE ALL ON SCHEMA public FROM PUBLIC;
REVOKE ALL ON SCHEMA public FROM postgres;
GRANT ALL ON SCHEMA public TO postgres;
GRANT ALL ON SCHEMA public TO PUBLIC;


--
-- PostgreSQL database dump complete
--

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ CREATE TABLE parenttable2 (
);

ALTER TABLE parenttable
DROP COLUMN id,
ADD COLUMN field3 information_schema.cardinal_number;
RENAME COLUMN id TO field3 /* RENAME column - table: parenttable original: id new: field3 */,
ALTER COLUMN field3 TYPE information_schema.cardinal_number /* TYPE change - table: parenttable original: bigserial new: information_schema.cardinal_number */,
ALTER COLUMN field3 DROP NOT NULL;

ALTER TABLE testtable
NO INHERIT parenttable;
Expand Down