mirror of
https://github.com/levinsv/pgadmin3.git
synced 2026-05-15 06:05:49 -06:00
647 lines
18 KiB
C++
647 lines
18 KiB
C++
//////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// pgAdmin III - PostgreSQL Tools
|
|
//
|
|
// Copyright (C) 2002 - 2016, The pgAdmin Development Team
|
|
// This software is released under the PostgreSQL Licence
|
|
//
|
|
// dbgTargetInfo.cpp - debugger
|
|
//
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "pgAdmin3.h"
|
|
#include "utils/pgDefs.h"
|
|
|
|
// wxWindows headers
|
|
#include <wx/wx.h>
|
|
|
|
// App headers
|
|
#include "debugger/dbgTargetInfo.h"
|
|
#include "debugger/dbgConst.h"
|
|
#include "utils/misc.h"
|
|
#include "utils/pgfeatures.h"
|
|
|
|
#include <stdexcept>
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// dbgTargetInfo constructor
|
|
//
|
|
// This class implements a container that holds information necessary to invoke
|
|
// a debugger target (a function or procedure).
|
|
//
|
|
// When the constructor is called, it sends a query to the server to retreive:
|
|
// the OID of the target,
|
|
// the name of the target,
|
|
// the name of the schema in which the target is defined
|
|
// the name of the language in which the target is defined
|
|
// the number of arguments expected by the target
|
|
// the argument names
|
|
// the argument types
|
|
// the argument modes (IN, OUT, or INOUT)
|
|
// the target type (function or procedure)
|
|
//
|
|
// This class offers a number of (inline) member functions that you can call
|
|
// to extract the above information after it's been queried from the server.
|
|
|
|
dbgTargetInfo::dbgTargetInfo(Oid _target, pgConn *_conn)
|
|
: m_args(NULL), m_inputParamCnt(0), m_hasVariadic(false)
|
|
{
|
|
wxMBConv *conv = _conn->GetConv();
|
|
wxString targetQuery =
|
|
wxT("SELECT\n")
|
|
wxT(" p.proname AS name, l.lanname, p.proretset, p.prorettype, y.typname AS rettype,\n")
|
|
wxT(" CASE WHEN proallargtypes IS NOT NULL THEN\n")
|
|
wxT(" pg_catalog.array_to_string(ARRAY(\n")
|
|
wxT(" SELECT\n")
|
|
wxT(" pg_catalog.format_type(p.proallargtypes[s.i], NULL)\n")
|
|
wxT(" FROM\n")
|
|
wxT(" pg_catalog.generate_series(0, pg_catalog.array_upper(\n")
|
|
wxT(" p.proallargtypes, 1)) AS s(i)), ',')\n")
|
|
wxT(" ELSE\n")
|
|
wxT(" pg_catalog.array_to_string(ARRAY(\n")
|
|
wxT(" SELECT\n")
|
|
wxT(" pg_catalog.format_type(p.proargtypes[s.i], NULL)\n")
|
|
wxT(" FROM\n")
|
|
wxT(" pg_catalog.generate_series(0, pg_catalog.array_upper(\n")
|
|
wxT(" p.proargtypes, 1)) AS s(i)), ',')\n")
|
|
wxT(" END AS proargtypenames,\n")
|
|
wxT(" CASE WHEN proallargtypes IS NOT NULL THEN\n")
|
|
wxT(" pg_catalog.array_to_string(ARRAY(\n")
|
|
wxT(" SELECT proallargtypes[s.i] FROM\n")
|
|
wxT(" pg_catalog.generate_series(0, pg_catalog.array_upper(proallargtypes, 1)) s(i)), ',')\n")
|
|
wxT(" ELSE\n")
|
|
wxT(" pg_catalog.array_to_string(ARRAY(\n")
|
|
wxT(" SELECT proargtypes[s.i] FROM\n")
|
|
wxT(" pg_catalog.generate_series(0, pg_catalog.array_upper(proargtypes, 1)) s(i)), ',')\n")
|
|
wxT(" END AS proargtypes,\n")
|
|
wxT(" pg_catalog.array_to_string(p.proargnames, ',') AS proargnames,\n")
|
|
wxT(" pg_catalog.array_to_string(proargmodes, ',') AS proargmodes,\n");
|
|
|
|
if (_conn->GetIsEdb())
|
|
{
|
|
targetQuery +=
|
|
wxT(" CASE WHEN n.nspparent <> 0 THEN n.oid ELSE 0 END AS pkg,\n")
|
|
wxT(" CASE WHEN n.nspparent <> 0 THEN n.nspname ELSE '' END AS pkgname,\n")
|
|
wxT(" CASE WHEN n.nspparent <> 0 THEN (SELECT oid FROM pg_proc WHERE pronamespace=n.oid AND proname='cons') ELSE 0 END AS pkgconsoid,\n")
|
|
wxT(" CASE WHEN n.nspparent <> 0 THEN g.oid ELSE n.oid END AS schema,\n")
|
|
wxT(" CASE WHEN n.nspparent <> 0 THEN g.nspname ELSE n.nspname END AS schemaname,\n")
|
|
wxT(" NOT (l.lanname = 'edbspl' AND protype = '1') AS isfunc,\n");
|
|
}
|
|
else
|
|
{
|
|
targetQuery +=
|
|
wxT(" 0 AS pkg,\n")
|
|
wxT(" '' AS pkgname,\n")
|
|
wxT(" 0 AS pkgconsoid,\n")
|
|
wxT(" n.oid AS schema,\n")
|
|
wxT(" n.nspname AS schemaname,\n")
|
|
wxT(" true AS isfunc,\n");
|
|
}
|
|
if (_conn->BackendMinimumVersion(8, 4))
|
|
{
|
|
targetQuery += wxT(" pg_catalog.pg_get_function_identity_arguments(p.oid) AS signature,");
|
|
}
|
|
else if (_conn->BackendMinimumVersion(8, 1))
|
|
{
|
|
targetQuery +=
|
|
wxT(" CASE\n")
|
|
wxT(" WHEN proallargtypes IS NOT NULL THEN pg_catalog.array_to_string(ARRAY(\n")
|
|
wxT(" SELECT\n")
|
|
wxT(" CASE\n")
|
|
wxT(" WHEN p.proargmodes[s.i] = 'i' THEN ''\n")
|
|
wxT(" WHEN p.proargmodes[s.i] = 'o' THEN 'OUT '\n")
|
|
wxT(" WHEN p.proargmodes[s.i] = 'b' THEN 'INOUT '\n")
|
|
wxT(" WHEN p.proargmodes[s.i] = 'v' THEN 'VARIADIC '\n")
|
|
wxT(" END ||\n")
|
|
wxT(" CASE WHEN COALESCE(p.proargnames[s.i], '') = '' THEN ''\n")
|
|
wxT(" ELSE p.proargnames[s.i] || ' '\n")
|
|
wxT(" END ||\n")
|
|
wxT(" pg_catalog.format_type(p.proallargtypes[s.i], NULL)\n")
|
|
wxT(" FROM\n")
|
|
wxT(" pg_catalog.generate_series(1, pg_catalog.array_upper(p.proallargtypes, 1)) AS s(i)\n")
|
|
wxT(" WHERE p.proargmodes[s.i] != 't'\n")
|
|
wxT(" ), ', ')\n")
|
|
wxT(" ELSE\n")
|
|
wxT(" pg_catalog.array_to_string(ARRAY(\n")
|
|
wxT(" SELECT\n")
|
|
wxT(" CASE\n")
|
|
wxT(" WHEN COALESCE(p.proargnames[s.i+1], '') = '' THEN ''\n")
|
|
wxT(" ELSE p.proargnames[s.i+1] || ' '\n")
|
|
wxT(" END ||\n")
|
|
wxT(" pg_catalog.format_type(p.proargtypes[s.i], NULL)\n")
|
|
wxT(" FROM\n")
|
|
wxT(" pg_catalog.generate_series(1, pg_catalog.array_upper(p.proargtypes, 1)) AS s(i)\n")
|
|
wxT(" ), ', ')\n")
|
|
wxT(" END AS signature,\n");
|
|
}
|
|
else
|
|
{
|
|
targetQuery += wxT(" '' AS signature,");
|
|
}
|
|
|
|
if (_conn->HasFeature(FEATURE_FUNCTION_DEFAULTS))
|
|
{
|
|
// EnterpriseDB 8.3R2
|
|
if(!_conn->BackendMinimumVersion(8, 4))
|
|
{
|
|
targetQuery +=
|
|
wxT(" pg_catalog.array_to_string(ARRAY(\n")
|
|
wxT(" SELECT\n")
|
|
wxT(" CASE WHEN p.proargdefvals[x.j] != '-' THEN\n")
|
|
wxT(" pg_catalog.pg_get_expr(p.proargdefvals[x.j], 'pg_catalog.pg_class'::regclass, true)\n")
|
|
wxT(" ELSE '-' END\n")
|
|
wxT(" FROM\n")
|
|
wxT(" pg_catalog.generate_series(1, pg_catalog.array_upper(p.proargdefvals, 1)) AS x(j)\n")
|
|
wxT(" ), ',') AS proargdefaults,\n")
|
|
wxT(" CASE WHEN p.proargdefvals IS NULL THEN '0'\n")
|
|
wxT(" ELSE pg_catalog.array_upper(p.proargdefvals, 1)::text END AS pronargdefaults\n");
|
|
}
|
|
else
|
|
{
|
|
targetQuery +=
|
|
wxT(" pg_catalog.pg_get_expr(p.proargdefaults, 'pg_catalog.pg_class'::regclass, false) AS proargdefaults,\n")
|
|
wxT(" p.pronargdefaults\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
targetQuery +=
|
|
wxT(" '' AS proargdefaults, 0 AS pronargdefaults\n");
|
|
}
|
|
targetQuery +=
|
|
wxT("FROM\n")
|
|
wxT(" pg_catalog.pg_proc p\n")
|
|
wxT(" LEFT JOIN pg_catalog.pg_namespace n ON p.pronamespace = n.oid\n")
|
|
wxT(" LEFT JOIN pg_catalog.pg_language l ON p.prolang = l.oid\n")
|
|
wxT(" LEFT JOIN pg_catalog.pg_type y ON p.prorettype = y.oid\n");
|
|
if(_conn->GetIsEdb())
|
|
{
|
|
targetQuery +=
|
|
wxT(" LEFT JOIN pg_catalog.pg_namespace g ON n.nspparent = g.oid\n");
|
|
}
|
|
targetQuery +=
|
|
wxString::Format(wxT("WHERE p.oid = %ld"), (long)_target);
|
|
|
|
pgSet *set = _conn->ExecuteSet(targetQuery);
|
|
|
|
if (conv == NULL)
|
|
{
|
|
conv = &wxConvLibc;
|
|
}
|
|
|
|
if (!set || _conn->GetLastResultStatus() != PGRES_TUPLES_OK)
|
|
{
|
|
if (set)
|
|
delete set;
|
|
wxLogError(_("Could not fetch information about the debugger target.\n") +
|
|
_conn->GetLastError());
|
|
|
|
throw (std::runtime_error(
|
|
(const char *)(_conn->GetLastError().c_str())));
|
|
}
|
|
|
|
if (set->NumRows() == 0)
|
|
{
|
|
delete set;
|
|
|
|
wxLogError(_("Can't find the debugging target"));
|
|
throw (std::runtime_error("Can't find target!"));
|
|
}
|
|
|
|
m_oid = _target;
|
|
m_name = set->GetVal(wxT("name"));
|
|
m_schema = set->GetVal(wxT("schemaname"));
|
|
m_package = set->GetVal(wxT("pkgname"));
|
|
m_language = set->GetVal(wxT("lanname"));
|
|
m_returnType = set->GetVal(wxT("rettype"));
|
|
m_funcSignature = set->GetVal(wxT("signature"));
|
|
m_isFunction = set->GetBool(wxT("isfunc"));
|
|
m_returnsSet = set->GetBool(wxT("proretset"));
|
|
m_pkgOid = set->GetOid(wxT("pkg"));
|
|
m_pkgInitOid = set->GetOid(wxT("pkgconsoid"));
|
|
m_schemaOid = set->GetOid(wxT("schema"));
|
|
m_fqName = qtIdent(m_schema) + wxT(".") +
|
|
(m_pkgOid == 0 ? wxT("") : (qtIdent(m_package) + wxT("."))) + qtIdent(m_name);
|
|
|
|
wxArrayString argModes, argNames, argTypes, argTypeOids, argDefVals,
|
|
argBaseTypes;
|
|
|
|
// Fetch Argument Modes (if available)
|
|
if (!set->IsNull(set->ColNumber(wxT("proargmodes"))))
|
|
{
|
|
wxString tmp;
|
|
tmp = set->GetVal(wxT("proargmodes"));
|
|
|
|
if (!tmp.IsEmpty())
|
|
getArrayFromCommaSeparatedList(tmp, argModes);
|
|
}
|
|
// Fetch Argument Names (if available)
|
|
if (!set->IsNull(set->ColNumber(wxT("proargnames"))))
|
|
{
|
|
wxString tmp;
|
|
tmp = set->GetVal(wxT("proargnames"));
|
|
|
|
if (!tmp.IsEmpty())
|
|
getArrayFromCommaSeparatedList(tmp, argNames);
|
|
}
|
|
// Fetch Argument Type-Names (if available)
|
|
if (!set->IsNull(set->ColNumber(wxT("proargtypenames"))))
|
|
{
|
|
wxString tmp;
|
|
tmp = set->GetVal(wxT("proargtypenames"));
|
|
|
|
if (!tmp.IsEmpty())
|
|
getArrayFromCommaSeparatedList(tmp, argTypes);
|
|
}
|
|
// Fetch Argument Type-Names (if available)
|
|
if (!set->IsNull(set->ColNumber(wxT("proargtypes"))))
|
|
{
|
|
wxString tmp;
|
|
tmp = set->GetVal(wxT("proargtypes"));
|
|
if (!tmp.IsEmpty())
|
|
getArrayFromCommaSeparatedList(tmp, argTypeOids);
|
|
}
|
|
|
|
size_t nArgDefs = (size_t)set->GetLong(wxT("pronargdefaults"));
|
|
// Fetch Argument Default Values (if available)
|
|
if (!set->IsNull(set->ColNumber(wxT("proargdefaults"))) && nArgDefs != 0)
|
|
{
|
|
wxString tmp;
|
|
tmp = set->GetVal(wxT("proargdefaults"));
|
|
|
|
if (!tmp.IsEmpty())
|
|
getArrayFromCommaSeparatedList(tmp, argDefVals);
|
|
}
|
|
|
|
wxString argName, argDefVal;
|
|
short argMode;
|
|
Oid argTypeOid;
|
|
size_t argCnt = argTypes.Count();
|
|
|
|
// This function/procedure does not take any arguments
|
|
if (argCnt == 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
size_t idx = 0;
|
|
m_args = new pgDbgArgs();
|
|
|
|
for (; idx < argCnt; idx++)
|
|
{
|
|
argTypeOid = (Oid)strtoul(argTypeOids[idx].mb_str(wxConvUTF8), 0, 10);
|
|
argDefVal = wxEmptyString;
|
|
|
|
argName = wxEmptyString;
|
|
if (idx < argNames.Count())
|
|
argName = argNames[idx];
|
|
|
|
if (argName.IsEmpty())
|
|
argName.Printf( wxT( "dbgParam%d" ), (idx + 1));
|
|
|
|
if (idx < argModes.Count())
|
|
{
|
|
wxString tmp = argModes[idx];
|
|
switch ((char)(tmp.c_str())[0])
|
|
{
|
|
case 'i':
|
|
argMode = pgParam::PG_PARAM_IN;
|
|
m_inputParamCnt++;
|
|
break;
|
|
case 'b':
|
|
m_inputParamCnt++;
|
|
argMode = pgParam::PG_PARAM_INOUT;
|
|
break;
|
|
case 'o':
|
|
argMode = pgParam::PG_PARAM_OUT;
|
|
break;
|
|
case 'v':
|
|
m_inputParamCnt++;
|
|
argMode = pgParam::PG_PARAM_VARIADIC;
|
|
m_hasVariadic = true;
|
|
break;
|
|
case 't':
|
|
continue;
|
|
default:
|
|
m_inputParamCnt++;
|
|
argMode = pgParam::PG_PARAM_IN;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_inputParamCnt++;
|
|
argMode = pgParam::PG_PARAM_IN;
|
|
}
|
|
|
|
// 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 (argName == wxT("_retval_") && _conn->EdbMinimumVersion(9, 0))
|
|
{
|
|
// this will be the return type for this object
|
|
m_returnType = argTypes[idx];
|
|
|
|
continue;
|
|
}
|
|
|
|
m_args->Add(new dbgArgInfo(argName, argTypes[idx], argTypeOid, argMode));
|
|
}
|
|
|
|
if (m_args->GetCount() == 0)
|
|
{
|
|
delete m_args;
|
|
m_args = NULL;
|
|
|
|
return;
|
|
}
|
|
|
|
if (nArgDefs != 0)
|
|
{
|
|
argCnt = m_args->GetCount();
|
|
|
|
// Set the default as the value for the argument
|
|
for (idx = argCnt - 1;; idx--)
|
|
{
|
|
dbgArgInfo *arg = (dbgArgInfo *)((*m_args)[idx]);
|
|
|
|
if (arg->GetMode() == pgParam::PG_PARAM_INOUT ||
|
|
arg->GetMode() == pgParam::PG_PARAM_IN)
|
|
{
|
|
nArgDefs--;
|
|
|
|
if (argDefVals[nArgDefs] != wxT("-"))
|
|
{
|
|
arg->SetDefault(argDefVals[nArgDefs]);
|
|
}
|
|
|
|
if (nArgDefs == 0)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if (idx == 0)
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// operator[]
|
|
//
|
|
// This operator function makes it easy to index into the m_args array
|
|
// using concise syntax.
|
|
dbgArgInfo *dbgTargetInfo::operator[](int index)
|
|
{
|
|
if (m_args == NULL)
|
|
return (dbgArgInfo *)NULL;
|
|
|
|
if (index < 0 || index >= (int)m_args->GetCount())
|
|
return (dbgArgInfo *)NULL;
|
|
|
|
return (dbgArgInfo *)((*m_args)[index]);
|
|
}
|
|
|
|
dbgArgInfo::dbgArgInfo(const wxString &_name, const wxString &_type, Oid _typeOid,
|
|
short _mode)
|
|
: m_name(_name), m_type(_type), m_typeOid(_typeOid), m_mode(_mode),
|
|
m_hasDefault(false), m_useDefault(false), m_null(false)
|
|
{
|
|
if (!_type.EndsWith(wxT("[]"), &m_baseType))
|
|
{
|
|
m_baseType = wxEmptyString;
|
|
}
|
|
}
|
|
|
|
|
|
pgParam *dbgArgInfo::GetParam(wxMBConv *_conv)
|
|
{
|
|
return new pgParam(m_typeOid,
|
|
(m_null ? (wxString *)NULL : &m_val),
|
|
_conv, m_mode);
|
|
}
|
|
|
|
bool dbgTargetInfo::AddForExecution(pgQueryThread *_thread)
|
|
{
|
|
wxASSERT(_thread != NULL);
|
|
|
|
if (_thread == NULL)
|
|
return false;
|
|
|
|
pgConn *conn = _thread->GetConn();
|
|
|
|
pgParamsArray *params = NULL;
|
|
wxString strQuery;
|
|
bool useCallable = false;
|
|
|
|
// Basically - we can call the function/target three ways:
|
|
// 1. If it is a edbspl procedure, we can use callable statement
|
|
// 2. If the database server is of type EnterpriseDB, and
|
|
// function/procedure is type 'edbspl', we should use the anonymous
|
|
// function block for:
|
|
// a. Version < 9.0
|
|
// b. Package function/procedure
|
|
// 3. Otherwise, we should use the simple function call (except using EXEC
|
|
// for the procedure in 'edbspl' instead of using SELECT)
|
|
if (_thread->SupportCallableStatement() &&
|
|
m_language == wxT("edbspl") &&
|
|
!m_isFunction)
|
|
{
|
|
useCallable = true;
|
|
strQuery = wxT("CALL ") + m_fqName + wxT("(");
|
|
|
|
if (m_args)
|
|
{
|
|
params = new pgParamsArray();
|
|
wxMBConv *conv = conn->GetConv();
|
|
|
|
for(int idx = 0; idx < (int)m_args->GetCount(); idx++)
|
|
{
|
|
params->Add(((*m_args)[idx])->GetParam(conv));
|
|
|
|
if (idx != 0)
|
|
strQuery += wxT(", ");
|
|
strQuery += wxString::Format(wxT("$%d::"), idx + 1) +
|
|
((*m_args)[idx])->GetTypeName();
|
|
}
|
|
}
|
|
strQuery += wxT(")");
|
|
}
|
|
else if (conn->GetIsEdb() && !conn->BackendMinimumVersion(9, 3))
|
|
{
|
|
wxString strDeclare, strStatement, strResult;
|
|
bool useAnonymousBlock = false;
|
|
|
|
if (m_language == wxT("edbspl"))
|
|
{
|
|
useAnonymousBlock = true;
|
|
if (!m_isFunction)
|
|
{
|
|
strStatement = wxT("\tEXEC ") + m_fqName;
|
|
}
|
|
else if (m_returnType == wxT("void") || m_returnsSet ||
|
|
!conn->BackendMinimumVersion(8, 4))
|
|
{
|
|
strStatement = wxT("\tPERFORM ") + m_fqName;
|
|
}
|
|
else
|
|
{
|
|
wxString resultVar = wxT("v_retVal");
|
|
strStatement = wxT("\t") + resultVar + wxT(" := ") + m_fqName;
|
|
strDeclare.Append(wxT("\t"))
|
|
.Append(resultVar)
|
|
.Append(wxT(" "))
|
|
.Append(m_returnType)
|
|
.Append(wxT(";\n"));
|
|
strResult = wxT("\tDBMS_OUTPUT.PUT_LINE(E'\\n\\nResult:\\n--------\\n' || ") +
|
|
resultVar +
|
|
wxT("::text || E'\\n\\nNOTE: This is the result generated during the function execution by the debugger.\\n');\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_returnType == wxT("record"))
|
|
{
|
|
strStatement = wxT("\tSELECT ") + m_fqName;
|
|
}
|
|
else
|
|
{
|
|
strStatement = wxT("\tSELECT * FROM ") + m_fqName;
|
|
}
|
|
}
|
|
|
|
if (m_args && m_args->GetCount() > 0)
|
|
{
|
|
strStatement.Append(wxT("("));
|
|
|
|
for(int idx = 0, firstProcessed = false; idx < (int)m_args->GetCount(); idx++)
|
|
{
|
|
dbgArgInfo *arg = (*m_args)[idx];
|
|
|
|
if (!conn->EdbMinimumVersion(8, 4) &&
|
|
arg->GetMode() == pgParam::PG_PARAM_OUT &&
|
|
(!m_isFunction || m_language == wxT("edbspl")))
|
|
{
|
|
if (firstProcessed)
|
|
strStatement.Append(wxT(", "));
|
|
firstProcessed = true;
|
|
|
|
strStatement.Append(wxT("NULL::")).Append(arg->GetTypeName());
|
|
}
|
|
else if (conn->EdbMinimumVersion(8, 4) && useAnonymousBlock &&
|
|
(arg->GetMode() == pgParam::PG_PARAM_OUT ||
|
|
arg->GetMode() == pgParam::PG_PARAM_INOUT))
|
|
{
|
|
wxString strParam = wxString::Format(wxT("p_param%d"), idx);
|
|
|
|
strDeclare.Append(wxT("\t"))
|
|
.Append(strParam)
|
|
.Append(wxT(" "))
|
|
.Append(arg->GetTypeName());
|
|
|
|
if (arg->GetMode() == pgParam::PG_PARAM_INOUT)
|
|
{
|
|
strDeclare.Append(wxT(" := "))
|
|
.Append(arg->Null() ? wxT("NULL") : conn->qtDbString(arg->Value()))
|
|
.Append(wxT("::"))
|
|
.Append(arg->GetTypeName());
|
|
}
|
|
strDeclare.Append(wxT(";\n"));
|
|
|
|
if (firstProcessed)
|
|
strStatement.Append(wxT(", "));
|
|
firstProcessed = true;
|
|
|
|
strStatement.Append(strParam);
|
|
}
|
|
else if (arg->GetMode() != pgParam::PG_PARAM_OUT)
|
|
{
|
|
if (firstProcessed)
|
|
strStatement.Append(wxT(", "));
|
|
firstProcessed = true;
|
|
|
|
if (arg->GetMode() == pgParam::PG_PARAM_VARIADIC)
|
|
strStatement += wxT("VARIADIC ");
|
|
|
|
strStatement
|
|
.Append(arg->Null() ? wxT("NULL") : conn->qtDbString(arg->Value()))
|
|
.Append(wxT("::"))
|
|
.Append(arg->GetTypeName());
|
|
}
|
|
}
|
|
strStatement.Append(wxT(")"));
|
|
strQuery = strStatement;
|
|
}
|
|
else if (!m_isFunction && m_language == wxT("edbspl"))
|
|
{
|
|
strQuery = strStatement;
|
|
}
|
|
else
|
|
{
|
|
strQuery = strStatement.Append(wxT("()"));
|
|
}
|
|
if (useAnonymousBlock)
|
|
{
|
|
strQuery = wxT("DECLARE\n") +
|
|
strDeclare + wxT("BEGIN\n") + strStatement + wxT(";\n") + strResult + wxT("END;");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!m_isFunction)
|
|
{
|
|
strQuery = wxT("EXEC ") + m_fqName + wxT("(");
|
|
}
|
|
else if (m_returnType == wxT("record"))
|
|
{
|
|
strQuery = wxT("SELECT ") + m_fqName + wxT("(");
|
|
}
|
|
else
|
|
{
|
|
strQuery = wxT("SELECT * FROM ") + m_fqName + wxT("(");
|
|
}
|
|
|
|
if (m_args)
|
|
{
|
|
params = new pgParamsArray();
|
|
wxMBConv *conv = conn->GetConv();
|
|
unsigned int noInParams = 0;
|
|
|
|
for(int idx = 0; idx < (int)m_args->GetCount(); idx++)
|
|
{
|
|
dbgArgInfo *arg = (*m_args)[idx];
|
|
|
|
if (arg->GetMode() != pgParam::PG_PARAM_OUT)
|
|
{
|
|
params->Add(arg->GetParam(conv));
|
|
|
|
if (noInParams != 0)
|
|
strQuery += wxT(", ");
|
|
|
|
if (arg->GetMode() == pgParam::PG_PARAM_VARIADIC)
|
|
strQuery += wxT("VARIADIC ");
|
|
|
|
noInParams++;
|
|
strQuery += wxString::Format(wxT("$%d::"), noInParams) +
|
|
((*m_args)[idx])->GetTypeName();
|
|
}
|
|
}
|
|
|
|
/*
|
|
* The function may not have IN/IN OUT/VARIADIC arguments, but only
|
|
* OUT one(s).
|
|
*/
|
|
if (params->GetCount() == 0)
|
|
{
|
|
delete params;
|
|
params = NULL;
|
|
}
|
|
}
|
|
strQuery += wxT(")");
|
|
}
|
|
|
|
_thread->AddQuery(strQuery, params, RESULT_ID_DIRECT_TARGET_COMPLETE, NULL, useCallable);
|
|
|
|
return true;
|
|
}
|