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; } } }
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; }
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; }
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(); } } } }