Take the 2-minute tour ×
Database Administrators Stack Exchange is a question and answer site for database professionals who wish to improve their database skills and learn from others in the community. It's 100% free, no registration required.

I'm working on a project on postgresql 8.4 server side. I'm adding some functionality in order to store some query informations.

I need to call two functions (start_create_profile() and check()) inside of exec_simple_query in postgres.c These functions are written by me in a file called test.c in /src/backend/utils/misc. I also written the library test.h is in /src/include/utils/

I'm using eclipse as IDE and I'm getting the proble:

undefined reference to `start_create_profile'   /pgsql/src/backend/tcop postgres.c C/C++ Problem

I don't understand where is my mistake

The test.c is

#include "postgres.h"
#include "utils/progProfile.h"
#include "nodes/pg_list.h"
#include <libpq-fe.h>

void start_create_profile(List *querytree_list){

    ListCell *l;
    ListCell *tl;
    FILE *f;

    //if the file exist just open and write
    //else create and write
    f = fopen ("QueryParsed.txt", "a+");

    Query *query_idr = (Query *)linitial(querytree_list);

    // CMD_SELECT=0 CMD_INSERT=1 CMD_UPDATE=2
    switch (query_idr->commandType)
    {
        case CMD_SELECT:
            fputs("CMD_SELECT, ", f);
        break;

        case CMD_INSERT:
            fputs("CMD_INSERT, ", f);
            break;

        case CMD_UPDATE:
            fputs("CMD_UPDATE, ", f);
        break;

        default:
            break;
    }

    //to have the ID of the table
    foreach(l, query_idr->rtable){
        Oid tab_idT = ((RangeTblEntry *) lfirst(l)) ->relid;
        char temp1[10];
        char *tab_idTConverted = itoa(tab_idT, temp1);
        /* This is not a table */
        if (tab_idT == 0)
            continue;

        fputs(" tab_id:  , ", f);
        fputs(tab_idTConverted, f);

    }

    //to have the name of the targer list
    foreach(tl, query_idr->targetList){
        TargetEntry *tle = (TargetEntry *) lfirst(tl);
        Oid tab_id = tle->resorigtbl;
        int tab_idCast=(int)tab_id;
        char temp[10];
        char *tab_idConverted = itoa(tab_idCast, temp);
        char *resname=tle->resname;

        fputs("Name of column:  ", f);
        fputs(resname, f);
        fputs(" ID:  ", f);
        fputs(tab_idConverted, f);
        fputs("\n", f);
    }

    //close the file that we write
    fputs("$", f);
    fclose (f);
}


static char* itoa(int n, char s[])
{
    int i, sign;
    if ((sign = n) < 0)
        n = -n;
    i = 0;
    do
    {
      s[i++] = n % 10 + '0';
    } while ((n /= 10) > 0);

    if (sign < 0)
        s[i++] = '-';

    s[i] = '\0';
    reverse(s);

    return s;
}

static void reverse(char s[])
{
    int i, j;
    char c;

    for (i = 0, j = strlen(s)-1; i<j; i++, j--) {
        c = s[i];
        s[i] = s[j];
        s[j] = c;
    }
}

test.h is

bool TrainingFinished=1;

typedef struct Profile{
    List *subProfile;
    char *nameProgram;
}Profile;

typedef struct SubProfile{
    List *input;
    char *command;
    char *columnName;
    int table;
}SubProfile;



/* interfaces */
extern void start_create_profile(List *querytree_list);
extern void create_profile();
extern void check_anomaly(List *querytree_list);

and in postgres.c in exec_simple_query I had added:

            start_create_profile(querytree_list);

that is after these postgresql command:

/*
 * OK to analyze, rewrite, and plan this query.
 *
 * Switch to appropriate context for constructing querytrees (again,
 * these must outlive the execution context).
 */
oldcontext = MemoryContextSwitchTo(MessageContext);

querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
                                        NULL, 0);

The header of postgres.c

#include "postgres.h"

#include <time.h>
#include <unistd.h>
#include <signal.h>
#include <fcntl.h>
#include <sys/socket.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif
#ifdef HAVE_SYS_RESOURCE_H
#include <sys/time.h>
#include <sys/resource.h>
#endif
#ifdef HAVE_GETOPT_H
#include <getopt.h>
#endif

#ifndef HAVE_GETRUSAGE
#include "rusagestub.h"
#endif

#include "access/printtup.h"
#include "access/xact.h"
#include "catalog/pg_type.h"
#include "commands/async.h"
#include "commands/prepare.h"
#include "libpq/libpq.h"
#include "libpq/pqformat.h"
#include "libpq/pqsignal.h"
#include "miscadmin.h"
#include "nodes/print.h"
#include "optimizer/planner.h"
#include "pgstat.h"
#include "pg_trace.h"
#include "parser/analyze.h"
#include "parser/parser.h"
#include "postmaster/autovacuum.h"
#include "rewrite/rewriteHandler.h"
#include "storage/bufmgr.h"
#include "storage/ipc.h"
#include "storage/proc.h"
#include "storage/sinval.h"
#include "tcop/fastpath.h"
#include "tcop/pquery.h"
#include "tcop/tcopprot.h"
#include "tcop/utility.h"
#include "utils/flatfiles.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/ps_status.h"
#include "utils/snapmgr.h"
#include "mb/pg_wchar.h"

/* Mine */
#include <utils/progProfile.h>

This is the exec_simple_query

/*
 * exec_simple_query
 *
 * Execute a "simple Query" protocol message.
 */
static void
exec_simple_query(const char *query_string)
{
    CommandDest dest = whereToSendOutput;
    MemoryContext oldcontext;
    List       *parsetree_list;
    ListCell   *parsetree_item;
    bool        save_log_statement_stats = log_statement_stats;
    bool        was_logged = false;
    bool        isTopLevel;
    char        msec_str[32];


    /*
     * Report query to various monitoring facilities.
     */
    debug_query_string = query_string;

    pgstat_report_activity(query_string);

    TRACE_POSTGRESQL_QUERY_START(query_string);

    /*
     * We use save_log_statement_stats so ShowUsage doesn't report incorrect
     * results because ResetUsage wasn't called.
     */
    if (save_log_statement_stats)
        ResetUsage();

    /*
     * Start up a transaction command.  All queries generated by the
     * query_string will be in this same command block, *unless* we find a
     * BEGIN/COMMIT/ABORT statement; we have to force a new xact command after
     * one of those, else bad things will happen in xact.c. (Note that this
     * will normally change current memory context.)
     */
    start_xact_command();

    /*
     * Zap any pre-existing unnamed statement.  (While not strictly necessary,
     * it seems best to define simple-Query mode as if it used the unnamed
     * statement and portal; this ensures we recover any storage used by prior
     * unnamed operations.)
     */
    drop_unnamed_stmt();

    /*
     * Switch to appropriate context for constructing parsetrees.
     */
    oldcontext = MemoryContextSwitchTo(MessageContext);

    /*
     * Do basic parsing of the query or queries (this should be safe even if
     * we are in aborted transaction state!)
     */
    parsetree_list = pg_parse_query(query_string);

    /* Log immediately if dictated by log_statement */
    if (check_log_statement(parsetree_list))
    {
        ereport(LOG,
                (errmsg("statement: %s", query_string),
                 errhidestmt(true),
                 errdetail_execute(parsetree_list)));
        was_logged = true;
    }

    /*
     * Switch back to transaction context to enter the loop.
     */
    MemoryContextSwitchTo(oldcontext);

    /*
     * We'll tell PortalRun it's a top-level command iff there's exactly one
     * raw parsetree.  If more than one, it's effectively a transaction block
     * and we want PreventTransactionChain to reject unsafe commands. (Note:
     * we're assuming that query rewrite cannot add commands that are
     * significant to PreventTransactionChain.)
     */
    isTopLevel = (list_length(parsetree_list) == 1);

    /*
     * Run through the raw parsetree(s) and process each one.
     */
    foreach(parsetree_item, parsetree_list)
    {
        Node       *parsetree = (Node *) lfirst(parsetree_item);
        bool        snapshot_set = false;
        const char *commandTag;
        char        completionTag[COMPLETION_TAG_BUFSIZE];
        List       *querytree_list,
                   *plantree_list;
        Portal      portal;
        DestReceiver *receiver;
        int16       format;

        /*
         * Get the command name for use in status display (it also becomes the
         * default completion tag, down inside PortalRun).  Set ps_status and
         * do any special start-of-SQL-command processing needed by the
         * destination.
         */
        commandTag = CreateCommandTag(parsetree);

        set_ps_display(commandTag, false);

        BeginCommand(commandTag, dest);

        /*
         * If we are in an aborted transaction, reject all commands except
         * COMMIT/ABORT.  It is important that this test occur before we try
         * to do parse analysis, rewrite, or planning, since all those phases
         * try to do database accesses, which may fail in abort state. (It
         * might be safe to allow some additional utility commands in this
         * state, but not many...)
         */
        if (IsAbortedTransactionBlockState() &&
            !IsTransactionExitStmt(parsetree))
            ereport(ERROR,
                    (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
                     errmsg("current transaction is aborted, "
                        "commands ignored until end of transaction block")));

        /* Make sure we are in a transaction command */
        start_xact_command();

        /* If we got a cancel signal in parsing or prior command, quit */
        CHECK_FOR_INTERRUPTS();

        /*
         * Set up a snapshot if parse analysis/planning will need one.
         */
        if (analyze_requires_snapshot(parsetree))
        {
            PushActiveSnapshot(GetTransactionSnapshot());
            snapshot_set = true;
        }

        /*
         * OK to analyze, rewrite, and plan this query.
         *
         * Switch to appropriate context for constructing querytrees (again,
         * these must outlive the execution context).
         */
        oldcontext = MemoryContextSwitchTo(MessageContext);

        querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
                                                NULL, 0);


        /*********** Mine **********/

            start_create_profile(querytree_list);

        /*********** Mine **********/

        plantree_list = pg_plan_queries(querytree_list, 0, NULL);

        /* Done with the snapshot used for parsing/planning */
        if (snapshot_set)
            PopActiveSnapshot();

        /* If we got a cancel signal in analysis or planning, quit */
        CHECK_FOR_INTERRUPTS();

        /*
         * Create unnamed portal to run the query or queries in. If there
         * already is one, silently drop it.
         */
        portal = CreatePortal("", true, true);
        /* Don't display the portal in pg_cursors */
        portal->visible = false;

        /*
         * We don't have to copy anything into the portal, because everything
         * we are passing here is in MessageContext, which will outlive the
         * portal anyway.
         */
        PortalDefineQuery(portal,
                          NULL,
                          query_string,
                          commandTag,
                          plantree_list,
                          NULL);

        /*
         * Start the portal.  No parameters here.
         */
        PortalStart(portal, NULL, InvalidSnapshot);

        /*
         * Select the appropriate output format: text unless we are doing a
         * FETCH from a binary cursor.  (Pretty grotty to have to do this here
         * --- but it avoids grottiness in other places.  Ah, the joys of
         * backward compatibility...)
         */
        format = 0;             /* TEXT is default */
        if (IsA(parsetree, FetchStmt))
        {
            FetchStmt  *stmt = (FetchStmt *) parsetree;

            if (!stmt->ismove)
            {
                Portal      fportal = GetPortalByName(stmt->portalname);

                if (PortalIsValid(fportal) &&
                    (fportal->cursorOptions & CURSOR_OPT_BINARY))
                    format = 1; /* BINARY */
            }
        }
        PortalSetResultFormat(portal, 1, &format);

        /*
         * Now we can create the destination receiver object.
         */
        receiver = CreateDestReceiver(dest);
        if (dest == DestRemote)
            SetRemoteDestReceiverParams(receiver, portal);

        /*
         * Switch back to transaction context for execution.
         */
        MemoryContextSwitchTo(oldcontext);

        /*
         * Run the portal to completion, and then drop it (and the receiver).
         */
        (void) PortalRun(portal,
                         FETCH_ALL,
                         isTopLevel,
                         receiver,
                         receiver,
                         completionTag);

        (*receiver->rDestroy) (receiver);

        PortalDrop(portal, false);

        if (IsA(parsetree, TransactionStmt))
        {
            /*
             * If this was a transaction control statement, commit it. We will
             * start a new xact command for the next command (if any).
             */
            finish_xact_command();
        }
        else if (lnext(parsetree_item) == NULL)
        {
            /*
             * If this is the last parsetree of the query string, close down
             * transaction statement before reporting command-complete.  This
             * is so that any end-of-transaction errors are reported before
             * the command-complete message is issued, to avoid confusing
             * clients who will expect either a command-complete message or an
             * error, not one and then the other.  But for compatibility with
             * historical Postgres behavior, we do not force a transaction
             * boundary between queries appearing in a single query string.
             */
            finish_xact_command();
        }
        else
        {
            /*
             * We need a CommandCounterIncrement after every query, except
             * those that start or end a transaction block.
             */
            CommandCounterIncrement();
        }

        /*
         * Tell client that we're done with this query.  Note we emit exactly
         * one EndCommand report for each raw parsetree, thus one for each SQL
         * command the client sent, regardless of rewriting. (But a command
         * aborted by error will not send an EndCommand report at all.)
         */
        EndCommand(completionTag, dest);
    }                           /* end loop over parsetrees */

    /*
     * Close down transaction statement, if one is open.
     */
    finish_xact_command();

    /*
     * If there were no parsetrees, return EmptyQueryResponse message.
     */
    if (!parsetree_list)
        NullCommand(dest);

    /*
     * Emit duration logging if appropriate.
     */
    switch (check_log_duration(msec_str, was_logged))
    {
        case 1:
            ereport(LOG,
                    (errmsg("duration: %s ms", msec_str),
                     errhidestmt(true)));
            break;
        case 2:
            ereport(LOG,
                    (errmsg("duration: %s ms  statement: %s",
                            msec_str, query_string),
                     errhidestmt(true),
                     errdetail_execute(parsetree_list)));
            break;
    }

    if (save_log_statement_stats)
        ShowUsage("QUERY STATISTICS");

    TRACE_POSTGRESQL_QUERY_DONE(query_string);

    debug_query_string = NULL;
}
share|improve this question

closed as off topic by dezso, RolandoMySQLDBA, Jon Seigel, Leigh Riffel, JNK Feb 22 '13 at 16:05

Questions on Database Administrators Stack Exchange are expected to relate to database administration within the scope defined by the community. Consider editing the question or leaving comments for improvement if you believe the question can be reworded to fit within the scope. Read more about reopening questions here.If this question can be reworded to fit the rules in the help center, please edit the question.

2  
And how do we know without seeing your code? :) –  dezso Feb 21 '13 at 7:44
    
Also what was the process used to build/link them? –  Chris Travers Feb 21 '13 at 8:50
    
@dezso sorry, you're right, I've edited the question. –  DarkCoffee Feb 21 '13 at 9:17
1  
Re-reading it looks like you're compiling the whole server. I initially thought you were just compiling an extension. If you're building the server use the standard build system (configure, make, etc for unix, or the src/tools/msvc/ dir for Windows). If you're building an extension use pgxs. In both cases, read the manual for details. postgresql.org/docs/current/static/extend-pgxs.html, postgresql.org/docs/current/static/install-procedure.html, postgresql.org/docs/current/static/install-windows.html –  Craig Ringer Feb 22 '13 at 4:17
1  
Also, "What do you mean with link". Um. cprogramming.com/compilingandlinking.html . –  Craig Ringer Feb 22 '13 at 4:19

1 Answer 1

I think the problem is that you are almost certainly missing a declaration and function prototype for the function. It looks to me like you trying to hack the PostgreSQL source to provide the execution of a function you have coded at a certain point, but you aren't able to compile the back-end because the function prototype is not found. This means you need to add the function declaration/prototype to the relevant header file as well.

At this point standard C troubleshooting applies, so check header files, check function declarations and prototypes, etc. That will probably solve this specific issue.

share|improve this answer

Not the answer you're looking for? Browse other questions tagged or ask your own question.