~ubuntu-branches/debian/sid/pgadmin3/sid

« back to all changes in this revision

Viewing changes to pgadmin/schema/pgFunction.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Gerfried Fuchs
  • Date: 2009-07-30 12:27:16 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20090730122716-fddbh42on721bbs2
Tags: 1.10.0-1
* New upstream release.
* Adjusted watch file to match release candidates.
* Updated to Standards-Version 3.8.2:
  - Moved to Section: database.
  - Add DEB_BUILD_OPTIONS support for parallel building.
  - Move from findstring to filter suggestion for DEB_BUILD_OPTIONS parsing.
* pgagent got split into its own separate source package by upstream.
* Exclude Docs.vcproj from installation.
* Move doc-base.enus from pgadmin3 to pgadmin3-data package, the files are
  in there too.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
//////////////////////////////////////////////////////////////////////////
2
2
//
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
7
7
//
8
8
// pgFunction.cpp - function class
9
9
//
15
15
// App headers
16
16
#include "pgAdmin3.h"
17
17
#include "frm/menu.h"
 
18
#include "utils/pgfeatures.h"
18
19
#include "utils/misc.h"
19
20
#include "schema/pgFunction.h"
20
21
#include "frm/frmReport.h"
84
85
            + wxT("\n\nCREATE OR REPLACE FUNCTION ") + qtName;
85
86
 
86
87
        // Use Oracle style syntax for edb-spl functions
87
 
        if (GetLanguage() == wxT("edbspl"))
 
88
        if (GetLanguage() == wxT("edbspl") && GetProcType() == 2)
88
89
        {
89
90
            sql += wxT("\nRETURN ");
90
91
            sql += GetReturnType();
98
99
        else
99
100
        {
100
101
            sql += wxT("\n  RETURNS ");
101
 
            if (GetReturnAsSet())
 
102
            if (GetReturnAsSet() && !GetReturnType().StartsWith(wxT("TABLE")))
102
103
                sql += wxT("SETOF ");
103
104
            sql += GetReturnType();
104
105
 
115
116
                else
116
117
                    sql += qtDbString(GetSource());
117
118
            }
118
 
            sql += wxT("\n  LANGUAGE '") + GetLanguage() + wxT("' ") + GetVolatility();
 
119
            sql += wxT("\n  LANGUAGE '") + GetLanguage() + wxT("' ");
 
120
            if (GetConnection()->BackendMinimumVersion(8, 4) && GetIsWindow())
 
121
                sql += wxT("WINDOW ");
 
122
            sql += GetVolatility();
119
123
 
120
124
            if (GetIsStrict())
121
125
                sql += wxT(" STRICT");
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());
192
198
 
193
199
        size_t i;
194
200
        for (i=0 ; i < configList.GetCount() ; i++)
260
266
 
261
267
    for (unsigned int i=0; i < argTypesArray.Count(); i++)
262
268
    {
 
269
        /*
 
270
        * All Table arguments lies at the end of the list
 
271
        * Do not include them as the part of the argument list
 
272
        */
 
273
        if (argModesArray.Item(i) == wxT("TABLE"))
 
274
            break;
 
275
 
263
276
        if (args.Length() > 0)
264
277
            args += wxT(", ");
265
278
 
267
280
 
268
281
        if (GetIsProcedure())
269
282
        {
270
 
            if (!argNamesArray.Item(i).IsEmpty())
 
283
            if (!argModesArray.Item(i).IsEmpty())
 
284
            {
271
285
                arg += qtIdent(argNamesArray.Item(i));
 
286
            }
 
287
            else
 
288
            {
 
289
                if (!argNamesArray.Item(i).IsEmpty())
 
290
                    arg += qtIdent(argNamesArray.Item(i));
 
291
                arg += wxT(" ") + argModesArray.Item(i);
 
292
            }
272
293
 
273
294
            if (!argModesArray.Item(i).IsEmpty())
 
295
            {
274
296
                if (arg.IsEmpty())
275
297
                    arg += argModesArray.Item(i);
276
298
                else
277
299
                    arg += wxT(" ") + argModesArray.Item(i);
 
300
            }
278
301
        }
279
302
        else
280
303
        {
282
305
                arg += argModesArray.Item(i);
283
306
 
284
307
            if (!argNamesArray.Item(i).IsEmpty())
 
308
            {
285
309
                if (arg.IsEmpty())
286
310
                    arg += qtIdent(argNamesArray.Item(i));
287
311
                else
288
312
                    arg += wxT(" ") + qtIdent(argNamesArray.Item(i));
 
313
            }
289
314
        }
290
315
 
291
316
        if (!arg.IsEmpty())
293
318
        else
294
319
            arg += argTypesArray.Item(i);
295
320
 
 
321
        // Parameter default value
 
322
        if (GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS) || GetConnection()->BackendMinimumVersion(8, 4))
 
