1
1
//////////////////////////////////////////////////////////////////////////
3
3
// pgAdmin III - PostgreSQL Tools
4
// RCS-ID: $Id: pgFunction.cpp 7205 2008-03-27 19:13:25Z dpage $
5
// Copyright (C) 2002 - 2008, The pgAdmin Development Team
6
// This software is released under the Artistic Licence
4
// RCS-ID: $Id: pgFunction.cpp 7883 2009-05-26 16:41:15Z dpage $
5
// Copyright (C) 2002 - 2009, The pgAdmin Development Team
6
// This software is released under the BSD Licence
8
8
// pgFunction.cpp - function class
189
193
properties->AppendItem(_("Volatility"), GetVolatility());
190
194
properties->AppendItem(_("Security of definer?"), GetSecureDefiner());
191
195
properties->AppendItem(_("Strict?"), GetIsStrict());
196
if (GetConnection()->BackendMinimumVersion(8, 4))
197
properties->AppendItem(_("Window?"), GetIsWindow());
194
200
for (i=0 ; i < configList.GetCount() ; i++)
268
281
if (GetIsProcedure())
270
if (!argNamesArray.Item(i).IsEmpty())
283
if (!argModesArray.Item(i).IsEmpty())
271
285
arg += qtIdent(argNamesArray.Item(i));
289
if (!argNamesArray.Item(i).IsEmpty())
290
arg += qtIdent(argNamesArray.Item(i));
291
arg += wxT(" ") + argModesArray.Item(i);
273
294
if (!argModesArray.Item(i).IsEmpty())
274
296
if (arg.IsEmpty())
275
297
arg += argModesArray.Item(i);
277
299
arg += wxT(" ") + argModesArray.Item(i);
329
361
pgFunction *pgFunctionFactory::AppendFunctions(pgObject *obj, pgSchema *schema, ctlTree *browser, const wxString &restriction)
364
cacheMap typeCache, exprCache;
331
366
pgFunction *function=0;
332
wxString argNamesCol, proConfigCol;
367
wxString argNamesCol, argDefsCol, proConfigCol, proType;
333
368
if (obj->GetConnection()->BackendMinimumVersion(8, 0))
334
369
argNamesCol = wxT("proargnames, ");
370
if (obj->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS) && !obj->GetConnection()->BackendMinimumVersion(8, 4))
371
argDefsCol = wxT("proargdefvals, ");
372
if (obj->GetConnection()->BackendMinimumVersion(8, 4))
373
argDefsCol = wxT("pg_get_expr(proargdefaults, 'pg_catalog.pg_class'::regclass) AS proargdefaultvals, pronargdefaults, ");
335
374
if (obj->GetConnection()->BackendMinimumVersion(8, 3))
336
375
proConfigCol = wxT("proconfig, ");
376
if (obj->GetConnection()->EdbMinimumVersion(8, 1))
377
proType = wxT("protype, ");
338
379
pgSet *functions = obj->GetDatabase()->ExecuteSet(
339
wxT("SELECT pr.oid, pr.xmin, pr.*, format_type(TYP.oid, NULL) AS typname, typns.nspname AS typnsp, lanname, ") + argNamesCol + proConfigCol +
380
wxT("SELECT pr.oid, pr.xmin, pr.*, format_type(TYP.oid, NULL) AS typname, typns.nspname AS typnsp, lanname, ") +
381
argNamesCol + argDefsCol + proConfigCol + proType +
340
382
wxT(" pg_get_userbyid(proowner) as funcowner, description\n")
341
383
wxT(" FROM pg_proc pr\n")
342
384
wxT(" JOIN pg_type typ ON typ.oid=prorettype\n")
349
391
pgSet *types = obj->GetDatabase()->ExecuteSet(wxT(
350
392
"SELECT oid, format_type(oid, NULL) AS typname FROM pg_type"));
356
396
while(!types->Eof())
358
map[types->GetVal(wxT("oid"))] = types->GetVal(wxT("typname"));
398
typeCache[types->GetVal(wxT("oid"))] = types->GetVal(wxT("typname"));
359
399
types->MoveNext();
365
405
while (!functions->Eof())
367
407
bool isProcedure=false;
408
bool hasDefValSupport = false;
368
409
wxString lanname=functions->GetVal(wxT("lanname"));
369
410
wxString typname=functions->GetVal(wxT("typname"));
375
416
// Create the new object
377
418
function = new pgProcedure(schema, functions->GetVal(wxT("proname")));
378
else if (typname == wxT("\"trigger\""))
419
else if (typname == wxT("\"trigger\"") || typname == wxT("trigger"))
379
420
function = new pgTriggerFunction(schema, functions->GetVal(wxT("proname")));
381
422
function = new pgFunction(schema, functions->GetVal(wxT("proname")));
384
424
// Tokenize the arguments
385
425
wxStringTokenizer argTypesTkz(wxEmptyString), argModesTkz(wxEmptyString);
386
queryTokenizer argNamesTkz(wxEmptyString, (wxChar)',');
426
queryTokenizer argNamesTkz(wxEmptyString, (wxChar)','), argDefsTkz(wxEmptyString, (wxChar)',');
429
// Support for Default Value in PG 8.4
430
wxArrayString argDefValArray;
389
432
// We always have types
390
433
argTypesTkz.SetString(functions->GetVal(wxT("proargtypes")));
401
444
if (!obj->GetConnection()->EdbMinimumVersion(8, 1) && isProcedure)
402
445
argModesTkz.SetString(functions->GetVal(wxT("proargdirs")));
447
if (obj->GetConnection()->EdbMinimumVersion(8, 1))
448
function->iSetProcType(functions->GetLong(wxT("protype")));
404
450
// EDB 8.1 and PostgreSQL 8.1 have modes in pg_proc.proargmodes
405
451
if (obj->GetConnection()->BackendMinimumVersion(8, 1))
413
459
argModesTkz.SetString(tmp.Mid(1, tmp.Length()-2), wxT(","));
462
// EDB 8.3: Function defaults
463
if (obj->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS) &&
464
!obj->GetConnection()->BackendMinimumVersion(8, 4))
466
tmp = functions->GetVal(wxT("proargdefvals"));
468
argDefsTkz.SetString(tmp.Mid(1, tmp.Length()-2), wxT(","));
471
if (obj->GetConnection()->BackendMinimumVersion(8, 4))
473
hasDefValSupport = true;
474
tmp = functions->GetVal(wxT("proargdefaultvals"));
475
getArrayFromCommaSeparatedList(tmp, argDefValArray);
477
function->iSetArgDefValCount(functions->GetLong(wxT("pronargdefaults")));
479
// Check if it is a window function
480
function->iSetIsWindow(functions->GetBool(wxT("proiswindow")));
483
function->iSetIsWindow(false);
416
485
// Now iterate the arguments and build the arrays
417
wxString type, name, mode;
486
wxString type, name, mode, def;
419
489
while (argTypesTkz.HasMoreTokens())
421
491
// Add the arg type. This is a type oid, so
422
492
// look it up in the hashmap
423
493
type = argTypesTkz.GetNextToken();
424
function->iAddArgType(map[type]);
494
function->iAddArgType(typeCache[type]);
426
496
// Now add the name, stripping the quotes and \" if
449
519
mode = wxT("INOUT");
450
520
else if (mode == wxT("3"))
451
521
mode = wxT("IN OUT");
522
else if (mode == wxT("v"))
523
mode = wxT("VARIADIC");
524
else if (mode == wxT("t"))
453
528
mode = wxT("IN");
455
532
function->iAddArgMode(mode);
458
536
function->iAddArgMode(wxEmptyString);
540
// Finally the defaults, as we got them.
541
if (!hasDefValSupport)
542
def = argDefsTkz.GetNextToken();
544
if (hasDefValSupport)
546
// We will process this later
548
else if (!def.IsEmpty() && !def.IsSameAs(wxT("-")))
551
def = def.Mid(1, def.Length()-2);
553
// Check the cache first - if we don't have a value, get it and cache for next time
554
wxString val = exprCache[def];
555
if (val == wxEmptyString)
557
val = obj->GetDatabase()->ExecuteScalar(wxT("SELECT pg_get_expr('") + def + wxT("', 'pg_catalog.pg_class'::regclass)"));
558
exprCache[def] = val;
560
function->iAddArgDef(val);
563
function->iAddArgDef(wxEmptyString);
566
function->iSetArgCount(functions->GetLong(wxT("pronargs")));
568
wxString strReturnTableArgs;
569
// Process default values
570
if (obj->GetConnection()->BackendMinimumVersion(8, 4) &&
571
function->GetArgCount() != 0)
573
size_t currINindex = 0;
574
for (size_t index = 0; index < function->GetArgModesArray().Count(); index++)
576
if (function->GetArgModesArray()[index] == wxT("IN") ||
577
function->GetArgModesArray()[index].IsEmpty())
580
if (function->GetArgDefValCount() != 0 &&
581
nArgsIN < (size_t)function->GetArgDefValCount())
583
if (argDefValArray[currINindex++] != wxT("-"))
584
function->iAddArgDef(argDefValArray[currINindex-1]);
587
else if(function->GetArgModesArray()[index] == wxT("TABLE"))
589
if (strReturnTableArgs.Length() > 0)
590
strReturnTableArgs += wxT(", ");
591
wxString strName = function->GetArgNamesArray()[index];
592
if (!strName.IsEmpty())
593
strReturnTableArgs += strName + wxT(" ");
594
strReturnTableArgs += function->GetArgTypesArray()[index];
596
function->iAddArgDef(wxEmptyString);
461
600
function->iSetOid(functions->GetOid(wxT("oid")));
462
function->iSetXid(functions->GetOid(wxT("xmin")));
601
function->iSetXid(functions->GetOid(wxT("xmin")));
463
602
function->UpdateSchema(browser, functions->GetOid(wxT("pronamespace")));
464
603
function->iSetOwner(functions->GetVal(wxT("funcowner")));
465
604
function->iSetAcl(functions->GetVal(wxT("proacl")));
466
function->iSetArgCount(functions->GetLong(wxT("pronargs")));
467
function->iSetReturnType(functions->GetVal(wxT("typname")));
605
wxString strType = functions->GetVal(wxT("typname"));
606
if (strType.Lower() == wxT("record") && !strReturnTableArgs.IsEmpty())
608
strType = wxT("TABLE(") + strReturnTableArgs + wxT(")");
610
function->iSetReturnType(strType);
468
611
function->iSetComment(functions->GetVal(wxT("description")));
470
613
function->iSetLanguage(lanname);
564
707
#include "images/function.xpm"
565
708
#include "images/functions.xpm"
567
pgFunctionFactory::pgFunctionFactory(const wxChar *tn, const wxChar *ns, const wxChar *nls, char **img)
710
pgFunctionFactory::pgFunctionFactory(const wxChar *tn, const wxChar *ns, const wxChar *nls, const char **img)
568
711
: pgSchemaObjFactory(tn, ns, nls, img)
570
713
metaType = PGM_FUNCTION;