home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / database / informix / 1632 < prev    next >
Encoding:
Internet Message Format  |  1992-07-29  |  6.9 KB

  1. Path: sparky!uunet!oracle!pyramid!infmx!news
  2. From: cortesi@informix.com (David Cortesi)
  3. Newsgroups: comp.databases.informix
  4. Subject: awk script to flatten isql output
  5. Message-ID: <1992Jul29.201431.2062@informix.com>
  6. Date: 29 Jul 92 20:14:31 GMT
  7. Sender: news@informix.com (Usenet News)
  8. Reply-To: cortesi@informix.com
  9. Organization: Informix Software, Inc.
  10. Lines: 182
  11.  
  12.  
  13. When you drive ISQL (or dbaccess?) from the command line, you can
  14. store its output in a redirected file.
  15.     isql stores - >customer.list  <<@
  16.     select * from customer;
  17.     @
  18. When the output width would exceed 79 chars, ISQL goes to vertical
  19. format, producing like:
  20.     customer_num  118
  21.     fname         Dick
  22.     lname         Baxter
  23.     company       Blue Ribbon Sports
  24.     address1      5427 College
  25.     etc...
  26. This was debated recently on comp.databases.informix.  The following
  27. awk program is one solution.  It takes ISQL output on standard
  28. input and reformats it so each data row is a single, flat line.
  29. It provides quite a bit of power to format the result, as well.
  30.  
  31. The key insight that makes this useful is, that awk's printf() will
  32. take its pattern from a variable, and a variable can be set from
  33. the command line.  So this script prepares a fairly stupid printf
  34. format based on the first input record contents -- but it lets you
  35. override it to do almost any sort of formatting you want.
  36.  
  37. ----------- cut here & save as "invsql" ---------------------------
  38. #
  39. #   invsql: an awk program to reformat an Informix-ISQL output listing,
  40. #   changing it from vertical format to horizontal report format.
  41. #
  42. #   Usage:
  43. #      [g]awk -f invsql [dpat="data-pattern"] [lpp=n] [hpat="head-pattern"]
  44. #
  45. #   <data-pattern> is a printf() pattern to format the column values
  46. #   <head-pattern> is a printf() pattern to format the column headings
  47. #   <n> is the number of lines of data per page
  48. #
  49. #   Headings are printed only when lpp is specified as greater than zero.
  50. #   See below for default heading and data patterns.
  51. #
  52. #   As written, supports only 30 columns of output. See the end of the
  53. #   program for how to expand this to more columns if required.
  54. #
  55. #   Requires an "awk" that matches the book by Aho et.al, that is,
  56. #   System V awk or Gnu awk -- not the obsolete awk shipped by Sun, NeXT, etc.
  57. #
  58. #   Author: David Cortesi (cortesi@informix.com)
  59. #
  60. # --------------------- User's Guide, so to speak --------------------------
  61. #
  62. #   Standard input to invsql is an ISQL vertical-format report like this:
  63. #
  64. # order_num      1007
  65. # order_date     03/25/1989
  66. # customer_num   117
  67. # backlog        n
  68. # po_num         278693
  69. # ship_date      04/23/1989
  70. # ship_weight    125.90
  71. #
  72. #   We change it to horizontal format with optional page headings:
  73. #
  74. # order_num order_date customer_num backlog po_num  ship_date ship_weight
  75. #      1007 03/25/1989          117       n 278693 04/28/1989      125.90
  76. #      1012 06/05/1989          117       n 278701 06/09/1989       70.80
  77. #
  78. #   The program prints each output line using a printf() like this:
  79. #       printf(pattern,col1,col2,...,coln)
  80. #   where each "col" is one value of that column from the input.
  81. #   The default pattern is: "%nns %nns...\n" where each "nn" is the
  82. #   default width of that column, determined by the following rule:
  83. #   The default width is the larger of the width of the heading text
  84. #   and the width of the data value in the first input record.
  85. #
  86. #   The default is often wrong, but you can specify exact widths and
  87. #   control the format in other ways, by specifying a printf()
  88. #   pattern string as the command-line argument dpat="pattern".
  89. #
  90. #   The program can print column headings at the top of each page of
  91. #   data.  The default is to NOT print headings -- you can paginate
  92. #   the output using the pr(1) command for example.  However if you
  93. #   specify lpp=n, n>0, the program will print column headings before
  94. #   each group of n data lines.
  95. #
  96. #   The default column heading display is:
  97. #       printf("\f%nns %nns...\n\n",col1,col2...coln)
  98. #   where each "col" is the heading text of that column from the first
  99. #   input record.  The pattern is essentially the default data pattern
  100. #    with formfeed before and newline after.  You can supply your own
  101. #   pattern using hpat="pattern" on the command line.
  102. #
  103. #   When writing printf patterns as part of c-shell commands you need
  104. #   only write the string in quotes, like this: dpat="%-5d\t%20f\n"
  105. #   (The c shell does not object to backslashes in such quotes.)
  106. #
  107. # --------------------- The Program  --------------------------
  108.  
  109. BEGIN { state = 0; colno = 0; recno = 0 }
  110.  
  111. # Leading blank lines: ignore them
  112.  
  113. state == 0 && $1 == "" { next }
  114.  
  115. # First data line of first group: note the length of the prefix
  116. # on each line, the name of the first column and some spaces.
  117. # The prefix has the same length on all lines, even when data is null.
  118.  
  119. state == 0 && $1 != "" {
  120.     match($0,/^[^ ]+ */)
  121.     pfxlen = RLENGTH+1
  122.     state = 1 # now into first data record
  123. }
  124.  
  125. # Any data line of any group: save the string value of the data line,
  126. # which is the whole line less the prefix.
  127.  
  128. $1 != ""  {
  129.     v[++colno] = substr($0,pfxlen)
  130. }
  131.  
  132. # Any data line of the first data record: save the column name
  133. # as well, and set the default length of this column.
  134.  
  135. state == 1 && $1 != "" {
  136.     h[colno] = $1
  137.     lh = length($1)
  138.     lv = length(v[colno])
  139.     dlen[colno] = (lh > lv)?lh:lv
  140. }
  141.  
  142. # End of first data record: build the print patterns.
  143.  
  144. state == 1 && $1 == "" {
  145.     pl = 0  # no pagination
  146.     if (lpp > 0) pl = lpp
  147.     pd = ""
  148.     for( j = 1; j <= colno; ++j ) pd = pd "%" dlen[j] "s "
  149.     sub(" $","\n",pd)
  150.     ph = "\f" pd "\n"
  151.     if (dpat != "") pd = fixup(dpat)
  152.     if (hpat != "") {
  153.         ph = fixup(hpat)
  154.         if (pl == 0) pl = 60
  155.     }
  156.     if (pl > 0) recno = pl-1 # force starting headings
  157.     state = 2 # no more setting up to do
  158. }
  159.  
  160. # End of any data record: print.
  161.  
  162. $1 == "" {
  163. # the printf statements have to list every possible column 1..colno
  164. # Columns that do not exist generate no output (because there's no
  165. # format for them in the pattern :) and awk does not object to you
  166. # referring to empty array elements.  To support more columns, add
  167. # more lines to the printf statements below, following the same pattern.
  168.  
  169.     if ( ++recno == pl ) { # only succeeds when pl > 0
  170.         printf ph \
  171.             ,h[1],h[2],h[3],h[4],h[5],h[6],h[7],h[8],h[9],h[10] \
  172.             ,h[11],h[12],h[13],h[14],h[15],h[16],h[17],h[18],h[19],h[20] \
  173.             ,h[21],h[22],h[23],h[24],h[25],h[26],h[27],h[28],h[29],h[30]
  174.         recno = 0
  175.     }
  176.     printf pd \
  177.             ,v[1],v[2],v[3],v[4],v[5],v[6],v[7],v[8],v[9],v[10] \
  178.             ,v[11],v[12],v[13],v[14],v[15],v[16],v[17],v[18],v[19],v[20] \
  179.             ,v[21],v[22],v[23],v[24],v[25],v[26],v[27],v[28],v[29],v[30]
  180. }
  181.  
  182. # As received from the command line, the print patterns still have
  183. # literally "\n" instead of a newline. Convert the 5 possible format
  184. # effectors to the real things.
  185.  
  186. function fixup(pat) {
  187.     gsub("\\\\f","\f",pat)
  188.     gsub("\\\\n","\n",pat)
  189.     gsub("\\\\r","\r",pat)
  190.     gsub("\\\\t","\t",pat)
  191.     gsub("\\\\v","\v",pat)
  192.     return pat
  193. }
  194.