Hi,

In EDBAS 9.0, following notable restructuring has been done with respect to
functions and procedures. We need to adopt the same in the pgAdmin code
base. Note that these changes make EDBAS funcs/procs behave more like native
Postgres functions which is a good thing:

* To debug edb-SPL functions/procedures, the debugger was using custom
EDB-protocol extension. With the latest refactorings, the normal code path
which was being employed for plpgsql objects can be used. This patch checks
for the version number at appropriate locations to avoid calling this custom
protocol now. Obviously the current behavior has to be retained for pre 9.0
versions. (changes in debugger files. Had to also make some misc. changes to
handle default parameters appropriately.)

*  Procedures with or without OUT-parameters can now also be called without
the EDB-protocol extension with the EXEC command. For example, if you have a
procedure like "fooproc(a IN integer, b OUT integer)", you can call it with
"exec fooproc(123)". The OUT value is returned as the return value, just as
if it was a function call. Again this behaviour will now be the same as for
normal plpgsql objects.(pgFunction.cpp)

* If an SPL-function has both an OUT-parameter and a return value, the
return value is transformed into an extra OUT-parameter named "_retval_".
This patch adds code to identify such a column and use its type to set the
return type appropriately. (pgFunction.cpp)

Note that the changes are not as intensive as the above may sound. The
protocol extension was only being used by the debugger code paths, so the
changes are localised in that module. The remaining changes are in
pgFunction.cpp file only. I tested the debugger changes against both AS90
and AS84 code bases. For the latter the extended protocol is getting invoked
appropriately. No testing on windows though yet.

Regards,
Nikhils
diff --git a/pgadmin/debugger/dbgPgThread.cpp b/pgadmin/debugger/dbgPgThread.cpp
index e7ffaf3..f01f29c 100644
--- a/pgadmin/debugger/dbgPgThread.cpp
+++ b/pgadmin/debugger/dbgPgThread.cpp
@@ -119,11 +119,16 @@ void *dbgPgThread::Entry( void )
 #if defined (__WXMSW__) || (EDB_LIBPQ)
 		// If we have a set of params, and we have the required functions...
 		dbgPgParams *params = m_currentCommand->getParams();
+		bool		 doit = true;
+
+		// we do not need all of PQi stuff AS90 onwards
+		if (m_owner.EdbMinimumVersion(9, 0))
+			doit = false;
 
 #ifdef EDB_LIBPQ
-		if (params)
+		if (params && doit)
 #else
-		if (PQiGetOutResult && PQiPrepareOut && PQiSendQueryPreparedOut && params)
+		if (PQiGetOutResult && PQiPrepareOut && PQiSendQueryPreparedOut && params && doit)
 #endif
 		{
 			wxLogInfo(wxT("Using an EnterpriseDB callable statement"));
diff --git a/pgadmin/debugger/dbgTargetInfo.cpp b/pgadmin/debugger/dbgTargetInfo.cpp
index 14cb871..8c9b937 100644
--- a/pgadmin/debugger/dbgTargetInfo.cpp
+++ b/pgadmin/debugger/dbgTargetInfo.cpp
@@ -150,7 +150,11 @@ dbgTargetInfo::dbgTargetInfo( const wxString &target,  dbgPgConn *conn, char tar
 		// store the "" only if this is stringlike type and nothing otherwise..
 		defVal = (defvals.GetNextToken()).Strip ( wxString::both );
 		if (argInfo.isValidDefVal(defVal))
+		{
+			// remove starting/trailing quotes
+			defVal.Replace( wxT( "\"" ), wxT( "" ));
 			argInfo.setValue(defVal);
+		}
 
 		m_argInfo.Add( argInfo );
 	}
diff --git a/pgadmin/debugger/debugger.cpp b/pgadmin/debugger/debugger.cpp
index a6b55fb..74c584c 100644
--- a/pgadmin/debugger/debugger.cpp
+++ b/pgadmin/debugger/debugger.cpp
@@ -138,6 +138,7 @@ bool debuggerFactory::CheckEnable(pgObject *obj)
 #ifdef __WXMSW__
 					else if (func->GetLanguage() == wxT("edbspl") &&
 					         obj->GetConnection()->EdbMinimumVersion(8, 4) &&
+					         !obj->GetConnection()->EdbMinimumVersion(9, 0) &&
 					         !(PQiGetOutResult && PQiPrepareOut && PQiSendQueryPreparedOut))
 						return false;
 #else
diff --git a/pgadmin/debugger/dlgDirectDbg.cpp b/pgadmin/debugger/dlgDirectDbg.cpp
index 8310abf..cdbd422 100644
--- a/pgadmin/debugger/dlgDirectDbg.cpp
+++ b/pgadmin/debugger/dlgDirectDbg.cpp
@@ -547,7 +547,8 @@ void dlgDirectDbg::invokeTarget()
 	// us to retrieve the OUT/INOUT parameter results.
 	// Otherwise, just SELECT/EXEC it as per normal.
 #ifdef __WXMSW__
-	if (!m_targetInfo->getIsFunction() &&
+	if (!m_conn->EdbMinimumVersion(9,0) &&
+			!m_targetInfo->getIsFunction() &&
 	        PQiGetOutResult &&
 	        PQiPrepareOut &&
 	        PQiSendQueryPreparedOut)
@@ -555,7 +556,8 @@ void dlgDirectDbg::invokeTarget()
 	else
 #else
 #ifdef EDB_LIBPQ
-	if (!m_targetInfo->getIsFunction())
+	if (!m_conn->EdbMinimumVersion(9,0) &&
+			!m_targetInfo->getIsFunction())
 		invokeTargetCallable();
 	else
 #endif
@@ -690,17 +692,30 @@ void dlgDirectDbg::invokeTargetStatement()
 				wxString strParam = wxString::Format(wxT("param%d"), i);
 				declareStatement +=  strParam + wxT(" ") + arg.getType();
 				if (arg.getMode() == wxT("b"))
-					declareStatement += wxT(" := ") + arg.quoteValue() + wxT("::") + arg.getType();
+				{
+					declareStatement += wxT(" := ") + arg.quoteValue();
+					if (!arg.quoteValue().Contains(wxT("::")))
+						declareStatement += wxT("::") + arg.getType();
+				}
 				declareStatement += wxT(";\n");
 				query.Append(strParam + wxT(", "));
 			}
 			else if (arg.getMode() != wxT("o"))
-				query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
+			{
+				if (!arg.quoteValue().Contains(wxT("::")))
+					query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
+				else
+					query.Append( arg.quoteValue() + wxT(", "));
+			}
 		}
 		else if(arg.getMode() == wxT("v"))
 			query.Append( arg.getValue() + wxT(", "));
