Example #1
0
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;
		}
	}
}
Example #2
0
pgFunction *pgFunctionFactory::AppendFunctions(pgObject *obj, pgSchema *schema, ctlTree *browser, const wxString &restriction)
{
	// Caches
	cacheMap typeCache, exprCache;

	pgFunction *function = 0;
	wxString argNamesCol, argDefsCol, proConfigCol, proType, seclab;
	if (obj->GetConnection()->BackendMinimumVersion(8, 0))
		argNamesCol = wxT("proargnames, ");
	if (obj->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS) && !obj->GetConnection()->BackendMinimumVersion(8, 4))
		argDefsCol = wxT("proargdefvals, COALESCE(substring(array_dims(proargdefvals), E'1:(.*)\\]')::integer, 0) AS pronargdefaults, ");
	if (obj->GetConnection()->BackendMinimumVersion(8, 4))
		argDefsCol = wxT("pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, pronargdefaults, ");
	if (obj->GetConnection()->BackendMinimumVersion(8, 3))
		proConfigCol = wxT("proconfig, ");
	if (obj->GetConnection()->EdbMinimumVersion(8, 1))
		proType = wxT("protype, ");
	if (obj->GetConnection()->BackendMinimumVersion(9, 1))
	{
		seclab = wxT(",\n")
		         wxT("(SELECT array_agg(label) FROM pg_seclabels sl1 WHERE sl1.objoid=pr.oid) AS labels,\n")
		         wxT("(SELECT array_agg(provider) FROM pg_seclabels sl2 WHERE sl2.objoid=pr.oid) AS providers");
	}

	pgSet *functions = obj->GetDatabase()->ExecuteSet(
	                       wxT("SELECT pr.oid, pr.xmin, pr.*, format_type(TYP.oid, NULL) AS typname, typns.nspname AS typnsp, lanname, ") +
	                       argNamesCol  + argDefsCol + proConfigCol + proType +
	                       wxT("       pg_get_userbyid(proowner) as funcowner, description") + seclab + wxT("\n")
	                       wxT("  FROM pg_proc pr\n")
	                       wxT("  JOIN pg_type typ ON typ.oid=prorettype\n")
	                       wxT("  JOIN pg_namespace typns ON typns.oid=typ.typnamespace\n")
	                       wxT("  JOIN pg_language lng ON lng.oid=prolang\n")
	                       wxT("  LEFT OUTER JOIN pg_description des ON des.objoid=pr.oid\n")
	                       + restriction +
	                       wxT(" ORDER BY proname"));

	pgSet *types = obj->GetDatabase()->ExecuteSet(wxT(
	                   "SELECT oid, format_type(oid, NULL) AS typname FROM pg_type"));

	if (types)
	{
		while(!types->Eof())
		{
			typeCache[types->GetVal(wxT("oid"))] = types->GetVal(wxT("typname"));
			types->MoveNext();
		}
	}

	if (functions)
	{
		while (!functions->Eof())
		{
			bool isProcedure = false;
			wxString lanname = functions->GetVal(wxT("lanname"));
			wxString typname = functions->GetVal(wxT("typname"));

			// Is this an EDB Stored Procedure?
			if (obj->GetConnection()->EdbMinimumVersion(8, 1))
			{
				wxString protype = functions->GetVal(wxT("protype"));
				if (protype == wxT("1"))
					isProcedure = true;
			}
			else if (obj->GetConnection()->EdbMinimumVersion(8, 0) &&
			         lanname == wxT("edbspl") && typname == wxT("void"))
				isProcedure = true;

			// Create the new object
			if (isProcedure)
				function = new pgProcedure(schema, functions->GetVal(wxT("proname")));
			else if (typname == wxT("\"trigger\"") || typname == wxT("trigger"))
				function = new pgTriggerFunction(schema, functions->GetVal(wxT("proname")));
			else
				function = new pgFunction(schema, functions->GetVal(wxT("proname")));

			// Tokenize the arguments
			wxStringTokenizer argTypesTkz(wxEmptyString), argModesTkz(wxEmptyString);
			wxString tmp;

			wxArrayString argNamesArray;
			wxArrayString argDefValArray;

			// We always have types
			argTypesTkz.SetString(functions->GetVal(wxT("proargtypes")));

			// We only have names in 8.0+
			if (obj->GetConnection()->BackendMinimumVersion(8, 0))
			{
				tmp = functions->GetVal(wxT("proargnames"));
				if (!tmp.IsEmpty())
					getArrayFromCommaSeparatedList(tmp.Mid(1, tmp.Length() - 2), argNamesArray);
			}

			// EDB 8.0 had modes in pg_proc.proargdirs
			if (!obj->GetConnection()->EdbMinimumVersion(8, 1) && isProcedure)
				argModesTkz.SetString(functions->GetVal(wxT("proargdirs")));

			if (obj->GetConnection()->EdbMinimumVersion(8, 1))
				function->iSetProcType(functions->GetLong(wxT("protype")));

			// EDB 8.1 and PostgreSQL 8.1 have modes in pg_proc.proargmodes
			if (obj->GetConnection()->BackendMinimumVersion(8, 1))
			{
				tmp = functions->GetVal(wxT("proallargtypes"));
				if (!tmp.IsEmpty())
					argTypesTkz.SetString(tmp.Mid(1, tmp.Length() - 2), wxT(","));

				tmp = functions->GetVal(wxT("proargmodes"));
				if (!tmp.IsEmpty())
					argModesTkz.SetString(tmp.Mid(1, tmp.Length() - 2), wxT(","));
			}

			// EDB 8.3: Function defaults
			if (obj->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS) &&
			        !obj->GetConnection()->BackendMinimumVersion(8, 4))
			{
				tmp = functions->GetVal(wxT("proargdefvals"));
				if (!tmp.IsEmpty())
					getArrayFromCommaSeparatedList(tmp.Mid(1, tmp.Length() - 2), argDefValArray);

				function->iSetArgDefValCount(functions->GetLong(wxT("pronargdefaults")));
			}

			if (obj->GetConnection()->BackendMinimumVersion(8, 4))
			{
				tmp = functions->GetVal(wxT("proargdefaultvals"));
				getArrayFromCommaSeparatedList(tmp, argDefValArray);

				function->iSetArgDefValCount(functions->GetLong(wxT("pronargdefaults")));

				// Check if it is a window function
				function->iSetIsWindow(functions->GetBool(wxT("proiswindow")));
			}
			else
				function->iSetIsWindow(false);

			// Now iterate the arguments and build the arrays
			wxString type, name, mode;
			size_t nArgsIN = 0;
			size_t nArgNames = 0;

			while (argTypesTkz.HasMoreTokens())
			{
				if (nArgNames < argNamesArray.GetCount())
				{
					name = argNamesArray[nArgNames++];
				}
				else
					name = wxEmptyString;
				if (!name.IsEmpty())
				{
					// Now add the name, stripping the quotes and \" if
					// necessary.
					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();

							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())
				{
					if (mode == wxT('o') || mode == wxT("2"))
						mode = wxT("OUT");
					else if (mode == wxT("b") || mode == wxT("3"))
					{
						if (isProcedure)
							mode = wxT("IN OUT");
						else
						{
							mode = wxT("INOUT");
							// 'edbspl' does not support default values for the
							// INOUT parameters.
							if (lanname != wxT("edbspl"))
							{
								nArgsIN++;
							}
						}
					}
					else if (mode == wxT("v"))
					{
						mode = wxT("VARIADIC");
						nArgsIN++;
					}
					else if (mode == wxT("t"))
						mode = wxT("TABLE");
					else
					{
						mode = wxT("IN");
						nArgsIN++;
					}

					function->iAddArgMode(mode);
				}
				else
				{
					function->iAddArgMode(wxEmptyString);
					nArgsIN++;
				}
			}

			function->iSetArgCount(functions->GetLong(wxT("pronargs")));

			wxString strReturnTableArgs;
			// Process default values
			size_t currINindex = 0;
			for (size_t index = 0; index < function->GetArgModesArray().Count(); index++)
			{
				wxString def = wxEmptyString;
				if(function->GetArgModesArray()[index].IsEmpty() ||
				        function->GetArgModesArray()[index] == wxT("IN") ||
				        (function->GetArgModesArray()[index] == wxT("INOUT") &&
				         lanname != wxT("edbspl")) ||
				        function->GetArgModesArray()[index] == wxT("VARIADIC"))
				{
					if (!argDefValArray.IsEmpty() && nArgsIN <= argDefValArray.GetCount())
					{
						def = argDefValArray[currINindex++];

						if (!def.IsEmpty() && def != wxT("-"))
						{
							// Only EDB 8.3 does not support get the default value
							// using pg_get_expr directly
							if (function->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS) &&
							        !function->GetConnection()->BackendMinimumVersion(8, 4))
							{
								// Check the cache first - if we don't have a value, get it and cache for next time
								wxString val = exprCache[def];

								if (val == wxEmptyString)
								{
									val = obj->GetDatabase()->ExecuteScalar(
									          wxT("SELECT pg_get_expr('") + def.Mid(1, def.Length() - 2) + wxT("', 'pg_catalog.pg_class'::regclass)"));
									exprCache[def] = val;
								}
								def = val;
							}
						}
						else
						{
							def = wxEmptyString;
						}
					}
					nArgsIN--;
				}
				else if(function->GetConnection()->BackendMinimumVersion(8, 4) &&
				        function->GetArgModesArray()[index] == wxT("TABLE"))
				{
					if (strReturnTableArgs.Length() > 0)
						strReturnTableArgs += wxT(", ");
					wxString strName = function->GetArgNamesArray()[index];
					if (!strName.IsEmpty())
						strReturnTableArgs += qtIdent(strName) + wxT(" ");
					strReturnTableArgs += function->GetArgTypesArray()[index];
				}
				function->iAddArgDef(def);
			}

			function->iSetOid(functions->GetOid(wxT("oid")));
			function->iSetXid(functions->GetOid(wxT("xmin")));

			if (browser)
				function->UpdateSchema(browser, functions->GetOid(wxT("pronamespace")));

			function->iSetOwner(functions->GetVal(wxT("funcowner")));
			function->iSetAcl(functions->GetVal(wxT("proacl")));

			// set the return type only if not already set..
			if (function->GetReturnType().IsEmpty())
			{
				wxString strType = functions->GetVal(wxT("typname"));
				if (strType.Lower() == wxT("record") && !strReturnTableArgs.IsEmpty())
				{
					strType = wxT("TABLE(") + strReturnTableArgs + wxT(")");
				}
				function->iSetReturnType(strType);
			}
			function->iSetComment(functions->GetVal(wxT("description")));

			function->iSetLanguage(lanname);
			function->iSetSecureDefiner(functions->GetBool(wxT("prosecdef")));
			function->iSetReturnAsSet(functions->GetBool(wxT("proretset")));
			function->iSetIsStrict(functions->GetBool(wxT("proisstrict")));
			function->iSetSource(functions->GetVal(wxT("prosrc")));
			function->iSetBin(functions->GetVal(wxT("probin")));

			wxString vol = functions->GetVal(wxT("provolatile"));
			function->iSetVolatility(
			    vol.IsSameAs(wxT("i")) ? wxT("IMMUTABLE") :
			    vol.IsSameAs(wxT("s")) ? wxT("STABLE") :
			    vol.IsSameAs(wxT("v")) ? wxT("VOLATILE") : wxT("unknown"));

			// PostgreSQL 8.3 cost/row estimations
			if (obj->GetConnection()->BackendMinimumVersion(8, 3))
			{
				function->iSetCost(functions->GetLong(wxT("procost")));
				function->iSetRows(functions->GetLong(wxT("prorows")));
				wxString cfg = functions->GetVal(wxT("proconfig"));
				if (!cfg.IsEmpty())
					FillArray(function->GetConfigList(), cfg.Mid(1, cfg.Length() - 2));
			}

			if (obj->GetConnection()->BackendMinimumVersion(9, 1))
			{
				function->iSetProviders(functions->GetVal(wxT("providers")));
				function->iSetLabels(functions->GetVal(wxT("labels")));
			}

			if (obj->GetConnection()->BackendMinimumVersion(9, 2))
			{
				function->iSetIsLeakProof(functions->GetBool(wxT("proleakproof")));
			}

			if (browser)
			{
				browser->AppendObject(obj, function);
				functions->MoveNext();
			}
			else
				break;
		}

		delete functions;
		delete types;
	}
	return function;
}
Example #3
0
edbPackageFunction *edbPackageFunctionFactory::AppendFunctions(pgObject *obj, edbPackage *package, ctlTree *browser, const wxString &restriction)
{
	edbPackageFunction *packageFunction = 0;
	pgSet *packageFunctions;

	// Caches
	cacheMap typeCache, exprCache;
	wxString sql, argDefsCol;

	if (obj->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS))
	{
		if (obj->GetConnection()->EdbMinimumVersion(8, 4))
		{
			argDefsCol = wxT("pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS argdefaults, pronargdefaults, ");
		}
		else
		{
			argDefsCol = wxT("proargdefvals AS argdefaults, COALESCE(substring(array_dims(proargdefvals), E'1:(.*)\\]')::integer, 0) AS pronargdefaults, ");
		}
	}

	if (obj->GetConnection()->EdbMinimumVersion(8, 2))
	{
		sql = wxT("SELECT pg_proc.oid, proname AS eltname, prorettype AS eltdatatype, pronargs AS nargs, proaccess AS visibility,\n")
		      wxT("       proallargtypes AS allargtypes, proargtypes AS argtypes, proargnames AS argnames, proargmodes AS argmodes,") + argDefsCol + wxT("\n")
		      wxT("       CASE WHEN format_type(prorettype, NULL) = 'void' THEN 'P' ELSE 'F' END AS eltclass\n")
		      wxT("  FROM pg_proc, pg_namespace\n")
		      + restriction + wxT("\n")
		      wxT("  AND pg_proc.pronamespace = pg_namespace.oid\n")
		      wxT("  ORDER BY eltname");
	}
	else
	{
		sql = wxT("SELECT oid, eltname, eltdatatype, eltclass, nargs, visibility,\n")
		      wxT("       allargtypes, argtypes, argnames, argmodes\n")
		      wxT("  FROM edb_pkgelements\n")
		      + restriction + wxT("\n")
		      wxT("  ORDER BY eltname");
	}

	packageFunctions = obj->GetDatabase()->ExecuteSet(sql);

	pgSet *types = obj->GetDatabase()->ExecuteSet(wxT(
	                   "SELECT oid, format_type(oid, NULL) AS typname FROM pg_type"));

	while(!types->Eof())
	{
		typeCache[types->GetVal(wxT("oid"))] = types->GetVal(wxT("typname"));
		types->MoveNext();
	}

	if (packageFunctions)
	{
		while (!packageFunctions->Eof())
		{
			size_t inModeCnt = 0;
			size_t defaultArgsCnt = 0;
			if (packageFunctions->GetVal(wxT("eltclass")) == wxT("F"))
				packageFunction = new edbPackageFunction(package, packageFunctions->GetVal(wxT("eltname")));
			else
				packageFunction = new edbPackageProcedure(package, packageFunctions->GetVal(wxT("eltname")));

			// Tokenize the arguments
			wxStringTokenizer argTypesTkz(wxEmptyString), argModesTkz(wxEmptyString);
			queryTokenizer argNamesTkz(wxEmptyString, (wxChar)',');
			wxArrayString argDefValArray;
			wxString tmp;

			// Types
			tmp = packageFunctions->GetVal(wxT("allargtypes"));
			if (!tmp.IsEmpty())
				argTypesTkz.SetString(tmp.Mid(1, tmp.Length() - 2), wxT(","));
			else
			{
				tmp = packageFunctions->GetVal(wxT("argtypes"));
				if (!tmp.IsEmpty())
					argTypesTkz.SetString(tmp);
			}

			// Names
			tmp = packageFunctions->GetVal(wxT("argnames"));
			if (!tmp.IsEmpty())
				argNamesTkz.SetString(tmp.Mid(1, tmp.Length() - 2), wxT(","));

			// Modes
			tmp = packageFunctions->GetVal(wxT("argmodes"));
			if (!tmp.IsEmpty())
				argModesTkz.SetString(tmp.Mid(1, tmp.Length() - 2), wxT(","));

			// Function defaults
			if (obj->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS))
			{
				defaultArgsCnt = packageFunctions->GetLong(wxT("pronargdefaults"));

				if (defaultArgsCnt > 0)
				{
					tmp = packageFunctions->GetVal(wxT("argdefaults"));

					if (!tmp.IsEmpty())
					{
						getArrayFromCommaSeparatedList(tmp.Mid(1, tmp.Length() - 2), argDefValArray);
					}
				}
			}

			// Now iterate the arguments and build the arrays
			wxString type, name, mode;

			while (argTypesTkz.HasMoreTokens())
			{
				// Add the arg type. This is a type oid, so
				// look it up in the hashmap
				type = argTypesTkz.GetNextToken();
				packageFunction->iAddArgType(typeCache[type]);

				// Now add the name, stripping the quotes if
				// necessary.
				name = argNamesTkz.GetNextToken();
				if (!name.IsEmpty())
				{
					if (name[0] == '"')
						name = name.Mid(1, name.Length() - 2);
					packageFunction->iAddArgName(name);
				}
				else
					packageFunction->iAddArgName(wxEmptyString);

				// Now the mode
				mode = argModesTkz.GetNextToken();
				if (!mode.IsEmpty())
				{
					if (mode == wxT('o') || mode == wxT("2"))
						mode = wxT("OUT");
					else if (mode == wxT("b"))
						if (packageFunctions->GetVal(wxT("eltclass")) == wxT("F"))
							mode = wxT("IN OUT");
						else
							mode = wxT("INOUT");
					else if (mode == wxT("3"))
						mode = wxT("IN OUT");
					else if (mode == wxT("v"))
					{
						inModeCnt++;
						mode = wxT("VARIADIC");
					}
					else
					{
						inModeCnt++;
						mode = wxT("IN");
					}

					packageFunction->iAddArgMode(mode);
				}
				else
					packageFunction->iAddArgMode(wxEmptyString);
			}

			// Finally the defaults, as we got them.
			if (packageFunction->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS))
			{
				size_t currINindex = 0;
				while (inModeCnt)
				{
					for (size_t index = 0; index < packageFunction->GetArgTypesArray().Count(); index++)
					{
						wxString def = wxEmptyString;
						if(packageFunction->GetArgModesArray()[index].IsEmpty() ||
						        packageFunction->GetArgModesArray()[index] == wxT("IN") ||
						        packageFunction->GetArgModesArray()[index] == wxT("VARIADIC"))
						{
							if (!argDefValArray.IsEmpty() && inModeCnt <= argDefValArray.GetCount())
							{
								def = argDefValArray[currINindex++];

								if (!def.IsEmpty() && def != wxT("-"))
								{
									// Only EDB 8.3 does not support get the
									// default value using pg_get_expr directly
									if (!packageFunction->GetConnection()->BackendMinimumVersion(8, 4))
									{
										// Check the cache first - if we don't
										// have a value, get it and cache for
										// next time
										wxString val = exprCache[def];

										if (val == wxEmptyString)
										{
											val = obj->GetDatabase()->ExecuteScalar(
											          wxT("SELECT pg_get_expr('") + def.Mid(1, def.Length() - 2) + wxT("', 'pg_catalog.pg_class'::regclass)"));
											exprCache[def] = val;
										}
										def = val;
									}
								}
								else
								{
									def = wxEmptyString;
								}
							}
							inModeCnt--;
						}
						packageFunction->iAddArgDef(def);
					}
				}
			}

			packageFunction->iSetOid(packageFunctions->GetOid(wxT("oid")));
			packageFunction->iSetArgCount(packageFunctions->GetOid(wxT("nargs")));
			packageFunction->iSetReturnType(typeCache[packageFunctions->GetVal(wxT("eltdatatype"))]);

			if (packageFunctions->GetVal(wxT("visibility")) == wxT("+"))
				packageFunction->iSetVisibility(_("Public"));
			else if (packageFunctions->GetVal(wxT("visibility")) == wxT("-"))
				packageFunction->iSetVisibility(_("Private"));
			else
				packageFunction->iSetVisibility(_("Unknown"));

			packageFunction->iSetSource(package->GetBodyInner());

			if (browser)
			{
				browser->AppendObject(obj, packageFunction);
				packageFunctions->MoveNext();
			}
			else
				break;
		}

		delete packageFunctions;
		delete types;
	}
	return packageFunction;
}
Example #4
0
void dlgColumn::SetSecurityPage(const pgColumn *node)
{
	if (node)
	{
		wxString strAcl = node->GetAcl();
		securityPage->lbPrivileges->DeleteAllItems();
		if (!strAcl.IsEmpty())
		{
			wxArrayString aclArray;
			strAcl = strAcl.Mid(1, strAcl.Length() - 2);
			getArrayFromCommaSeparatedList(strAcl, aclArray);
			wxString roleName;
			for (unsigned int index = 0; index < aclArray.Count(); index++)
			{
				wxString strCurrAcl = aclArray[index];

				/*
				* In rare case, we can have ',' (comma) in the user name.
				* But, we need to handle them also
				*/
				if (strCurrAcl.Find(wxChar('=')) == wxNOT_FOUND)
				{
					// Check it is start of the ACL
					if (strCurrAcl[0U] == (wxChar)'"')
						roleName = strCurrAcl + wxT(",");
					continue;
				}
				else
					strCurrAcl = roleName + strCurrAcl;

				if (strCurrAcl[0U] == (wxChar)'"')
					strCurrAcl = strCurrAcl.Mid(1, strCurrAcl.Length() - 1);
				roleName = strCurrAcl.BeforeLast('=');

				wxString value = strCurrAcl.Mid(roleName.Length() + 1).BeforeLast('/');

				int icon = userFactory.GetIconId();

				if (roleName.Left(6).IsSameAs(wxT("group "), false))
				{
					icon = groupFactory.GetIconId();
					roleName = wxT("group ") + qtStrip(roleName.Mid(6));
				}
				else if (roleName.IsEmpty())
				{
					icon = PGICON_PUBLIC;
					roleName = wxT("public");
				}
				else
				{
					roleName = qtStrip(roleName);
					for (unsigned int index = 0; index < groups.Count(); index++)
						if (roleName == groups[index])
						{
							roleName = wxT("group ") + roleName;
							icon = groupFactory.GetIconId();
							break;
						}
				}

				securityPage->lbPrivileges->AppendItem(icon, roleName, value);

				if(changedColumn == NULL)
					currentAcl.Add(roleName + wxT("=") + value);

				// Reset roleName
				roleName.Empty();
			}
		}
	}
}