LCOV - code coverage report
Current view: top level - src/ctlib/unittests - rpc_ct_param.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 195 234 83.3 %
Date: 2024-04-18 20:40:06 Functions: 3 3 100.0 %

          Line data    Source code
       1             : #include <config.h>
       2             : 
       3             : #include <stdio.h>
       4             : 
       5             : #if HAVE_STDLIB_H
       6             : #include <stdlib.h>
       7             : #endif /* HAVE_STRING_H */
       8             : 
       9             : #if HAVE_STRING_H
      10             : #include <string.h>
      11             : #endif /* HAVE_STRING_H */
      12             : 
      13             : #include <ctpublic.h>
      14             : #include "common.h"
      15             : 
      16             : #define MAX(X,Y)      (((X) > (Y)) ? (X) : (Y))
      17             : #define MIN(X,Y)      (((X) < (Y)) ? (X) : (Y))
      18             : 
      19             : static CS_INT ex_display_dlen(CS_DATAFMT * column);
      20             : static CS_RETCODE ex_display_header(CS_INT numcols, CS_DATAFMT columns[]);
      21             : 
      22             : typedef struct _ex_column_data
      23             : {
      24             :         CS_SMALLINT indicator;
      25             :         CS_CHAR *value;
      26             :         CS_INT valuelen;
      27             : }
      28             : EX_COLUMN_DATA;
      29             : 
      30             : /* Testing: array binding of result set */
      31             : int
      32           8 : main(void)
      33             : {
      34             :         CS_CONTEXT *ctx;
      35             :         CS_CONNECTION *conn;
      36             :         CS_COMMAND *cmd;
      37           8 :         int verbose = 0;
      38             : 
      39             :         CS_RETCODE ret;
      40             :         CS_INT res_type;
      41             :         CS_INT num_cols;
      42             : 
      43             :         CS_CHAR cmdbuf[4096];
      44             : 
      45             :         CS_DATAFMT datafmt;
      46             :         CS_DATAFMT srcfmt;
      47             :         CS_DATAFMT destfmt;
      48             :         CS_INT intvar;
      49             :         CS_SMALLINT smallintvar;
      50             :         CS_FLOAT floatvar;
      51             :         CS_MONEY moneyvar;
      52             :         CS_BINARY binaryvar;
      53           8 :         CS_BIT bitvar = 1;
      54             :         char moneystring[10];
      55             :         char rpc_name[15];
      56             :         CS_INT destlen;
      57             :         CS_INT i;
      58             :         CS_INT j;
      59           8 :         CS_INT row_count = 0;
      60             :         CS_INT rows_read;
      61             :         CS_INT disp_len;
      62             :         EX_COLUMN_DATA *coldata;
      63             :         CS_DATAFMT *outdatafmt;
      64             :         CS_SMALLINT msg_id;
      65             : 
      66             : 
      67             : 
      68           8 :         printf("%s: submit a stored procedure using ct_param \n", __FILE__);
      69             :         if (verbose) {
      70             :                 printf("Trying login\n");
      71             :         }
      72           8 :         check_call(try_ctlogin, (&ctx, &conn, &cmd, verbose));
      73           8 :         error_to_stdout = true;
      74             : 
      75             :         /* do not test error */
      76           8 :         ret = run_command(cmd, "IF OBJECT_ID('sample_rpc') IS NOT NULL DROP PROCEDURE sample_rpc");
      77             : 
      78           8 :         strcpy(cmdbuf, "create proc sample_rpc (@intparam int, \
      79             :         @sintparam smallint output, @floatparam float output, \
      80             :         @moneyparam money output,  \
      81             :         @dateparam datetime output, @charparam char(20) output, @empty varchar(20) output, \
      82             :         @binaryparam    binary(20) output, @bitparam bit) \
      83             :         as ");
      84             : 
      85           8 :         strcat(cmdbuf, "select @intparam, @sintparam, @floatparam, @moneyparam, \
      86             :         @dateparam, @charparam, @binaryparam \
      87             :         select @sintparam = @sintparam + @intparam \
      88             :         select @floatparam = @floatparam + @intparam \
      89             :         select @moneyparam = @moneyparam + convert(money, @intparam) \
      90             :         select @dateparam = getdate() \
      91             :         select @charparam = \'The char parameters\' \
      92             :         select @empty = \'\' \
      93             :         select @binaryparam = @binaryparam \
      94             :         print \'This is the message printed out by sample_rpc.\'");
      95             : 
      96           8 :         check_call(run_command, (cmd, cmdbuf));
      97             : 
      98             :         /*
      99             :          * Assign values to the variables used for parameter passing.
     100             :          */
     101             : 
     102           8 :         intvar = 2;
     103           8 :         smallintvar = 234;
     104           8 :         floatvar = 0.12;
     105           8 :         binaryvar = (CS_BINARY) 0xff;
     106           8 :         strcpy(rpc_name, "sample_rpc");
     107           8 :         strcpy(moneystring, "300.90");
     108             : 
     109             :         /*
     110             :          * Clear and setup the CS_DATAFMT structures used to convert datatypes.
     111             :          */
     112             : 
     113           8 :         memset(&srcfmt, 0, sizeof(CS_DATAFMT));
     114             :         srcfmt.datatype = CS_CHAR_TYPE;
     115           8 :         srcfmt.maxlength = strlen(moneystring);
     116           8 :         srcfmt.precision = 5;
     117           8 :         srcfmt.scale = 2;
     118             :         srcfmt.locale = NULL;
     119             : 
     120           8 :         memset(&destfmt, 0, sizeof(CS_DATAFMT));
     121           8 :         destfmt.datatype = CS_MONEY_TYPE;
     122           8 :         destfmt.maxlength = sizeof(CS_MONEY);
     123           8 :         destfmt.precision = 5;
     124           8 :         destfmt.scale = 2;
     125             :         destfmt.locale = NULL;
     126             : 
     127             :         /*
     128             :          * Convert the string representing the money value
     129             :          * to a CS_MONEY variable. Since this routine does not have the
     130             :          * context handle, we use the property functions to get it.
     131             :          */
     132           8 :         check_call(ct_cmd_props, (cmd, CS_GET, CS_PARENT_HANDLE, &conn, CS_UNUSED, NULL));
     133           8 :         check_call(ct_con_props, (conn, CS_GET, CS_PARENT_HANDLE, &ctx, CS_UNUSED, NULL));
     134           8 :         check_call(cs_convert, (ctx, &srcfmt, (CS_VOID *) moneystring, &destfmt, &moneyvar, &destlen));
     135             : 
     136             :         /*
     137             :          * Send the RPC command for our stored procedure.
     138             :          */
     139           8 :         check_call(ct_command, (cmd, CS_RPC_CMD, rpc_name, CS_NULLTERM, CS_NO_RECOMPILE));
     140             : 
     141             :         /*
     142             :          * Clear and setup the CS_DATAFMT structure, then pass
     143             :          * each of the parameters for the RPC.
     144             :          */
     145           8 :         memset(&datafmt, 0, sizeof(datafmt));
     146           8 :         strcpy(datafmt.name, "@intparam");
     147           8 :         datafmt.namelen = CS_NULLTERM;
     148           8 :         datafmt.datatype = CS_INT_TYPE;
     149           8 :         datafmt.maxlength = CS_UNUSED;
     150           8 :         datafmt.status = CS_INPUTVALUE;
     151             :         datafmt.locale = NULL;
     152             : 
     153           8 :         check_call(ct_param, (cmd, &datafmt, (CS_VOID *) & intvar, CS_SIZEOF(CS_INT), 0));
     154             : 
     155           8 :         strcpy(datafmt.name, "@sintparam");
     156           8 :         datafmt.namelen = CS_NULLTERM;
     157           8 :         datafmt.datatype = CS_SMALLINT_TYPE;
     158           8 :         datafmt.maxlength = 255;
     159           8 :         datafmt.status = CS_RETURN;
     160           8 :         datafmt.locale = NULL;
     161             : 
     162           8 :         check_call(ct_param, (cmd, &datafmt, (CS_VOID *) & smallintvar, CS_SIZEOF(CS_SMALLINT), 0));
     163             : 
     164           8 :         strcpy(datafmt.name, "@floatparam");
     165           8 :         datafmt.namelen = CS_NULLTERM;
     166           8 :         datafmt.datatype = CS_FLOAT_TYPE;
     167           8 :         datafmt.maxlength = 255;
     168           8 :         datafmt.status = CS_RETURN;
     169           8 :         datafmt.locale = NULL;
     170             : 
     171           8 :         check_call(ct_param, (cmd, &datafmt, (CS_VOID *) & floatvar, CS_SIZEOF(CS_FLOAT), 0));
     172             : 
     173           8 :         strcpy(datafmt.name, "@moneyparam");
     174           8 :         datafmt.namelen = CS_NULLTERM;
     175           8 :         datafmt.datatype = CS_MONEY_TYPE;
     176           8 :         datafmt.maxlength = 255;
     177           8 :         datafmt.status = CS_RETURN;
     178           8 :         datafmt.locale = NULL;
     179             : 
     180           8 :         check_call(ct_param, (cmd, &datafmt, (CS_VOID *) & moneyvar, CS_SIZEOF(CS_MONEY), 0));
     181             : 
     182           8 :         strcpy(datafmt.name, "@dateparam");
     183           8 :         datafmt.namelen = CS_NULLTERM;
     184           8 :         datafmt.datatype = CS_DATETIME4_TYPE;
     185           8 :         datafmt.maxlength = 255;
     186           8 :         datafmt.status = CS_RETURN;
     187           8 :         datafmt.locale = NULL;
     188             : 
     189             :         /*
     190             :          * The datetime variable is filled in by the RPC so pass NULL for
     191             :          * the data, 0 for data length, and -1 for the indicator arguments.
     192             :          */
     193           8 :         check_call(ct_param, (cmd, &datafmt, NULL, 0, -1));
     194           8 :         strcpy(datafmt.name, "@charparam");
     195           8 :         datafmt.namelen = CS_NULLTERM;
     196           8 :         datafmt.datatype = CS_CHAR_TYPE;
     197           8 :         datafmt.maxlength = 60;
     198           8 :         datafmt.status = CS_RETURN;
     199           8 :         datafmt.locale = NULL;
     200             : 
     201             :         /*
     202             :          * The character string variable is filled in by the RPC so pass NULL
     203             :          * for the data 0 for data length, and -1 for the indicator arguments.
     204             :          */
     205           8 :         check_call(ct_param, (cmd, &datafmt, NULL, 0, -1));
     206             : 
     207           8 :         strcpy(datafmt.name, "@empty");
     208           8 :         datafmt.namelen = CS_NULLTERM;
     209           8 :         datafmt.datatype = CS_VARCHAR_TYPE;
     210           8 :         datafmt.maxlength = 60;
     211           8 :         datafmt.status = CS_RETURN;
     212           8 :         datafmt.locale = NULL;
     213             : 
     214             :         /*
     215             :          * The character string variable is filled in by the RPC so pass NULL
     216             :          * for the data 0 for data length, and -1 for the indicator arguments.
     217             :          */
     218           8 :         check_call(ct_param, (cmd, &datafmt, NULL, 0, -1));
     219             : 
     220           8 :         strcpy(datafmt.name, "@binaryparam");
     221           8 :         datafmt.namelen = CS_NULLTERM;
     222           8 :         datafmt.datatype = CS_BINARY_TYPE;
     223           8 :         datafmt.maxlength = 255;
     224           8 :         datafmt.status = CS_RETURN;
     225           8 :         datafmt.locale = NULL;
     226             : 
     227           8 :         check_call(ct_param, (cmd, &datafmt, (CS_VOID *) & binaryvar, CS_SIZEOF(CS_BINARY), 0));
     228             : 
     229           8 :         strcpy(datafmt.name, "@bitparam");
     230           8 :         datafmt.namelen = CS_NULLTERM;
     231           8 :         datafmt.datatype = CS_BIT_TYPE;
     232           8 :         datafmt.maxlength = 1;
     233           8 :         datafmt.status = 0;
     234           8 :         datafmt.locale = NULL;
     235             : 
     236           8 :         check_call(ct_param, (cmd, &datafmt, (CS_VOID *) & bitvar, CS_SIZEOF(CS_BIT), 0));
     237             : 
     238             :         /*
     239             :          * Send the command to the server
     240             :          */
     241           8 :         check_call(ct_send, (cmd));
     242             : 
     243             :         /*
     244             :          * Process the results of the RPC.
     245             :          */
     246          64 :         while ((ret = ct_results(cmd, &res_type)) == CS_SUCCEED) {
     247          48 :                 switch ((int) res_type) {
     248          24 :                 case CS_ROW_RESULT:
     249             :                 case CS_PARAM_RESULT:
     250             :                 case CS_STATUS_RESULT:
     251             :                         /*
     252             :                          * Print the result header based on the result type.
     253             :                          */
     254          24 :                         switch ((int) res_type) {
     255           8 :                         case CS_ROW_RESULT:
     256           8 :                                 printf("\nROW RESULTS\n");
     257           8 :                                 break;
     258             : 
     259           8 :                         case CS_PARAM_RESULT:
     260           8 :                                 printf("\nPARAMETER RESULTS\n");
     261           8 :                                 break;
     262             : 
     263           8 :                         case CS_STATUS_RESULT:
     264           8 :                                 printf("\nSTATUS RESULTS\n");
     265           8 :                                 break;
     266             :                         }
     267          24 :                         fflush(stdout);
     268             : 
     269             :                         /*
     270             :                          * All three of these result types are fetchable.
     271             :                          * Since the result model for rpcs and rows have
     272             :                          * been unified in the New Client-Library, we
     273             :                          * will use the same routine to display them
     274             :                          */
     275             : 
     276             :                         /*
     277             :                          * Find out how many columns there are in this result set.
     278             :                          */
     279          24 :                         check_call(ct_res_info, (cmd, CS_NUMDATA, &num_cols, CS_UNUSED, NULL));
     280             : 
     281             :                         /*
     282             :                          * Make sure we have at least one column
     283             :                          */
     284          24 :                         if (num_cols <= 0) {
     285           0 :                                 fprintf(stderr, "ct_res_info(CS_NUMDATA) returned zero columns");
     286           0 :                                 return 1;
     287             :                         }
     288             : 
     289             :                         /*
     290             :                          * Our program variable, called 'coldata', is an array of
     291             :                          * EX_COLUMN_DATA structures. Each array element represents
     292             :                          * one column.  Each array element will re-used for each row.
     293             :                          * 
     294             :                          * First, allocate memory for the data element to process.
     295             :                          */
     296          24 :                         coldata = (EX_COLUMN_DATA *) malloc(num_cols * sizeof(EX_COLUMN_DATA));
     297          24 :                         if (coldata == NULL) {
     298           0 :                                 fprintf(stderr, "malloc coldata failed \n");
     299           0 :                                 return 1;
     300             :                         }
     301             : 
     302          24 :                         outdatafmt = (CS_DATAFMT *) malloc(num_cols * sizeof(CS_DATAFMT));
     303          24 :                         if (outdatafmt == NULL) {
     304           0 :                                 fprintf(stderr, "malloc outdatafmt failed \n");
     305           0 :                                 return 1;
     306             :                         }
     307             : 
     308         120 :                         for (i = 0; i < num_cols; i++) {
     309         120 :                                 check_call(ct_describe, (cmd, (i + 1), &outdatafmt[i]));
     310             : 
     311         120 :                                 outdatafmt[i].maxlength = ex_display_dlen(&outdatafmt[i]) + 1;
     312         120 :                                 outdatafmt[i].datatype = CS_CHAR_TYPE;
     313         120 :                                 outdatafmt[i].format = CS_FMT_NULLTERM;
     314             : 
     315         120 :                                 coldata[i].value = (CS_CHAR *) malloc(outdatafmt[i].maxlength);
     316         120 :                                 if (coldata[i].value == NULL) {
     317           0 :                                         fprintf(stderr, "malloc coldata.value failed \n");
     318           0 :                                         return 1;
     319             :                                 }
     320         120 :                                 coldata[i].value[0] = 0;
     321             : 
     322         120 :                                 check_call(ct_bind, (cmd, (i + 1), &outdatafmt[i], coldata[i].value, &coldata[i].valuelen,
     323             :                                               & coldata[i].indicator));
     324             :                         }
     325             : 
     326          24 :                         ex_display_header(num_cols, outdatafmt);
     327             : 
     328          72 :                         while (((ret = ct_fetch(cmd, CS_UNUSED, CS_UNUSED, CS_UNUSED,
     329          24 :                                                 &rows_read)) == CS_SUCCEED) || (ret == CS_ROW_FAIL)) {
     330             :                                 /*
     331             :                                  * Increment our row count by the number of rows just fetched.
     332             :                                  */
     333          24 :                                 row_count = row_count + rows_read;
     334             : 
     335             :                                 /*
     336             :                                  * Check if we hit a recoverable error.
     337             :                                  */
     338          24 :                                 if (ret == CS_ROW_FAIL) {
     339           0 :                                         printf("Error on row %d.\n", row_count);
     340           0 :                                         fflush(stdout);
     341             :                                 }
     342             : 
     343             :                                 /*
     344             :                                  * We have a row.  Loop through the columns displaying the
     345             :                                  * column values.
     346             :                                  */
     347         120 :                                 for (i = 0; i < num_cols; i++) {
     348             :                                         /*
     349             :                                          * Display the column value
     350             :                                          */
     351         120 :                                         printf("%s", coldata[i].value);
     352         120 :                                         fflush(stdout);
     353             : 
     354             :                                         /*
     355             :                                          * If not last column, Print out spaces between this
     356             :                                          * column and next one.
     357             :                                          */
     358         120 :                                         if (i != num_cols - 1) {
     359          96 :                                                 disp_len = ex_display_dlen(&outdatafmt[i]);
     360          96 :                                                 disp_len -= coldata[i].valuelen - 1;
     361        1822 :                                                 for (j = 0; j < disp_len; j++) {
     362        1726 :                                                         fputc(' ', stdout);
     363             :                                                 }
     364             :                                         }
     365             :                                 }
     366          24 :                                 printf("\n");
     367          24 :                                 fflush(stdout);
     368             :                         }
     369             : 
     370             :                         /*
     371             :                          * Free allocated space.
     372             :                          */
     373         120 :                         for (i = 0; i < num_cols; i++) {
     374         120 :                                 free(coldata[i].value);
     375             :                         }
     376          24 :                         free(coldata);
     377          24 :                         free(outdatafmt);
     378             : 
     379             :                         /*
     380             :                          * We're done processing rows.  Let's check the final return
     381             :                          * value of ct_fetch().
     382             :                          */
     383          24 :                         switch ((int) ret) {
     384          24 :                         case CS_END_DATA:
     385             :                                 /*
     386             :                                  * Everything went fine.
     387             :                                  */
     388          24 :                                 printf("All done processing rows.\n");
     389          24 :                                 fflush(stdout);
     390             :                                 break;
     391             : 
     392           0 :                         case CS_FAIL:
     393             :                                 /*
     394             :                                  * Something terrible happened.
     395             :                                  */
     396           0 :                                 fprintf(stderr, "ct_fetch returned CS_FAIL\n");
     397           0 :                                 return 1;
     398             :                                 break;
     399             : 
     400           0 :                         default:
     401             :                                 /*
     402             :                                  * We got an unexpected return value.
     403             :                                  */
     404           0 :                                 fprintf(stderr, "ct_fetch returned %d\n", ret);
     405           0 :                                 return 1;
     406             :                                 break;
     407             : 
     408             :                         }
     409          24 :                         break;
     410             : 
     411           0 :                 case CS_MSG_RESULT:
     412           0 :                         check_call(ct_res_info, (cmd, CS_MSGTYPE, (CS_VOID *) & msg_id, CS_UNUSED, NULL));
     413           0 :                         printf("ct_result returned CS_MSG_RESULT where msg id = %d.\n", msg_id);
     414           0 :                         fflush(stdout);
     415           0 :                         break;
     416             : 
     417             :                 case CS_CMD_SUCCEED:
     418             :                         /*
     419             :                          * This means no rows were returned.
     420             :                          */
     421             :                         break;
     422             : 
     423             :                 case CS_CMD_DONE:
     424             :                         /*
     425             :                          * Done with result set.
     426             :                          */
     427             :                         break;
     428             : 
     429           0 :                 case CS_CMD_FAIL:
     430             :                         /*
     431             :                          * The server encountered an error while
     432             :                          * processing our command.
     433             :                          */
     434           0 :                         fprintf(stderr, "ct_results returned CS_CMD_FAIL.");
     435           0 :                         break;
     436             : 
     437           0 :                 default:
     438             :                         /*
     439             :                          * We got something unexpected.
     440             :                          */
     441           0 :                         fprintf(stderr, "ct_results returned unexpected result type.");
     442           0 :                         return CS_FAIL;
     443             :                 }
     444             :         }
     445             : 
     446             :         /*
     447             :          * We're done processing results. Let's check the
     448             :          * return value of ct_results() to see if everything
     449             :          * went ok.
     450             :          */
     451           8 :         switch ((int) ret) {
     452             :         case CS_END_RESULTS:
     453             :                 /*
     454             :                  * Everything went fine.
     455             :                  */
     456             :                 break;
     457             : 
     458           0 :         case CS_FAIL:
     459             :                 /*
     460             :                  * Something failed happened.
     461             :                  */
     462           0 :                 fprintf(stderr, "ct_results failed.");
     463           0 :                 break;
     464             : 
     465           0 :         default:
     466             :                 /*
     467             :                  * We got an unexpected return value.
     468             :                  */
     469           0 :                 fprintf(stderr, "ct_results returned unexpected result type.");
     470           0 :                 break;
     471             :         }
     472             : 
     473           8 :         run_command(cmd, "DROP PROCEDURE sample_rpc");
     474             : 
     475             :         if (verbose) {
     476             :                 printf("Trying logout\n");
     477             :         }
     478           8 :         check_call(try_ctlogout, (ctx, conn, cmd, verbose));
     479             : 
     480           8 :         return 0;
     481             : }
     482             : 
     483             : static CS_INT
     484         456 : ex_display_dlen(CS_DATAFMT * column)
     485             : {
     486             : CS_INT len;
     487             : 
     488         456 :         switch ((int) column->datatype) {
     489         360 :         case CS_CHAR_TYPE:
     490             :         case CS_VARCHAR_TYPE:
     491             :         case CS_TEXT_TYPE:
     492             :         case CS_IMAGE_TYPE:
     493         360 :                 len = MIN(column->maxlength, 1024);
     494         360 :                 break;
     495             : 
     496          16 :         case CS_BINARY_TYPE:
     497             :         case CS_VARBINARY_TYPE:
     498          16 :                 len = MIN((2 * column->maxlength) + 2, 1024);
     499          16 :                 break;
     500             : 
     501             :         case CS_BIT_TYPE:
     502             :         case CS_TINYINT_TYPE:
     503             :                 len = 3;
     504             :                 break;
     505             : 
     506          16 :         case CS_SMALLINT_TYPE:
     507          16 :                 len = 6;
     508          16 :                 break;
     509             : 
     510          16 :         case CS_INT_TYPE:
     511          16 :                 len = 11;
     512          16 :                 break;
     513             : 
     514          16 :         case CS_REAL_TYPE:
     515             :         case CS_FLOAT_TYPE:
     516          16 :                 len = 20;
     517          16 :                 break;
     518             : 
     519          16 :         case CS_MONEY_TYPE:
     520             :         case CS_MONEY4_TYPE:
     521          16 :                 len = 24;
     522          16 :                 break;
     523             : 
     524          16 :         case CS_DATETIME_TYPE:
     525             :         case CS_DATETIME4_TYPE:
     526          16 :                 len = 30;
     527          16 :                 break;
     528             : 
     529           0 :         case CS_NUMERIC_TYPE:
     530             :         case CS_DECIMAL_TYPE:
     531           0 :                 len = (CS_MAX_PREC + 2);
     532           0 :                 break;
     533             : 
     534           0 :         default:
     535           0 :                 len = 12;
     536           0 :                 break;
     537             :         }
     538             : 
     539         456 :         return MAX((CS_INT) (strlen(column->name) + 1), len);
     540             : }
     541             : 
     542             : static CS_RETCODE
     543          24 : ex_display_header(CS_INT numcols, CS_DATAFMT columns[])
     544             : {
     545             : CS_INT i;
     546             : CS_INT l;
     547             : CS_INT j;
     548             : CS_INT disp_len;
     549             : 
     550          24 :         fputc('\n', stdout);
     551         144 :         for (i = 0; i < numcols; i++) {
     552         120 :                 disp_len = ex_display_dlen(&columns[i]);
     553         120 :                 printf("%s", columns[i].name);
     554         120 :                 fflush(stdout);
     555         120 :                 l = disp_len - strlen(columns[i].name);
     556        6728 :                 for (j = 0; j < l; j++) {
     557        6608 :                         fputc(' ', stdout);
     558        6608 :                         fflush(stdout);
     559             :                 }
     560             :         }
     561          24 :         fputc('\n', stdout);
     562          24 :         fflush(stdout);
     563         144 :         for (i = 0; i < numcols; i++) {
     564         120 :                 disp_len = ex_display_dlen(&columns[i]);
     565         120 :                 l = disp_len - 1;
     566        7168 :                 for (j = 0; j < l; j++) {
     567        7048 :                         fputc('-', stdout);
     568             :                 }
     569         120 :                 fputc(' ', stdout);
     570             :         }
     571          24 :         fputc('\n', stdout);
     572             : 
     573          24 :         return CS_SUCCEED;
     574             : }

Generated by: LCOV version 1.13