-		else
-			query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
+		else {
+			if (!arg.quoteValue().Contains(wxT("::")))
+				query.Append( arg.quoteValue() + wxT("::") + arg.getType() + wxT(", "));
+			else
+				query.Append( arg.quoteValue() + wxT(", "));
+		}
 	}
 
 	if (query.EndsWith(wxT(", ")))
diff --git a/pgadmin/schema/pgFunction.cpp b/pgadmin/schema/pgFunction.cpp
index 5676843..d490023 100644
--- a/pgadmin/schema/pgFunction.cpp
+++ b/pgadmin/schema/pgFunction.cpp
@@ -558,7 +558,8 @@ wxString pgFunction::GetArgSigList(const bool forScript)
 
 	for (unsigned int i = 0; i < argTypesArray.Count(); i++)
 	{
-		// OUT parameters are not considered part of the signature, except for EDB-SPL
+		// OUT parameters are not considered part of the signature, except for EDB-SPL,
+		// although this is not true for EDB AS90 onwards..
 		if (argModesArray.Item(i) != wxT("OUT") && argModesArray.Item(i) != wxT("TABLE"))
 		{
 			if (args.Length() > 0)
@@ -576,7 +577,8 @@ wxString pgFunction::GetArgSigList(const bool forScript)
 		}
 		else
 		{
-			if (GetLanguage() == wxT("edbspl") && argModesArray.Item(i) != wxT("TABLE"))
+			if (GetLanguage() == wxT("edbspl") && argModesArray.Item(i) != wxT("TABLE") &&
+									!this->GetConnection()->EdbMinimumVersion(9, 0))
 			{
 				if (args.Length() > 0)
 				{
@@ -733,10 +735,6 @@ pgFunction *pgFunctionFactory::AppendFunctions(pgObject *obj, pgSchema *schema,
 
 			while (argTypesTkz.HasMoreTokens())
 			{
-				// Add the arg type. This is a type oid, so
-				// look it up in the hashmap
-				type = argTypesTkz.GetNextToken();
-				function->iAddArgType(typeCache[type]);
 
 				// Now add the name, stripping the quotes and \" if
 				// necessary.
@@ -746,11 +744,37 @@ pgFunction *pgFunctionFactory::AppendFunctions(pgObject *obj, pgSchema *schema,
 					if (name[0] == '"')
 						name = name.Mid(1, name.Length() - 2);
 					name.Replace(wxT("\\\""), wxT("\""));
+
+					// In EDBAS 90, if an SPL-function has both an OUT-parameter
+					// and a return value (which is not possible on PostgreSQL otherwise),
+					// the return value is transformed into an extra OUT-parameter
+					// named "_retval_"
+					if (obj->GetConnection()->EdbMinimumVersion(9, 0))
+					{
+						if (name == wxT("_retval_"))
+						{
+							type = argTypesTkz.GetNextToken();
+							// this will be the return type for this object
+							function->iSetReturnType(typeCache[type]);
+
+							// consume uniformly, mode will definitely be "OUT"
+							mode = argModesTkz.GetNextToken();
+							// no defvals..
+							if (!hasDefValSupport)
+								def = argDefsTkz.GetNextToken();
+							continue;
+						}
+					}
 					function->iAddArgName(name);
 				}
 				else
 					function->iAddArgName(wxEmptyString);
 
+				// Add the arg type. This is a type oid, so
+				// look it up in the hashmap
+				type = argTypesTkz.GetNextToken();
+				function->iAddArgType(typeCache[type]);
+
 				// Now the mode
 				mode = argModesTkz.GetNextToken();
 				if (!mode.IsEmpty())
@@ -858,12 +882,17 @@ pgFunction *pgFunctionFactory::AppendFunctions(pgObject *obj, pgSchema *schema,
 
 			function->iSetOwner(functions->GetVal(wxT("funcowner")));
 			function->iSetAcl(functions->GetVal(wxT("proacl")));
-			wxString strType = functions->GetVal(wxT("typname"));
-			if (strType.Lower() == wxT("record") && !strReturnTableArgs.IsEmpty())
+
+			// set the return type only if not already set..
+			if (function->GetReturnType().IsEmpty())
 			{
-				strType = wxT("TABLE(") + strReturnTableArgs + wxT(")");
+				wxString strType = functions->GetVal(wxT("typname"));
+				if (strType.Lower() == wxT("record") && !strReturnTableArgs.IsEmpty())
+				{
+					strType = wxT("TABLE(") + strReturnTableArgs + wxT(")");
+				}
+				function->iSetReturnType(strType);
 			}
-			function->iSetReturnType(strType);
 			function->iSetComment(functions->GetVal(wxT("description")));
 
 			function->iSetLanguage(lanname);
-- 
Sent via pgadmin-hackers mailing list ([email protected])
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgadmin-hackers

Reply via email to