• 发个C语言连接Postgresql程序(转)


    一直用的是Oracle,今天要在postgresql写个程序,查了半天的pg官方文档件才搞定。

    官方的例子有点简单,我把项目中的程序直接发过来供后来者学习和参考。

    备注:
    1,这个程序功能是使2台服务器的postgresql数据库中的一个表保持一致。
    2,加了进程重启功能。
    3,postgresql有自动提交回滚功能,害的我在官方api文档找了半天的事务回滚在哪里(高手莫笑,哈哈)
    4,程序最好总是在BEGIN和END之间操作数据库,哪怕仅仅是select操作。
    5,若遇乱码问题,请在sql语句前加set client_encoding = 'GBK';
    /*
    *Program Name : updateplicheck.c
    *Author : Liu Lin
    *Date : 20090701
    */
    #include "public.h"
    #include "db_manager.h"
    #include "libpq-fe.h"
    #include <stdio.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <fcntl.h>

    static void sig_child(int signo);
    static void task_fork();
    static void run_task();

    int main(void)
    {
        int pid;                    //创建守护进程开始
        
        if ((pid = fork()) < 0)
        {
            LOGLINE; LOG("创建进程操作失败");
            exit(1);
        }
        
        if (pid > 0)
            exit(0);
            
        setsid();
        signal(SIGHUP, SIG_IGN);   
        umask(0);                  //创建守护进程结束
        
        signal(SIGCHLD, sig_child);
           
        task_fork();
        
        while (1)
        {
            pause();
        }  
        
    }

    static void task_fork()
    {
        pid_t pid;
        
        if ((pid = fork()) < 0)
        {
            LOGLINE, LOG("创建子进程失败");
            exit(1);
        }
        
        if (pid == 0)  
        {
            signal(SIGCHLD, SIG_DFL); 
            run_task();
            exit(0);
        }
    }

    static void run_task(void)
    {
        char conninfo[256] = {0};  
        PGconn *conn;  //连接代理服务器数据库
        PGresult *res;
        PGconn *conn2; //连接本地服务器数据库
        PGresult *res2;
        int status; 
        char sql_que[1024] = {0};
        int i;   
        int update_times = 0;
        
        while (update_times < 12*7)//每个进程只负责一周的更新,防止内存泄露
        {
            update_times++;
            memset(conninfo, 0, sizeof(conninfo));
            strcpy(conninfo, "host=192.168.1.110 dbname=ydds user=postgres password=postgres port=5432 connect_timeout=30");  
            conn = PQconnectdb(conninfo);  
            
            if(PQstatus(conn) != CONNECTION_OK)  
            {   
                LOGLINE; LOG("与更新源postgresql数据库连接失败,时间是[%s]", TIME());
                PQfinish(conn);
                sleep(60*60);
                continue;
            }
            else
            {
                LOGLINE; LOG("与更新源postgresql数据库连接成功,时间是[%s]", TIME());
            }  
            
            memset(conninfo, 0, sizeof(conninfo));
            strcpy(conninfo, "host=localhost dbname=ydds user=postgres password=postgres port=5432 connect_timeout=30");  
            conn2 = PQconnectdb(conninfo);  
            
            if(PQstatus(conn2) != CONNECTION_OK)  
            {
                LOGLINE; LOG("与本地postgresql数据库连接失败,时间是[%s]", TIME());
                PQfinish(conn);
                PQfinish(conn2);
                sleep(60*60);
                continue;
            }
            else
            {
                LOGLINE; LOG("与本地postgresql数据库连接成功,时间是[%s]", TIME());
            }  
            
            res2 = PQexec(conn2, "BEGIN");
            
            if(PQresultStatus(res2) != PGRES_COMMAND_OK) //成功完成一个不返回数据的命令
            {
                LOGLINE; LOG("执行BEGIN失败[%s]", PQerrorMessage(conn));
                PQclear(res2);
                PQfinish(conn);
                PQfinish(conn2);
                sleep(60*60);
                continue;
            }
            
            PQclear(res2);
            
            memset(sql_que, 0, sizeof(sql_que));
            sprintf(sql_que, "select adm_no, adm_name, pli_no, pli_name from bank_pli_check");
            res = PQexec(conn, sql_que);
            
            status = PQresultStatus(res); 
            
            if (status != PGRES_TUPLES_OK) //成功执行一个返回数据的查询查询
            { 
                LOGLINE; LOG("查询表bank_pli_check失败");
                PQclear(res); 
                PQfinish(conn);
                PQfinish(conn2);
                sleep(60*60);
                continue;
            }
            
            for (i = 0; i < PQntuples(res); i++)
            {
                memset(sql_que, 0, sizeof(sql_que));
                sprintf(sql_que, "select pli_no from bank_pli_check where pli_no = '%s'", PQgetvalue(res, i, 2));
                res2 = PQexec(conn2, sql_que);//查看该条记录是否已经存在
                status = PQresultStatus(res2);
                
                if (status != PGRES_TUPLES_OK)//注意一个碰巧检索了零条元组的SELECT仍然显示PGRES_TUPLES_OK
                { 
                    LOGLINE; LOG("查询表bank_pli_check失败");
                    PQclear(res); 
                    PQclear(res2); 
                    PQfinish(conn);
                    PQfinish(conn2);
                    sleep(60*60);
                    continue;
                }
                
                if (PQntuples(res2) != 0)
                {
                    LOGLINE; LOG("记录pli=[%s]已经在bank_pli_check存在", PQgetvalue(res, i, 2));
                    PQclear(res2);
                }
                else
                {
                    PQclear(res2);
                    memset(sql_que, 0, sizeof(sql_que));
                    sprintf(sql_que, "insert into bank_pli_check (adm_no, adm_name, pli_no, pli_name) values ('%s', '%s', '%s', '%s')", PQgetvalue(res, i, 0), PQgetvalue(res, i, 1), PQgetvalue(res, i, 2), PQgetvalue(res, i, 3));
                    res2 = PQexec(conn2, sql_que);//没有的记录将更新到表里面
                    status = PQresultStatus(res2);
                    
                    if (status == PGRES_COMMAND_OK)
                    {
                        LOGLINE; LOG("记录pli=[%s]已经更新到bank_pli_check表里", PQgetvalue(res, i, 2));
                    }
                    else
                    {
                        LOGLINE; LOG("记录pli=[%s]插入bank_pli_check表失败", PQgetvalue(res, i, 2));
                    }
                        
                }
                
            }
            
            res2 = PQexec(conn2, "END");
            PQclear(res);
            PQclear(res2);
            PQfinish(conn);
            PQfinish(conn2);
            sleep(60*60);
        }
        
        return;
    }

    static void sig_child(int signo)
    {
            pid_t pid;
            int status;
            
            while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
            {
            LOGLINE; LOG("子进程[%d]]退出, 时间是[%s]", pid, TIME());
            task_fork();
        }
        
        return;
    }

    static int LOG_INIT(void)
    {
        time_t timep;
        struct tm *time_ptr = NULL;
        
        time(&timep);
        time_ptr = localtime(&timep);
        
        memset(g_log_file, 0, sizeof(g_log_file));
        sprintf(g_log_file, "%s%s.log.%d%02d%02d", LOG_PATH, __FILE__, (1900 + time_ptr->tm_year), (1 + time_ptr->tm_mon), (time_ptr->tm_mday));
        memset(g_source_file, 0, sizeof(g_source_file));
        strcpy(g_source_file, __FILE__);
        
        return 0;
    }

    http://bbs2.chinaunix.net/thread-1497010-1-1.html

    aliyun活动 https://www.aliyun.com/acts/limit-buy?userCode=re2o7acl
  • 相关阅读:
    软工课设第一周周五报告
    软工课设第一周周四报告
    软工课设第一周周三报告
    软工课设第一周周二报告
    软工课设第一周周一报告
    团队项目记录4
    团队项目记录3
    团队项目记录2
    jQuery 打气球小游戏 点击气球爆炸效果
    计网第二章:物理层
  • 原文地址:https://www.cnblogs.com/wangbin/p/1517871.html
Copyright © 2020-2023  润新知