Skip to content

Commit 4a8c5e9

Browse files
committed
Impl. of DBRestore(Domain|Enum|UDT)Postgres
Fix of some new implementations errors Improve test case with custom types
1 parent fbff854 commit 4a8c5e9

File tree

8 files changed

+421
-42
lines changed

8 files changed

+421
-42
lines changed

src/main/java/ru/fusionsoft/dbgit/adapters/DBAdapter.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ private void printRestoreMessage(IMetaObject obj) {
169169
if(obj instanceof MetaView){ leafName = "restoreView"; }
170170
if(obj instanceof MetaTrigger){ leafName = "restoreTrigger"; }
171171
if(obj instanceof MetaSchema){ leafName = "restoreSchema"; }
172-
if(obj instanceof MetaSchema){ leafName = "restoreUDT"; }
172+
if(obj instanceof MetaUDT){ leafName = "restoreUDT"; }
173173
if(obj instanceof MetaEnum){ leafName = "restoreEnum"; }
174174
if(obj instanceof MetaDomain){ leafName = "restoreDomain"; }
175175
if(obj instanceof MetaRole){ leafName = "restoreRole"; }

src/main/java/ru/fusionsoft/dbgit/postgres/DBAdapterPostgres.java

Lines changed: 95 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1013,8 +1013,68 @@ public Map<String, DBRole> getRoles() {
10131013

10141014
@Override
10151015
public Map<String, DBUserDefinedType> getUDTs(String schema) {
1016-
System.out.println("getting UDT's");
1017-
return Collections.emptyMap();
1016+
final Map<String, DBUserDefinedType> objects = new HashMap<>();
1017+
final String query =
1018+
"SELECT \n"
1019+
+ " n.nspname AS schema,\n"
1020+
+ " t.typname AS name, \n"
1021+
+ " r.rolname AS owner,\n"
1022+
+ " pg_catalog.obj_description ( t.oid, 'pg_type' ) AS description\n"
1023+
+ "FROM pg_type t \n"
1024+
+ "LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace \n"
1025+
+ "LEFT JOIN pg_roles r ON r.oid = t.typowner\n"
1026+
+ "WHERE (t.typrelid = 0 OR (SELECT c.relkind = 'c' FROM pg_catalog.pg_class c WHERE c.oid = t.typrelid)) \n"
1027+
+ "AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_type el WHERE el.oid = t.typelem AND el.typarray = t.oid)\n"
1028+
+ "AND t.typtype = 'c'\n"
1029+
+ "AND n.nspname = '"+schema+"'";
1030+
1031+
try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) {
1032+
while (rs.next()) {
1033+
final String name = rs.getString("name");
1034+
final String owner = rs.getString("owner");
1035+
final List<String> attributesSqls = new ArrayList<>();
1036+
final String attributesQuery =
1037+
"SELECT \n"
1038+
+ " attribute_name AS \"name\", \n"
1039+
+ " data_type AS \"type\", \n"
1040+
+ " ordinal_position AS \"order\"\n"
1041+
+ "FROM information_schema.attributes a\n"
1042+
+ "WHERE udt_schema = '"+schema+"' AND udt_name = '"+name+"'\n"
1043+
+ "ORDER BY ordinal_position";
1044+
try (Statement stmt2 = getConnection().createStatement(); ResultSet attributeRs = stmt2.executeQuery(
1045+
attributesQuery)) {
1046+
while (attributeRs.next()) {
1047+
final String attrName = attributeRs.getString("name");
1048+
final String attrType = attributeRs.getString("type");
1049+
final String udtAttrDefinition = MessageFormat.format(
1050+
"{0} {1}",
1051+
escapeNameIfNeeded(attrName),
1052+
attrType
1053+
);
1054+
attributesSqls.add(udtAttrDefinition);
1055+
}
1056+
}
1057+
final StringProperties options = new StringProperties();
1058+
final String sql = MessageFormat.format(
1059+
"CREATE TYPE {0}.{1} AS (\n{2}\n);\n"
1060+
+ "ALTER TYPE {0}.{1} OWNER TO {3};",
1061+
escapeNameIfNeeded(schema),
1062+
escapeNameIfNeeded(name),
1063+
String.join(",\n ", attributesSqls),
1064+
owner
1065+
);
1066+
1067+
DBUserDefinedType object = new DBUserDefinedType(name, options, schema, owner, Collections.emptySet(), sql);
1068+
options.addChild("attributes", String.join(",", attributesSqls));
1069+
options.addChild("description", rs.getString("description"));
1070+
objects.put(name, object);
1071+
}
1072+
1073+
} catch (Exception e) {
1074+
throw new ExceptionDBGitRunTime(e);
1075+
}
1076+
1077+
return objects;
10181078
}
10191079

10201080
@Override
@@ -1024,7 +1084,7 @@ public Map<String, DBDomain> getDomains(String schema) {
10241084
final String query =
10251085
"SELECT \n"
10261086
+ " n.nspname,\n"
1027-
+ " t.typname, \n"
1087+
+ " t.typname, \n"
10281088
+ " dom.data_type, \n"
10291089
+ " dom.domain_default,\n"
10301090
+ " r.rolname,\n"
@@ -1038,7 +1098,6 @@ public Map<String, DBDomain> getDomains(String schema) {
10381098
+ "AND n.nspname NOT IN ('pg_catalog', 'information_schema')\n"
10391099
+ "AND dom.domain_schema = '"+schema+"'";
10401100

1041-
System.out.println("query = " + query);
10421101
try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) {
10431102

10441103
while (rs.next()) {
@@ -1059,16 +1118,14 @@ public Map<String, DBDomain> getDomains(String schema) {
10591118
final String conName = conRs.getString("conname");
10601119
final String conSrc = conRs.getString("consrc");
10611120
final Boolean conIsValidated = conRs.getBoolean("convalidated");
1062-
final String conSql = MessageFormat.format(
1121+
constraintSqls.add(MessageFormat.format(
10631122
"ALTER DOMAIN {0}.{1} ADD CONSTRAINT {2} CHECK {3} {4};",
1064-
escapeNameIfNeeded(schema),
1065-
escapeNameIfNeeded(name),
1066-
escapeNameIfNeeded(conName),
1067-
conSrc,
1123+
escapeNameIfNeeded(schema),
1124+
escapeNameIfNeeded(name),
1125+
escapeNameIfNeeded(conName),
1126+
conSrc,
10681127
conIsValidated ? "" : "NOT VALID"
1069-
);
1070-
constraintSqls.add(conSql);
1071-
System.out.println("conSql = " + conSql);
1128+
));
10721129
}
10731130
}
10741131

@@ -1078,7 +1135,6 @@ public Map<String, DBDomain> getDomains(String schema) {
10781135
escapeNameIfNeeded(schema), escapeNameIfNeeded(name), type, defaultValue != null ? "DEFAULT " + defaultValue : "", owner,
10791136
String.join("\n", constraintSqls)
10801137
);
1081-
System.out.println("sql = " + sql);
10821138

10831139
DBDomain object = new DBDomain(name, options, schema, owner, Collections.emptySet(), sql);
10841140
objects.put(name, object);
@@ -1112,23 +1168,23 @@ public Map<String, DBEnum> getEnums(String schema) {
11121168
+ "AND n.nspname = '"+schema+"'"
11131169
+ "AND t.typtype = 'e'";
11141170

1115-
System.out.println("query = " + query);
11161171
try (Statement stmt = getConnection().createStatement(); ResultSet rs = stmt.executeQuery(query);) {
11171172

11181173
while (rs.next()) {
11191174
final String name = rs.getString("typname");
11201175
final String owner = rs.getString("rolname");
1121-
final StringProperties options = new StringProperties(rs);
1122-
final List<String> elements = Arrays.stream((String[]) rs.getArray("elements").getArray())
1123-
.map( x->"'"+x+"'")
1124-
.collect(Collectors.toList());
1176+
final String elements = String.join(
1177+
",",
1178+
Arrays.stream((String[]) rs.getArray("elements").getArray()).map( x->"'"+x+"'").collect(Collectors.toList())
1179+
);
1180+
final StringProperties options = new StringProperties();
11251181
final String sql = MessageFormat.format(
1126-
"CREATE TYPE {0}.{1} AS ENUM ({2});\nALTER TYPE {0}.{1} ONWER TO {3}",
1127-
schema, name, String.join(",", elements), owner
1182+
"CREATE TYPE {0}.{1} AS ENUM ({2});\nALTER TYPE {0}.{1} OWNER TO {3}",
1183+
schema, name, elements, owner
11281184
);
1129-
System.out.println("sql = " + sql);
11301185

11311186
DBEnum object = new DBEnum(name, options, schema, owner, Collections.emptySet(), sql);
1187+
options.addChild("elements", elements);
11321188
objects.put(name, object);
11331189
}
11341190

@@ -1141,20 +1197,32 @@ public Map<String, DBEnum> getEnums(String schema) {
11411197

11421198
@Override
11431199
public DBUserDefinedType getUDT(String schema, String name) {
1144-
final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString();
1145-
throw new ExceptionDBGitObjectNotFound(msg);
1200+
final Map<String, DBUserDefinedType> udTs = getUDTs(schema);
1201+
if (udTs.containsKey(name)) {
1202+
return udTs.get(name);
1203+
} else {
1204+
throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString());
1205+
}
11461206
}
11471207

11481208
@Override
11491209
public DBDomain getDomain(String schema, String name) {
1150-
final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString();
1151-
throw new ExceptionDBGitObjectNotFound(msg);
1210+
final Map<String, DBDomain> domains = getDomains(schema);
1211+
if (domains.containsKey(name)) {
1212+
return domains.get(name);
1213+
} else {
1214+
throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString());
1215+
}
11521216
}
11531217

11541218
@Override
11551219
public DBEnum getEnum(String schema, String name) {
1156-
final String msg = lang.getValue("errors", "adapter", "objectNotFoundInDb").toString();
1157-
throw new ExceptionDBGitObjectNotFound(msg);
1220+
final Map<String, DBEnum> enums = getEnums(schema);
1221+
if (enums.containsKey(name)) {
1222+
return enums.get(name);
1223+
} else {
1224+
throw new ExceptionDBGitObjectNotFound(lang.getValue("errors", "adapter", "objectNotFoundInDb").toString());
1225+
}
11581226
}
11591227

11601228
@Override
Lines changed: 109 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,122 @@
11
package ru.fusionsoft.dbgit.postgres;
22

3+
import java.sql.Connection;
4+
import java.text.MessageFormat;
5+
import java.util.Map;
36
import ru.fusionsoft.dbgit.adapters.DBRestoreAdapter;
4-
import ru.fusionsoft.dbgit.core.NotImplementedExceptionDBGitRuntime;
7+
import ru.fusionsoft.dbgit.adapters.IDBAdapter;
8+
import ru.fusionsoft.dbgit.core.DBGitConfig;
9+
import ru.fusionsoft.dbgit.core.ExceptionDBGitRestore;
10+
import ru.fusionsoft.dbgit.dbobjects.DBDomain;
11+
import ru.fusionsoft.dbgit.dbobjects.DBSQLObject;
512
import ru.fusionsoft.dbgit.meta.IMetaObject;
13+
import ru.fusionsoft.dbgit.meta.MetaDomain;
14+
import ru.fusionsoft.dbgit.statement.StatementLogging;
15+
import ru.fusionsoft.dbgit.utils.ConsoleWriter;
616

717
public class DBRestoreDomainPostgres extends DBRestoreAdapter {
818
@Override
919
public final boolean restoreMetaObject(IMetaObject obj, int step) throws Exception {
10-
throw new NotImplementedExceptionDBGitRuntime();
20+
final IDBAdapter adapter = getAdapter();
21+
final Connection connect = adapter.getConnection();
22+
try (final StatementLogging st = new StatementLogging(
23+
connect,
24+
adapter.getStreamOutputSqlCommand(),
25+
adapter.isExecSql()
26+
)) {
27+
if (! ( obj instanceof MetaDomain )) {
28+
throw new ExceptionDBGitRestore(
29+
lang.getValue("errors", "restore", "metaTypeError").withParams(
30+
obj.getName(),
31+
"view",
32+
obj.getType().getValue()
33+
)
34+
);
35+
}
36+
final DBSQLObject restoreDomain = (DBSQLObject) obj.getUnderlyingDbObject();
37+
final Map<String, DBDomain> domains = adapter.getDomains(restoreDomain.getSchema());
38+
39+
if (domains.containsKey(restoreDomain.getName())) {
40+
final DBDomain currentDomain = domains.get(restoreDomain.getName());
41+
if (
42+
! restoreDomain.getOptions().get("attributes").equals(
43+
currentDomain.getOptions().get("attributes")
44+
)
45+
) {
46+
st.execute(MessageFormat.format(
47+
"DROP DOMAIN IF EXISTS {0}._deprecated_{1} RESTRICT;\n"
48+
+ "ALTER DOMAIN {0}.{1} RENAME TO _deprecated_{1};\n"
49+
+ "{2}",
50+
currentDomain.getSchema(), currentDomain.getName(), getDdlEscaped(restoreDomain)
51+
));
52+
} else {
53+
if (! DBGitConfig.getInstance().getToIgnoreOnwer(false)) {
54+
st.execute(getChangeOwnerDdl(currentDomain, restoreDomain.getOwner()));
55+
}
56+
}
57+
} else {
58+
st.execute(getDdlEscaped(restoreDomain));
59+
}
60+
61+
} catch (Exception e) {
62+
throw new ExceptionDBGitRestore(
63+
lang.getValue("errors", "restore", "objectRestoreError").withParams(obj.getName()),
64+
e
65+
);
66+
} finally {
67+
ConsoleWriter.detailsPrintGreen(lang.getValue("general", "ok"));
68+
}
69+
return true;
1170
}
1271

1372
@Override
14-
public final void removeMetaObject(IMetaObject obj) throws Exception {
15-
throw new NotImplementedExceptionDBGitRuntime();
73+
public void removeMetaObject(IMetaObject obj) throws Exception {
74+
final IDBAdapter adapter = getAdapter();
75+
final Connection connect = adapter.getConnection();
76+
77+
try (StatementLogging st = new StatementLogging(
78+
connect,
79+
adapter.getStreamOutputSqlCommand(),
80+
adapter.isExecSql()
81+
)) {
82+
83+
final DBSQLObject currentObject = (DBSQLObject) obj.getUnderlyingDbObject();
84+
st.execute(MessageFormat.format(
85+
"DROP DOMAIN IF EXISTS {0}.{1} RESTRICT",
86+
adapter.escapeNameIfNeeded(getPhisicalSchema(currentObject.getSchema())),
87+
adapter.escapeNameIfNeeded(currentObject.getName())
88+
));
89+
90+
} catch (Exception e) {
91+
throw new ExceptionDBGitRestore(
92+
lang.getValue("errors", "restore", "objectRemoveError")
93+
.withParams(obj.getName()), e);
94+
}
95+
}
96+
97+
private String getDdlEscaped(DBSQLObject dbsqlObject) {
98+
String query = dbsqlObject.getSql();
99+
final String name = dbsqlObject.getName();
100+
final String schema = dbsqlObject.getSchema();
101+
final String nameEscaped = adapter.escapeNameIfNeeded(name);
102+
final String schemaEscaped = adapter.escapeNameIfNeeded(schema);
103+
104+
if (! name.equalsIgnoreCase(nameEscaped)) {
105+
query = query.replace(
106+
"CREATE DOMAIN " + schema + "." + name,
107+
"CREATE DOMAIN " + schemaEscaped + "." + nameEscaped
108+
);
109+
}
110+
if (! query.endsWith(";")) query = query + ";\n";
111+
query = query + "\n";
112+
return query;
113+
}
114+
115+
private String getChangeOwnerDdl(DBSQLObject dbsqlObject, String owner) {
116+
return MessageFormat.format("ALTER TYPE {0}.{1} OWNER TO {2}\n"
117+
, adapter.escapeNameIfNeeded(dbsqlObject.getSchema())
118+
, adapter.escapeNameIfNeeded(dbsqlObject.getName())
119+
, owner
120+
);
16121
}
17122
}

0 commit comments

Comments
 (0)