首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >未定义的对我的函数的引用

未定义的对我的函数的引用
EN

Database Administration用户
提问于 2013-02-21 06:39:12
回答 1查看 711关注 0票数 0

我正在进行一个PostgreSQL8.4服务器端的项目。为了存储一些查询信息,我添加了一些功能。

我需要在start_create_profile中调用exec_simple_query中的两个函数( postgres.c ()和check()),这些函数是由我在/src/backend/utils/misc中名为test.c的文件中编写的。我还用/src/include/utils/编写了库test.h

我正在使用eclipse作为IDE,我得到了一个问题:

代码语言:javascript
复制
undefined reference to `start_create_profile'   /pgsql/src/backend/tcop postgres.c C/C++ Problem

我不明白我的错误在哪里

C是

代码语言:javascript
复制
#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;
    }
}

测试.h是

代码语言:javascript
复制
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);

在postgres.c中,我在exec_simple_query中添加了:

代码语言:javascript
复制
            start_create_profile(querytree_list);

这是在以下postgresql命令之后:

代码语言:javascript
复制
/*
 * 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);

postgres.c的头。

代码语言:javascript
复制
#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>

这是exec_simple_query

代码语言:javascript
复制
/*
 * 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;
}
EN

回答 1

Database Administration用户

发布于 2013-02-22 04:12:21

我认为问题在于,您几乎肯定缺少了函数的声明和函数原型。在我看来,您似乎试图对PostgreSQL源代码进行黑客攻击,以提供在某一点上编码的函数的执行,但由于找不到函数原型,所以无法编译后端。这意味着还需要将函数声明/原型添加到相关的头文件中。

在这一点上,标准C故障排除应用,所以检查头文件,检查函数声明和原型等,这可能解决这个特定的问题。

票数 1
EN
页面原文内容由Database Administration提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://dba.stackexchange.com/questions/35144

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档