LCOV - code coverage report
Current view: top level - src/ctlib/unittests - rpc_ct_setparam.c (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 203 245 82.9 %
Date: 2025-04-22 17:15:43 Functions: 4 4 100.0 %

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

Generated by: LCOV version 1.13