323
        {
 
324
            if (!argModesArray.Item(i).IsSameAs(wxT("OUT"), false) && !argDefsArray.Item(i).IsEmpty())
 
325
                arg += wxT(" DEFAULT ") + argDefsArray.Item(i);
 
326
        }
 
327
 
296
328
        args += arg;
297
329
    }
298
330
    return args;
305
337
    for (unsigned int i=0; i < argTypesArray.Count(); i++)
306
338
    {
307
339
        // OUT parameters are not considered part of the signature, except for EDB-SPL
308
 
        if (argModesArray.Item(i) != wxT("OUT"))
 
340
        if (argModesArray.Item(i) != wxT("OUT") && argModesArray.Item(i) != wxT("TABLE"))
309
341
        {
310
342
            if (args.Length() > 0)
311
343
                args += wxT(", ");
314
346
        }
315
347
        else
316
348
        {
317
 
            if (GetLanguage() == wxT("edbspl"))
 
349
            if (GetLanguage() == wxT("edbspl") && argModesArray.Item(i) != wxT("TABLE"))
318
350
            {
319
351
                if (args.Length() > 0)
320
352
                    args += wxT(", ");
328
360
 
329
361
pgFunction *pgFunctionFactory::AppendFunctions(pgObject *obj, pgSchema *schema, ctlTree *browser, const wxString &restriction)
330
362
{
 
363
    // Caches
 
364
    cacheMap typeCache, exprCache;
 
365
 
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, ");
337
378
 
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"));
351
393
 
352
 
    typeMap map;
353
 
 
354
 
        if (types)
355
 
        {
 
394
    if (types)
 
395
    {
356
396
        while(!types->Eof())
357
397
        {
358
 
            map[types->GetVal(wxT("oid"))] = types->GetVal(wxT("typname"));
 
398
            typeCache[types->GetVal(wxT("oid"))] = types->GetVal(wxT("typname"));
359
399
            types->MoveNext();
360
400
        }
361
 
        }
 
401
    }
362
402
 
363
403
    if (functions)
364
404
    {
365
405
        while (!functions->Eof())
366
406
        {
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"));
370
411
 
375
416
            // Create the new object
376
417
            if (isProcedure)
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")));
380
421
            else
381
422
                function = new pgFunction(schema, functions->GetVal(wxT("proname")));
382
 
 
383
423
            
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)',');
387
427
            wxString tmp;
388
428
 
 
429
            // Support for Default Value in PG 8.4
 
430
            wxArrayString argDefValArray;
 
431
 
389
432
            // We always have types
390
433
            argTypesTkz.SetString(functions->GetVal(wxT("proargtypes")));
391
434
 
401
444
            if (!obj->GetConnection()->EdbMinimumVersion(8, 1) && isProcedure)
402
445
                argModesTkz.SetString(functions->GetVal(wxT("proargdirs")));
403
446
 
 
447
            if (obj->GetConnection()->EdbMinimumVersion(8, 1))
 
448
                function->iSetProcType(functions->GetLong(wxT("protype")));
 
449
 
404
450
            // EDB 8.1 and PostgreSQL 8.1 have modes in pg_proc.proargmodes
405
451
            if (obj->GetConnection()->BackendMinimumVersion(8, 1))
406
452
            {
413
459
                    argModesTkz.SetString(tmp.Mid(1, tmp.Length()-2), wxT(","));
414
460
            }
415
461
 
 
462
            // EDB 8.3: Function defaults
 
463
            if (obj->GetConnection()->HasFeature(FEATURE_FUNCTION_DEFAULTS) &&
 
464
                !obj->GetConnection()->BackendMinimumVersion(8, 4))
 
465
            {
 
466
                tmp = functions->GetVal(wxT("proargdefvals"));
 
467
                if (!tmp.IsEmpty())
 
468
                    argDefsTkz.SetString(tmp.Mid(1, tmp.Length()-2), wxT(","));
 
469
            }
 
470
 
 
471
            if (obj->GetConnection()->BackendMinimumVersion(8, 4))
 
472
            {
 
473
                hasDefValSupport = true;
 
474
                tmp = functions->GetVal(wxT("proargdefaultvals"));
 
475
                getArrayFromCommaSeparatedList(tmp, argDefValArray);
 
476
 
 
477
                function->iSetArgDefValCount(functions->GetLong(wxT("pronargdefaults")));
 
478
 
 
479
                // Check if it is a window function
 
480
                function->iSetIsWindow(functions->GetBool(wxT("proiswindow")));
 
481
            }
 
482
                        else
 
483
                function->iSetIsWindow(false);
 
484
 
416
485
            // Now iterate the arguments and build the arrays
417
 
            wxString type, name, mode;
 
486
            wxString type, name, mode, def;
 
487
            size_t nArgsIN = 0;
418
488
            
419
489
            while (argTypesTkz.HasMoreTokens())
420
490
            {
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]);
425
495
 
426
496
                // Now add the name, stripping the quotes and \" if
427
497
                // necessary. 
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"))
 
525
                        mode = wxT("TABLE");
452
526
                    else
 
527
                    {
453
528
                        mode = wxT("IN");
 
529
                        nArgsIN++;
 
530
                    }
454
531
 
455
532
                    function->iAddArgMode(mode);
456
533
                }
457
534
                else
 
535
                {
458
536
                    function->iAddArgMode(wxEmptyString);
 
537
                    nArgsIN++;
 
538
                }
 
539
 
 
540
                // Finally the defaults, as we got them.
 
541
                if (!hasDefValSupport)
 
542
                    def = argDefsTkz.GetNextToken();
 
543
 
 
544
                if (hasDefValSupport)
 
545
                {
 
546
                    // We will process this later
 
547
                }
 
548
                else if (!def.IsEmpty() && !def.IsSameAs(wxT("-")))
 
549
                {
 
550
                    if (def[0] == '"')
 
551
                        def = def.Mid(1, def.Length()-2);
 
552
 
 
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)
 
556
                    {
 
557
                        val = obj->GetDatabase()->ExecuteScalar(wxT("SELECT pg_get_expr('") + def + wxT("', 'pg_catalog.pg_class'::regclass)"));
 
558
                        exprCache[def] = val;
 
559
                    }
 
560
                    function->iAddArgDef(val);
 
561
                }
 
562
                else
 
563
                    function->iAddArgDef(wxEmptyString);
 
564
            }
 
