LCOV - code coverage report
Current view: top level - src/interfaces/ecpg/ecpglib - cursor.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13devel Lines: 65 83 78.3 %
Date: 2019-08-24 15:07:19 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* src/interfaces/ecpg/ecpglib/cursor.c */
       2             : 
       3             : #define POSTGRES_ECPG_INTERNAL
       4             : #include "postgres_fe.h"
       5             : 
       6             : #include <ctype.h>
       7             : #include <locale.h>
       8             : #include <string.h>
       9             : 
      10             : #include "ecpgtype.h"
      11             : #include "ecpglib.h"
      12             : #include "ecpgerrno.h"
      13             : #include "ecpglib_extern.h"
      14             : #include "sqlca.h"
      15             : 
      16             : static void add_cursor(const int, const char *, const char *);
      17             : static void remove_cursor(const char *, struct connection *);
      18             : static bool find_cursor(const char *, const struct connection *);
      19             : 
      20             : /*
      21             :  *  Function: Handle the EXEC SQL OPEN cursor statement:
      22             :  *  Input:
      23             :  *      cursor_name --- cursor name
      24             :  *      prepared_name --- prepared name
      25             :  *      others --- keep same as the parameters in ECPGdo() function
      26             :  */
      27             : bool
      28         152 : ECPGopen(const char *cursor_name, const char *prepared_name,
      29             :          const int lineno, const int compat, const int force_indicator,
      30             :          const char *connection_name, const bool questionmarks,
      31             :          const int st, const char *query,...)
      32             : {
      33             :     va_list     args;
      34             :     bool        status;
      35         152 :     const char *real_connection_name = NULL;
      36             : 
      37         152 :     if (!query)
      38             :     {
      39           0 :         ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
      40           0 :         return false;
      41             :     }
      42             : 
      43             :     /*
      44             :      * If the declared name is referred by the PREPARE statement then the
      45             :      * prepared_name is same as declared name
      46             :      */
      47         152 :     real_connection_name = ecpg_get_con_name_by_declared_name(prepared_name);
      48         152 :     if (real_connection_name)
      49             :     {
      50             :         /* Add the cursor name into the declared node */
      51           8 :         ecpg_update_declare_statement(prepared_name, cursor_name, lineno);
      52             :     }
      53             :     else
      54             :     {
      55             :         /*
      56             :          * If can't get the connection name by declared name then using
      57             :          * connection name coming from the parameter connection_name
      58             :          */
      59         144 :         real_connection_name = connection_name;
      60             :     }
      61             : 
      62             : 
      63             :     /* Add the cursor into the connection */
      64         152 :     add_cursor(lineno, cursor_name, real_connection_name);
      65             : 
      66         152 :     va_start(args, query);
      67             : 
      68         152 :     status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
      69             : 
      70         152 :     va_end(args);
      71             : 
      72         152 :     return status;
      73             : }
      74             : 
      75             : 
      76             : /*
      77             :  *  Function: Handle the EXEC SQL FETCH/MOVE CURSOR statements:
      78             :  *  Input:
      79             :  *      cursor_name --- cursor name
      80             :  *      others --- keep same as the parameters in ECPGdo() function
      81             :  */
      82             : bool
      83         540 : ECPGfetch(const char *cursor_name,
      84             :           const int lineno, const int compat, const int force_indicator,
      85             :           const char *connection_name, const bool questionmarks,
      86             :           const int st, const char *query,...)
      87             : {
      88             :     va_list     args;
      89             :     bool        status;
      90         540 :     const char *real_connection_name = NULL;
      91             : 
      92         540 :     if (!query)
      93             :     {
      94           0 :         ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
      95           0 :         return (false);
      96             :     }
      97             : 
      98         540 :     real_connection_name = ecpg_get_con_name_by_cursor_name(cursor_name);
      99         540 :     if (real_connection_name == NULL)
     100             :     {
     101             :         /*
     102             :          * If can't get the connection name by cursor name then using
     103             :          * connection name coming from the parameter connection_name
     104             :          */
     105         516 :         real_connection_name = connection_name;
     106             :     }
     107             : 
     108         540 :     va_start(args, query);
     109             : 
     110         540 :     status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
     111             : 
     112         540 :     va_end(args);
     113             : 
     114         540 :     return status;
     115             : }
     116             : 
     117             : 
     118             : /*
     119             :  *  Function: Handle the EXEC SQL CLOSE CURSOR statements:
     120             :  *  Input:
     121             :  *      cursor_name --- cursor name
     122             :  *      others --- keep same as the parameters in ECPGdo() function
     123             :  */
     124             : bool
     125         144 : ECPGclose(const char *cursor_name,
     126             :           const int lineno, const int compat, const int force_indicator,
     127             :           const char *connection_name, const bool questionmarks,
     128             :           const int st, const char *query,...)
     129             : {
     130             :     va_list     args;
     131             :     bool        status;
     132         144 :     const char *real_connection_name = NULL;
     133         144 :     struct connection *con = NULL;
     134             : 
     135         144 :     if (!query)
     136             :     {
     137           0 :         ecpg_raise(lineno, ECPG_EMPTY, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
     138           0 :         return false;
     139             :     }
     140             : 
     141         144 :     real_connection_name = ecpg_get_con_name_by_cursor_name(cursor_name);
     142         144 :     if (real_connection_name == NULL)
     143             :     {
     144             :         /*
     145             :          * If can't get the connection name by cursor name then using
     146             :          * connection name coming from the parameter connection_name
     147             :          */
     148         136 :         real_connection_name = connection_name;
     149             :     }
     150             : 
     151         144 :     con = ecpg_get_connection(real_connection_name);
     152             : 
     153             :     /* send the query to backend */
     154         144 :     va_start(args, query);
     155             : 
     156         144 :     status = ecpg_do(lineno, compat, force_indicator, real_connection_name, questionmarks, st, query, args);
     157             : 
     158         144 :     va_end(args);
     159             : 
     160             :     /* if it fails, raise an error */
     161         144 :     if (!status)
     162             :     {
     163           0 :         ecpg_raise(lineno, ECPG_INVALID_CURSOR, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
     164           0 :         return false;
     165             :     }
     166             : 
     167             :     /* check the existence of the cursor in the connection */
     168         144 :     if (find_cursor(cursor_name, con) == true)
     169         144 :         remove_cursor(cursor_name, con);
     170             : 
     171         144 :     return status;
     172             : }
     173             : 
     174             : /*
     175             :  * Function: Add a cursor into the connection
     176             :  * The duplication of cursor_name is checked at ecpg.trailer,
     177             :  * so we don't check here.
     178             :  */
     179             : static void
     180         152 : add_cursor(const int lineno, const char *cursor_name, const char *connection_name)
     181             : {
     182             :     struct connection *con;
     183         152 :     struct cursor_statement *new = NULL;
     184             : 
     185         152 :     if (!cursor_name)
     186             :     {
     187           0 :         ecpg_raise(lineno, ECPG_INVALID_CURSOR, ECPG_SQLSTATE_ECPG_INTERNAL_ERROR, NULL);
     188           0 :         return;
     189             :     }
     190             : 
     191         152 :     con = ecpg_get_connection(connection_name);
     192         152 :     if (!con)
     193             :     {
     194           0 :         ecpg_raise(lineno, ECPG_NO_CONN, ECPG_SQLSTATE_CONNECTION_DOES_NOT_EXIST,
     195             :                    connection_name ? connection_name : ecpg_gettext("NULL"));
     196           0 :         return;
     197             :     }
     198             : 
     199             :     /* allocate a node to store the new cursor */
     200         152 :     new = (struct cursor_statement *) ecpg_alloc(sizeof(struct cursor_statement), lineno);
     201         152 :     if (new)
     202             :     {
     203         152 :         new->name = ecpg_strdup(cursor_name, lineno);
     204         152 :         new->next = con->cursor_stmts;
     205         152 :         con->cursor_stmts = new;
     206             :     }
     207             : }
     208             : 
     209             : /*
     210             :  * Function: Remove the cursor from the connection
     211             :  */
     212             : static void
     213         144 : remove_cursor(const char *cursor_name, struct connection *connection)
     214             : {
     215         144 :     struct cursor_statement *cur = NULL;
     216         144 :     struct cursor_statement *prev = NULL;
     217             : 
     218         144 :     if (!connection || !cursor_name)
     219           0 :         return;
     220             : 
     221         144 :     cur = connection->cursor_stmts;
     222         288 :     while (cur)
     223             :     {
     224         144 :         if (strcmp(cur->name, cursor_name) == 0)
     225             :         {
     226         144 :             if (!prev)
     227         144 :                 connection->cursor_stmts = cur->next;
     228             :             else
     229           0 :                 prev->next = cur->next;
     230             : 
     231         144 :             ecpg_free(cur->name);
     232         144 :             ecpg_free(cur);
     233             : 
     234         144 :             break;
     235             :         }
     236           0 :         prev = cur;
     237           0 :         cur = cur->next;
     238             :     }
     239             : }
     240             : 
     241             : /*
     242             :  * Function: check the existence of the cursor in the connection
     243             :  * Return: true ---Found
     244             :  *         false --- Not found
     245             :  */
     246             : static bool
     247         144 : find_cursor(const char *cursor_name, const struct connection *connection)
     248             : {
     249         144 :     struct cursor_statement *cur = NULL;
     250             : 
     251         144 :     if (!connection || !cursor_name)
     252           0 :         return false;
     253             : 
     254         144 :     for (cur = connection->cursor_stmts; cur != NULL; cur = cur->next)
     255             :     {
     256         144 :         if (strcmp(cur->name, cursor_name) == 0)
     257         144 :             return true;
     258             :     }
     259             : 
     260           0 :     return false;
     261             : }

Generated by: LCOV version 1.13