Hi all,
I noticed that if you add, delete, rename or change the type,
collation or precision of a composite type attribute, it deletes all
of them then adds them all back in. Obviously attribute additions,
deletions and modifications may only occur for types under PostgreSQL
9.1, but I thought it a bit extreme to actually drop all types if
you're adding a new one in, or just removing one. Also, if you rename
a type, it drops all attributes again then re-adds them, just to have
an attribute with a different name.
So I've attached a patch which "does the right thing". Take the
example of the following type:
CREATE TYPE bark AS
(one text,
two text,
three text,
four text,
five text);
Say we wanted to remove "two", change the type of three to uuid,
rename four to forty and add an extra text type of six.
Normally we'd just get:
ALTER TYPE bark DROP ATTRIBUTE one;
ALTER TYPE bark DROP ATTRIBUTE two;
ALTER TYPE bark DROP ATTRIBUTE three;
ALTER TYPE bark DROP ATTRIBUTE four;
ALTER TYPE bark DROP ATTRIBUTE five;
ALTER TYPE bark ADD ATTRIBUTE one text;
ALTER TYPE bark ADD ATTRIBUTE three text;
ALTER TYPE bark ADD ATTRIBUTE forty uuid;
ALTER TYPE bark ADD ATTRIBUTE five text;
ALTER TYPE bark ADD ATTRIBUTE six uuid;
With these changes we'd now get:
ALTER TYPE bark DROP ATTRIBUTE two;
ALTER TYPE bark RENAME ATTRIBUTE four TO forty;
ALTER TYPE bark ADD ATTRIBUTE six text;
.. except now those are also nicely indented to be more readable for
types with long schemas/type names.
e.g.
ALTER TYPE long_schema_name.quite_a_long_table_name
ADD ATTRIBUTE "suspiciously long attribute name"?
It also fixes a bug whereby if you have a precision specified, the
word COLLATE mysteriously appears after the type whether or not you
have a collation assigned because the collation condition was based on
the precision being present for some reason. And if you actually
assigned a collation for a valid data type, it wouldn't appear at all,
so that's fixed too.
--
Thom Brown
Twitter: @darkixion
IRC (freenode): dark_ixion
Registered Linux user: #516935
EnterpriseDB UK: http://www.enterprisedb.com
The Enterprise PostgreSQL Company
diff --git a/pgadmin/dlg/dlgType.cpp b/pgadmin/dlg/dlgType.cpp
index 5f3a36c..b951d7b 100644
--- a/pgadmin/dlg/dlgType.cpp
+++ b/pgadmin/dlg/dlgType.cpp
@@ -285,6 +285,7 @@ int dlgType::Go(bool modal)
memberLengths.Add(typeLength);
memberPrecisions.Add(typePrecision);
memberCollations.Add(elements.Item(i + 2));
+ memberOriginalNames.Add(elements.Item(i));
}
cbDatatype->Enable(changeok);
@@ -533,6 +534,7 @@ void dlgType::OnMemberAdd(wxCommandEvent &ev)
memberLengths.Add(length);
memberPrecisions.Add(precision);
memberCollations.Add(collation);
+ memberOriginalNames.Add(wxEmptyString);
}
CheckChange();
@@ -574,10 +576,12 @@ void dlgType::OnMemberChange(wxCommandEvent &ev)
memberLengths.Insert(length, pos);
memberPrecisions.Insert(precision, pos);
memberCollations.Insert(collation, pos);
+// memberOriginalNames.Insert(name, pos);
memberTypes.RemoveAt(pos + 1);
memberLengths.RemoveAt(pos + 1);
memberPrecisions.RemoveAt(pos + 1);
memberCollations.RemoveAt(pos + 1);
+// memberOriginalNames.RemoveAt(pos + 1);
}
}
@@ -596,6 +600,7 @@ void dlgType::OnMemberRemove(wxCommandEvent &ev)
memberLengths.RemoveAt(pos);
memberPrecisions.RemoveAt(pos);
memberCollations.RemoveAt(pos);
+ memberOriginalNames.RemoveAt(pos);
}
CheckChange();
}
@@ -833,7 +838,7 @@ wxString dlgType::GetFullTypeName(int type)
typname += wxT(",") + memberPrecisions.Item(type);
typname += wxT(")");
}
- if (!memberPrecisions.Item(type).IsEmpty() && memberPrecisions.Item(type) != wxT("pg_catalog.\"default\""))
+ if (!memberCollations.Item(type).IsEmpty() && memberCollations.Item(type) != wxT("pg_catalog.\"default\""))
typname += wxT(" COLLATE ") + memberCollations.Item(type);
return typname;
@@ -842,46 +847,78 @@ wxString dlgType::GetFullTypeName(int type)
wxString dlgType::GetSqlForTypes()
{
wxString sql = wxEmptyString;
- wxString old_name, old_type, old_collation, new_name, new_type, new_collation;
+ wxString objname, old_name, old_type, old_collation, new_name, new_type, new_collation, original_name;
wxArrayString elements = type->GetTypesArray();
- bool modified = lstMembers->GetItemCount() * 3 != (int)elements.GetCount();
- size_t i;
+ size_t newindex;
+ size_t oldindex = 0;
+ int hold = 0;
+ objname = schema->GetQuotedPrefix() + qtIdent(GetName());
- // Check if there is a change
- for (int i = 0 ; i < lstMembers->GetItemCount() && !modified; i++)
+ for (newindex = 0 ; newindex < lstMembers->GetItemCount() ; newindex = newindex + 1 - hold)
{
- old_name = elements.Item(i * 3);
- old_type = elements.Item(i * 3 + 1);
- old_collation = elements.Item(i * 3 + 2);
- new_name = lstMembers->GetItemText(i);
- new_type = GetFullTypeName(i);
- new_collation = memberCollations.Item(i);
- modified = modified || old_name != new_name
- || old_type != new_type
- || old_collation != new_collation;
- }
+ // this will decide whether we progress to the next new item,
+ // or whether we need to continue checking the old list first
+ hold = 0;
- if (modified)
- {
- // Drop all old attributes
- for (i = 0 ; i < elements.GetCount() ; i += 3)
+ // these are a copy of the list before any changes
+ if (elements.GetCount() >= (oldindex * 3) + 3)
{
- old_name = elements.Item(i);
- sql += wxT("ALTER TYPE ") + type->GetName() + wxT("\n DROP ATTRIBUTE ") + old_name + wxT(";\n");
+ old_name = elements.Item(oldindex * 3);
+ old_type = elements.Item(oldindex * 3 + 1);
+ old_collation = elements.Item(oldindex * 3 + 2);
}
+ // this is the original name of the type before editing
+ original_name = memberOriginalNames.Item(newindex);
- // Add all new attributes
- for (int i = 0 ; i < lstMembers->GetItemCount() ; i++)
+ new_name = lstMembers->GetItemText(newindex);
+ new_type = GetFullTypeName(newindex);
+ new_collation = memberCollations.Item(newindex);
+
+ if (connection->BackendMinimumVersion(9, 1) && !original_name.IsEmpty()
+ && original_name != new_name && original_name == old_name
+ && old_type == new_type && old_collation == new_collation)
{
- new_name = lstMembers->GetItemText(i);
- new_type = GetFullTypeName(i);
- new_collation = memberCollations.Item(i);
- sql += wxT("ALTER TYPE ") + type->GetName() + wxT("\n ADD ATTRIBUTE ")
- + new_name + wxT(" ") + new_type;
- if (!new_collation.IsEmpty() && new_collation != wxT("pg_catalog.\"default\""))
- sql += wxT(" COLLATE ") + new_collation;
- sql += wxT(";\n");
+ // if this was originally in the list and the name has changed then rename it
+
+ sql += wxT("ALTER TYPE ") + objname + wxT("\n RENAME ATTRIBUTE ")
+ + qtIdent(original_name) + wxT(" TO ") + qtIdent(new_name) + wxT(";\n");
}
+ else if (!original_name.IsEmpty() && original_name != old_name)
+ {
+ // the old attribute isn't in the new list so drop it
+
+ // don't move through new list yet
+ hold = 1;
+
+ sql += wxT("ALTER TYPE ") + objname + wxT("\n DROP ATTRIBUTE ")
+ + qtIdent(old_name) + wxT(";\n");
+ }
+ else if (original_name == new_name)
+ {
+ // drop then add the attribute since more than the name has changed
+ if (new_type != old_type || new_collation != old_collation)
+ {
+ sql += wxT("ALTER TYPE ") + objname + wxT("\n DROP ATTRIBUTE ")
+ + qtIdent(old_name) + wxT(";\n");
+
+ sql += wxT("ALTER TYPE ") + objname + wxT("\n ADD ATTRIBUTE ")
+ + qtIdent(new_name) + wxT(" ") + new_type + wxT(";\n");
+ }
+
+ // but do nothing if nothing has changed
+ }
+ else
+ {
+ // add new attribute as it doesn't have an original name and isn't in the old list
+
+ sql += wxT("ALTER TYPE ") + objname + wxT("\n ADD ATTRIBUTE ")
+ + qtIdent(new_name) + wxT(" ") + new_type + wxT(";\n");
+
+ // we don't need to increment the old list as this is a new item
+ continue;
+ }
+
+ oldindex++;
}
return sql;
diff --git a/pgadmin/include/dlg/dlgType.h b/pgadmin/include/dlg/dlgType.h
index d618221..8a3481b 100644
--- a/pgadmin/include/dlg/dlgType.h
+++ b/pgadmin/include/dlg/dlgType.h
@@ -54,7 +54,7 @@ private:
void showDefinition(int panel);
wxString GetFullTypeName(int type);
- wxArrayString memberTypes, memberLengths, memberPrecisions, memberCollations;
+ wxArrayString memberTypes, memberLengths, memberPrecisions, memberCollations, memberOriginalNames;
bool queriesToBeSplitted;
DECLARE_EVENT_TABLE()
--
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers