Thread: Patch to add typmod's functions to a type's creation statement

Patch to add typmod's functions to a type's creation statement

From
Guillaume Lelarge
Date:
Hi all,

Here is a patch to support this new PostgreSQL 8.3 feature : the
possibility to add type modifier input and ouput functions to a newly
created type.

I tried many things but wasn't able to test it. If someone has an
example of a use of this statement, can he send it to me or can he test
my patch ? Thanks.

BTW, I discovered a bug on the dlgType.c file. I commited it. pgAdmin
appended a string to cbOuput three times instead of once for itself and
one for cbReceive and one for cbSend.

Regards.


--
Guillaume.
 http://www.postgresqlfr.org
 http://dalibo.com
Index: pgadmin/include/schema/pgType.h
===================================================================
--- pgadmin/include/schema/pgType.h    (révision 6675)
+++ 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 6675)
+++ pgadmin/schema/pgType.cpp    (copie de travail)
@@ -185,6 +185,11 @@
             properties->AppendItem(_("Receive function"), GetReceiveFunction());
             properties->AppendItem(_("Send function"), GetSendFunction());
             }
+            if (GetConnection()->BackendMinimumVersion(8, 3))
+            {
+            properties->AppendItem(_("Typmod_in function"), GetTypmodinFunction());
+            properties->AppendItem(_("Typmod_out function"), GetTypmodoutFunction());
+            }
             properties->AppendItem(_("Storage"), GetStorage());
         }
         properties->AppendItem(_("System type?"), GetSystemObject());
@@ -262,6 +267,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 6675)
+++ 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")
@@ -150,6 +152,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 +197,7 @@
         cbOwner->Disable();

         bool hasSendRcv = connection->BackendMinimumVersion(7, 4);
+        bool hasTypmod = connection->BackendMinimumVersion(8, 3);

         if (hasSendRcv)
         {
@@ -205,6 +210,17 @@
             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);

@@ -231,6 +247,11 @@
                     cbOutput->Append(pn);
                     cbOutput->Append(pn);
                 }
+                if (hasTypmod)
+                {
+                    cbTypmodin->Append(pn);
+                    cbTypmodout->Append(pn);
+                }
                 set->MoveNext();
             }
             delete set;
@@ -486,6 +507,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 6675)
+++ 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 fctn</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 fctn</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>

Re: Patch to add typmod's functions to a type's creation statement

From
"Dave Page"
Date:
Added to my patch queue.

Thanks, Dave

> ------- Original Message -------
> From: Guillaume Lelarge <guillaume@lelarge.info>
> To: pgadmin-hackers@postgresql.org
> Sent: 26/09/07, 18:15:25
> Subject: Patch to add typmod's functions to a type's creation statement
>
> Hi all,
>
> Here is a patch to support this new PostgreSQL 8.3 feature : the
> possibility to add type modifier input and ouput functions to a newly
> created type.
>
> I tried many things but wasn't able to test it. If someone has an
> example of a use of this statement, can he send it to me or can he test
> my patch ? Thanks.
>
> BTW, I discovered a bug on the dlgType.c file. I commited it. pgAdmin
> appended a string to cbOuput three times instead of once for itself and
> one for cbReceive and one for cbSend.
>
> Regards.
>
>
> --
> Guillaume.
>  http://www.postgresqlfr.org
>  http://dalibo.com
>

Re: Patch to add typmod's functions to a type's creation statement

From
Dave Page
Date:
Guillaume Lelarge wrote:
> Hi all,
>
> Here is a patch to support this new PostgreSQL 8.3 feature : the
> possibility to add type modifier input and ouput functions to a newly
> created type.

Unfortunately this still needs some work. I found the following issues:

- The typemod in/out functions are not included the reverse engineered
SQL displayed on the main window when a type with such functions is
selected (for reference, try pg_catalog.time).

- I'm not so keen on the labelling. I would suggest:

  'Typmod in function'/'Typmod out function' in the properties list.
  'Typmod in func'/'Typmod out func' on dlgType.

- 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.

[as a side note, the code here seems somewhat broken in general wrt the
handling of the whole create function/create type chicken and egg
scenario - I'll make a note to review that]

> I tried many things but wasn't able to test it. If someone has an
> example of a use of this statement, can he send it to me or can he test
> my patch ? Thanks.

Look at the code for the time datatype in pg_catalog. You can create
your own experimental types from it's reverse-engineers SQL (once the
first item above is fixed).

Patch NOT applied.

Regards, Dave.

Re: Patch to add typmod's functions to a type's creation statement

From
Guillaume Lelarge
Date:
Hi,

Dave Page a écrit :
> Guillaume Lelarge wrote:
>> Here is a patch to support this new PostgreSQL 8.3 feature : the
>> possibility to add type modifier input and ouput functions to a newly
>> created type.
>
> Unfortunately this still needs some work. I found the following issues:
>
> - The typemod in/out functions are not included the reverse engineered
> SQL displayed on the main window when a type with such functions is
> selected (for reference, try pg_catalog.time).
>

Fixed.

> - I'm not so keen on the labelling. I would suggest:
>
>   'Typmod in function'/'Typmod out function' in the properties list.
>   'Typmod in func'/'Typmod out func' on dlgType.
>

Fixed too.

> - 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, all the code that get input, ouput, send and receive
functions is broken. Right ?

> [as a side note, the code here seems somewhat broken in general wrt the
> handling of the whole create function/create type chicken and egg
> scenario - I'll make a note to review that]
>

+1

Thanks.


--
Guillaume.
 http://www.postgresqlfr.org
 http://dalibo.com

Re: Patch to add typmod's functions to a type's creation statement

From
Guillaume Lelarge
Date:
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>

Re: Patch to add typmod's functions to a type's creation statement

From
Dave Page
Date:
Guillaume Lelarge wrote:
> Guillaume Lelarge a écrit :
>> 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).

Thanks, patch applied.

Regards, Dave.