Guillaume Lelarge a écrit :
>> - The code that loads the combo boxes in dlgType is broken. It's
>> currently in loop designed to load the I/O and Send/Receive functions
>> (which is somewhat broken in itself). The doc at
>> http://www.postgresql.org/docs/8.3/static/sql-createtype.html describes
>> the general signature of functions that are appropriate.
>>
>
> If I correctly understand what the code is doing, it selects all
> functions that has a first argument but no second one, is this right ?
> it does not check arguments' types.
>
> In this case, I think we should change this SQL query
>
> SELECT proname, nspname
> FROM (
> SELECT proname, nspname, max(proargtypes[0]) AS arg0,
> max(proargtypes[1]) AS arg1
> FROM pg_proc p
> JOIN pg_namespace n ON n.oid=pronamespace
> GROUP BY proname, nspname
> HAVING count(proname) = 1 ) AS uniquefunc
> WHERE arg0 <> 0 AND arg1 = 0
>
> with this one
>
> SELECT proname, nspname
> FROM (
> SELECT proname, nspname, max(proargtypes[0]) AS arg0,
> max(proargtypes[1]) AS arg1
> FROM pg_proc p
> JOIN pg_namespace n ON n.oid=pronamespace
> GROUP BY proname, nspname
> HAVING count(proname) = 1 ) AS uniquefunc
> WHERE arg0 <> 0 AND coalesce(arg1, 0) = 0
>
> If I correctly read the CREATE TYPE manpage, I need to check that the
> type_modifier_input_function function has one argument of type cstring[]
> and returns an integer. And I need to check that the
> type_modifier_output_function function has one integer argument and
> returns a single ctring value. Is this right ?
>
If I'm right, this patch does the job (ie, all previous patch's known
issues fixed).
--
Guillaume.
http://www.postgresqlfr.org
http://dalibo.com
Index: pgadmin/include/schema/pgType.h
===================================================================
--- pgadmin/include/schema/pgType.h (révision 6864)
+++ pgadmin/include/schema/pgType.h (copie de travail)
@@ -50,6 +50,10 @@
void iSetReceiveFunction(const wxString& s) { receiveFunction=s; }
wxString GetSendFunction() const { return sendFunction; }
void iSetSendFunction(const wxString& s) { sendFunction=s; }
+ wxString GetTypmodinFunction() const { return typmodinFunction; }
+ void iSetTypmodinFunction(const wxString& s) { typmodinFunction=s; }
+ wxString GetTypmodoutFunction() const { return typmodoutFunction; }
+ void iSetTypmodoutFunction(const wxString& s) { typmodoutFunction=s; }
wxString GetDefault() const { return defaultVal; }
void iSetDefault(const wxString& s) { defaultVal=s; }
wxString GetElement() { return element; }
@@ -87,7 +91,8 @@
private:
wxString alias, inputFunction, outputFunction, defaultVal, element, delimiter, alignment, storage,
- typesList, quotedTypesList, labelList, quotedLabelList, sendFunction, receiveFunction;
+ typesList, quotedTypesList, labelList, quotedLabelList, sendFunction, receiveFunction,
+ typmodinFunction, typmodoutFunction;
wxArrayString typesArray, labelArray;
long internalLength;
int typeClass;
Index: pgadmin/schema/pgType.cpp
===================================================================
--- pgadmin/schema/pgType.cpp (révision 6864)
+++ pgadmin/schema/pgType.cpp (copie de travail)
@@ -66,6 +66,11 @@
sql +=wxT(",\n INTERNALLENGTH=") + NumToStr(GetInternalLength())
+ wxT(", ALIGNMENT=" + GetAlignment()
+ wxT(", STORAGE=") + GetStorage());
+ if (GetConnection()->BackendMinimumVersion(8, 3))
+ {
+ sql +=wxT(",\n TYPMOD_IN=") + GetTypmodinFunction()
+ + wxT(", TYPMOD_OUT=") + GetTypmodoutFunction();
+ }
}
sql += wxT(");\n")
+ GetOwnerSql(8, 0)
@@ -185,6 +190,13 @@
properties->AppendItem(_("Receive function"), GetReceiveFunction());
properties->AppendItem(_("Send function"), GetSendFunction());
}
+ if (GetConnection()->BackendMinimumVersion(8, 3))
+ {
+ if (GetTypmodinFunction().Length() > 0)
+ properties->AppendItem(_("Typmod in function"), GetTypmodinFunction());
+ if (GetTypmodoutFunction().Length() > 0)
+ properties->AppendItem(_("Typmod out function"), GetTypmodoutFunction());
+ }
properties->AppendItem(_("Storage"), GetStorage());
}
properties->AppendItem(_("System type?"), GetSystemObject());
@@ -262,6 +274,11 @@
type->iSetReceiveFunction(types->GetVal(wxT("typreceive")));
type->iSetSendFunction(types->GetVal(wxT("typsend")));
}
+ if (collection->GetConnection()->BackendMinimumVersion(8, 3))
+ {
+ type->iSetTypmodinFunction(types->GetVal(wxT("typmodin")));
+ type->iSetTypmodoutFunction(types->GetVal(wxT("typmodout")));
+ }
wxString align=types->GetVal(wxT("typalign"));
type->iSetAlignment(
align == wxT("c") ? wxT("char") :
Index: pgadmin/dlg/dlgType.cpp
===================================================================
--- pgadmin/dlg/dlgType.cpp (révision 6864)
+++ pgadmin/dlg/dlgType.cpp (copie de travail)
@@ -30,6 +30,8 @@
#define cbOutput CTRL_COMBOBOX("cbOutput")
#define cbReceive CTRL_COMBOBOX("cbReceive")
#define cbSend CTRL_COMBOBOX("cbSend")
+#define cbTypmodin CTRL_COMBOBOX("cbTypmodin")
+#define cbTypmodout CTRL_COMBOBOX("cbTypmodout")
#define chkVariable CTRL_CHECKBOX("chkVariable")
#define txtIntLength CTRL_TEXT("txtIntLength")
#define txtDefault CTRL_TEXT("txtDefault")
@@ -137,6 +139,8 @@
int dlgType::Go(bool modal)
{
+ pgSet *set;
+
if (type)
{
// Edit Mode
@@ -150,6 +154,8 @@
cbOutput->Append(type->GetOutputFunction()); cbOutput->SetSelection(0); cbOutput->Disable();
cbReceive->Append(type->GetReceiveFunction()); cbReceive->SetSelection(0); cbReceive->Disable();
cbSend->Append(type->GetSendFunction()); cbSend->SetSelection(0); cbSend->Disable();
+ cbTypmodin->Append(type->GetTypmodinFunction()); cbTypmodin->SetSelection(0); cbTypmodin->Disable();
+ cbTypmodout->Append(type->GetTypmodoutFunction()); cbTypmodout->SetSelection(0); cbTypmodout->Disable();
chkVariable->SetValue(type->GetInternalLength() < 0); chkVariable->Disable();
if (type->GetInternalLength() > 0)
@@ -193,6 +199,7 @@
cbOwner->Disable();
bool hasSendRcv = connection->BackendMinimumVersion(7, 4);
+ bool hasTypmod = connection->BackendMinimumVersion(8, 3);
if (hasSendRcv)
{
@@ -205,10 +212,21 @@
cbSend->Disable();
}
+ if (hasTypmod)
+ {
+ cbTypmodin->Append(wxEmptyString);
+ cbTypmodout->Append(wxEmptyString);
+ }
+ else
+ {
+ cbTypmodin->Disable();
+ cbTypmodout->Disable();
+ }
+
if (!connection->BackendMinimumVersion(8, 3))
rdbType->Enable(TYPE_ENUM, false);
- pgSet *set=connection->ExecuteSet(
+ set = connection->ExecuteSet(
wxT("SELECT proname, nspname\n")
wxT(" FROM (\n")
wxT(" SELECT proname, nspname, max(proargtypes[0]) AS arg0, max(proargtypes[1]) AS arg1\n")
@@ -231,10 +249,61 @@
cbReceive->Append(pn);
cbSend->Append(pn);
}
+ if (hasTypmod)
+ {
+ cbTypmodin->Append(pn);
+ cbTypmodout->Append(pn);
+ }
set->MoveNext();
}
delete set;
}
+
+ if (hasTypmod)
+ {
+ set = connection->ExecuteSet(
+ wxT("SELECT proname, nspname\n")
+ wxT(" FROM pg_proc p\n")
+ wxT(" JOIN pg_namespace n ON n.oid=pronamespace\n")
+ wxT(" WHERE prorettype=(SELECT oid FROM pg_type WHERE typname='int4')")
+ wxT(" AND proargtypes[0]=(SELECT oid FROM pg_type WHERE typname='_cstring')")
+ wxT(" AND proargtypes[1] IS NULL")
+ wxT(" ORDER BY nspname, proname"));
+
+ if (set)
+ {
+ while (!set->Eof())
+ {
+ wxString pn = database->GetSchemaPrefix(set->GetVal(wxT("nspname"))) + set->GetVal(wxT("proname"));
+
+ cbTypmodin->Append(pn);
+ set->MoveNext();
+ }
+ delete set;
+ }
+
+ set = connection->ExecuteSet(
+ wxT("SELECT proname, nspname\n")
+ wxT(" FROM pg_proc p\n")
+ wxT(" JOIN pg_namespace n ON n.oid=pronamespace\n")
+ wxT(" WHERE prorettype=(SELECT oid FROM pg_type WHERE typname='cstring')")
+ wxT(" AND proargtypes[0]=(SELECT oid FROM pg_type WHERE typname='int4')")
+ wxT(" AND proargtypes[1] IS NULL")
+ wxT(" ORDER BY nspname, proname"));
+
+ if (set)
+ {
+ while (!set->Eof())
+ {
+ wxString pn = database->GetSchemaPrefix(set->GetVal(wxT("nspname"))) + set->GetVal(wxT("proname"));
+
+ cbTypmodout->Append(pn);
+ set->MoveNext();
+ }
+ delete set;
+ }
+ }
+
FillDatatype(cbDatatype, cbElement);
txtLength->SetValidator(numericValidator);
}
@@ -486,6 +555,28 @@
}
}
+ if (connection->BackendMinimumVersion(8, 3))
+ {
+ if (cbTypmodin->GetCurrentSelection() > 0 || cbTypmodout->GetCurrentSelection() > 0)
+ {
+ if (cbTypmodin->GetCurrentSelection() > 0)
+ {
+ sql += wxT(",\n TYPMOD_IN=");
+ AppendQuoted(sql, cbTypmodin->GetValue());
+ if (cbTypmodout->GetCurrentSelection() > 0)
+ {
+ sql += wxT(", TYPMOD_OUT=");
+ AppendQuoted(sql, cbTypmodout->GetValue());
+ }
+ }
+ else
+ {
+ sql += wxT(",\n TYPMOD_OUT=");
+ AppendQuoted(sql, cbTypmodout->GetValue());
+ }
+ }
+
+ }
sql += wxT(",\n INTERNALLENGTH=");
if (chkVariable->GetValue())
sql += wxT("VARIABLE");
Index: pgadmin/ui/dlgType.xrc
===================================================================
--- pgadmin/ui/dlgType.xrc (révision 6864)
+++ pgadmin/ui/dlgType.xrc (copie de travail)
@@ -96,69 +96,89 @@
<size>135,12d</size>
<style>wxCB_READONLY|wxCB_DROPDOWN</style>
</object>
- <object class="wxStaticText" name="stReceive">
- <label>Receive function</label>
- <pos>5,37d</pos>
- </object>
- <object class="wxComboBox" name="cbReceive">
- <content/>
- <pos>70,35d</pos>
- <size>135,12d</size>
- <style>wxCB_READONLY|wxCB_DROPDOWN</style>
- </object>
- <object class="wxStaticText" name="stSend">
- <label>Send Function</label>
- <pos>5,52d</pos>
- </object>
- <object class="wxComboBox" name="cbSend">
- <content/>
- <pos>70,50d</pos>
- <size>135,12d</size>
- <style>wxCB_READONLY|wxCB_DROPDOWN</style>
- </object>
+ <object class="wxStaticText" name="stReceive">
+ <label>Receive function</label>
+ <pos>5,37d</pos>
+ </object>
+ <object class="wxComboBox" name="cbReceive">
+ <content/>
+ <pos>70,35d</pos>
+ <size>135,12d</size>
+ <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+ </object>
+ <object class="wxStaticText" name="stSend">
+ <label>Send function</label>
+ <pos>5,52d</pos>
+ </object>
+ <object class="wxComboBox" name="cbSend">
+ <content/>
+ <pos>70,50d</pos>
+ <size>135,12d</size>
+ <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+ </object>
+ <object class="wxStaticText" name="stTypmodin">
+ <label>Typmod in func</label>
+ <pos>5,67d</pos>
+ </object>
+ <object class="wxComboBox" name="cbTypmodin">
+ <content/>
+ <pos>70,65d</pos>
+ <size>135,12d</size>
+ <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+ </object>
+ <object class="wxStaticText" name="stTypmodout">
+ <label>Typmod out func</label>
+ <pos>5,82d</pos>
+ </object>
+ <object class="wxComboBox" name="cbTypmodout">
+ <content/>
+ <pos>70,80d</pos>
+ <size>135,12d</size>
+ <style>wxCB_READONLY|wxCB_DROPDOWN</style>
+ </object>
<object class="wxStaticText" name="stIntLength">
<label>Internal length</label>
- <pos>5,67d</pos>
+ <pos>5,97d</pos>
</object>
<object class="wxTextCtrl" name="txtIntLength">
- <pos>70,65d</pos>
+ <pos>70,95d</pos>
<size>70,-1d</size>
</object>
<object class="wxCheckBox" name="chkVariable">
<label>Variable</label>
<checked>1</checked>
- <pos>150,65d</pos>
+ <pos>150,95d</pos>
<size>70,12d</size>
</object>
<object class="wxStaticText" name="stDefault">
<label>Default</label>
- <pos>5,82d</pos>
+ <pos>5,112d</pos>
</object>
<object class="wxTextCtrl" name="txtDefault">
- <pos>70,80d</pos>
+ <pos>70,110d</pos>
<size>135,-1d</size>
</object>
<object class="wxStaticText" name="stElement">
<label>Element</label>
- <pos>5,97d</pos>
+ <pos>5,127d</pos>
</object>
<object class="ctlComboBox" name="cbElement">
<content/>
- <pos>70,95d</pos>
+ <pos>70,125d</pos>
<size>135,12d</size>
<style>wxCB_READONLY|wxCB_DROPDOWN</style>
</object>
<object class="wxStaticText" name="stDelimiter">
<label>Delimiter</label>
- <pos>5,112d</pos>
+ <pos>5,142d</pos>
</object>
<object class="wxTextCtrl" name="txtDelimiter">
- <pos>70,110d</pos>
+ <pos>70,140d</pos>
<size>135,-1d</size>
</object>
<object class="wxStaticText" name="stAlignment">
<label>Alignment</label>
- <pos>5,127d</pos>
+ <pos>5,157d</pos>
</object>
<object class="wxComboBox" name="cbAlignment">
<content>
@@ -167,13 +187,13 @@
<item>int2</item>
<item>int4</item>
<item>double</item></content>
- <pos>70,125d</pos>
+ <pos>70,155d</pos>
<size>135,12d</size>
<style>wxCB_READONLY|wxCB_DROPDOWN</style>
</object>
<object class="wxStaticText" name="stStorage">
<label>Storage</label>
- <pos>5,146d</pos>
+ <pos>5,172d</pos>
</object>
<object class="wxComboBox" name="cbStorage">
<content>
@@ -183,17 +203,17 @@
<item>EXTENDED</item>
<item>MAIN</item></content>
<selection>0</selection>
- <pos>70,144d</pos>
+ <pos>70,170d</pos>
<size>135,12d</size>
<style>wxCB_READONLY|wxCB_DROPDOWN</style>
</object>
<object class="wxCheckBox" name="chkByValue">
<label>Passed by value</label>
- <pos>70,160d</pos>
+ <pos>70,185d</pos>
<size>135,12d</size>
</object>
<pos>0,0</pos>
- <size>214,215d</size>
+ <size>214,200d</size>
<style></style>
</object>
<object class="wxPanel" name="pnlDefinitionComposite">
@@ -247,7 +267,7 @@
<size>50,-1d</size>
</object>
<pos>0,0</pos>
- <size>214,215d</size>
+ <size>214,200d</size>
</object>
<object class="wxPanel" name="pnlDefinitionEnum">
<object class="wxListCtrl" name="lstLabels">
@@ -274,7 +294,7 @@
<size>50,-1d</size>
</object>
<pos>0,0</pos>
- <size>214,215d</size>
+ <size>214,200d</size>
</object>
</object>
</object>
@@ -292,7 +312,7 @@
<label>&Cancel</label>
<pos>166,220d</pos>
</object>
- <size>218,238d</size>
+ <size>218,2223d</size>
<style></style>
</object>
</resource>
---------------------------(end of broadcast)---------------------------
TIP 2: Don't 'kill -9' the postmaster