565
            
 
566
            function->iSetArgCount(functions->GetLong(wxT("pronargs")));
 
567
 
 
568
            wxString strReturnTableArgs;
 
569
            // Process default values
 
570
            if (obj->GetConnection()->BackendMinimumVersion(8, 4) &&
 
571
                function->GetArgCount() != 0)
 
572
            {
 
573
                size_t currINindex = 0;
 
574
                for (size_t index = 0; index < function->GetArgModesArray().Count(); index++)
 
575
                {
 
576
                    if (function->GetArgModesArray()[index] == wxT("IN") ||
 
577
                        function->GetArgModesArray()[index].IsEmpty())
 
578
                    {
 
579
                        nArgsIN--;
 
580
                        if (function->GetArgDefValCount() != 0 &&
 
581
                            nArgsIN < (size_t)function->GetArgDefValCount())
 
582
                        {
 
583
                            if (argDefValArray[currINindex++] != wxT("-"))
 
584
                                function->iAddArgDef(argDefValArray[currINindex-1]);
 
585
                        }
 
586
                    }
 
587
                    else if(function->GetArgModesArray()[index] == wxT("TABLE"))
 
588
                    {
 
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];
 
595
                    }
 
596
                    function->iAddArgDef(wxEmptyString);
 
597
                }
459
598
            }
460
599
 
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())
 
607
            {
 
608
                strType = wxT("TABLE(") + strReturnTableArgs + wxT(")");
 
609
            }
 
610
            function->iSetReturnType(strType);
468
611
            function->iSetComment(functions->GetVal(wxT("description")));
469
612
 
470
613
            function->iSetLanguage(lanname);
493
636
            if (browser)
494
637
            {
495
638
                browser->AppendObject(obj, function);
496
 
                            functions->MoveNext();
 
639
                functions->MoveNext();
497
640
            }
498
641
            else
499
642
                break;
500
643
        }
501
644
 
502
 
                delete functions;
 
645
        delete functions;
503
646
        delete types;
504
647
    }
505
648
    return function;
564
707
#include "images/function.xpm"
565
708
#include "images/functions.xpm"
566
709
 
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)
569
712
{
570
713
    metaType = PGM_FUNCTION;