You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafodion.apache.org by db...@apache.org on 2019/02/12 17:43:39 UTC

[trafodion] branch master updated: [TRAFODION-3261] Change logsort tool to sort GET statement output also

This is an automated email from the ASF dual-hosted git repository.

dbirdsall pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafodion.git


The following commit(s) were added to refs/heads/master by this push:
     new 5aa3806  [TRAFODION-3261] Change logsort tool to sort GET statement output also
     new bae8752  Merge pull request #1793 from DaveBirdsall/Trafodion3261
5aa3806 is described below

commit 5aa3806f2fbbe90163e2844698a1c372f64e0f31
Author: Dave Birdsall <db...@apache.org>
AuthorDate: Mon Feb 11 20:08:33 2019 +0000

    [TRAFODION-3261] Change logsort tool to sort GET statement output also
---
 core/sql/regress/tools/logsort_src/line.c    |  35 ++++++++
 core/sql/regress/tools/logsort_src/line.h    |   2 +
 core/sql/regress/tools/logsort_src/logsort.c | 128 +++++++++++++++++++++++++++
 core/sql/regress/tools/logsort_src/tokstr.c  |  86 ++++++++++++++++--
 core/sql/regress/tools/logsort_src/tokstr.h  |   5 +-
 5 files changed, 248 insertions(+), 8 deletions(-)

diff --git a/core/sql/regress/tools/logsort_src/line.c b/core/sql/regress/tools/logsort_src/line.c
index 057db9a..6ceab36 100755
--- a/core/sql/regress/tools/logsort_src/line.c
+++ b/core/sql/regress/tools/logsort_src/line.c
@@ -561,3 +561,38 @@ else
 
 return rc;
 }
+
+/*
+
+    line_isgetheadingorfooting
+
+    This function determines if a line is a header or footer line
+    for GET statement output.
+
+    entry parameters:  line - the line to analyze
+
+    exit parameters:  returns TRUE if so, FALSE if not.
+
+                                                                          */
+
+int line_isgetheadingorfooting(char *line)
+{
+return (strncmp(line,"==========",10) == 0);
+}
+
+/*
+
+    line_issqloperationcomplete
+
+    This function determines if a line is "SQL operation complete."
+
+    entry parameters:  line - the line to analyze
+
+    exit parameters:  returns TRUE if so, FALSE if not.
+
+                                                                          */
+
+int line_issqloperationcomplete(char *line)
+{
+return (strcmp(line,"--- SQL operation complete.\n") == 0);
+}
diff --git a/core/sql/regress/tools/logsort_src/line.h b/core/sql/regress/tools/logsort_src/line.h
index 84bfbcc..a2a9fc2 100755
--- a/core/sql/regress/tools/logsort_src/line.h
+++ b/core/sql/regress/tools/logsort_src/line.h
@@ -40,3 +40,5 @@ int line_isnnrows(char *line);
 int line_isignore(char *line);
 int line_isstats(char *line);
 int line_isoptstats(char *line);
+int line_isgetheadingorfooting(char *line);
+int line_issqloperationcomplete(char *line);
diff --git a/core/sql/regress/tools/logsort_src/logsort.c b/core/sql/regress/tools/logsort_src/logsort.c
index 29af62d..69074a1 100755
--- a/core/sql/regress/tools/logsort_src/logsort.c
+++ b/core/sql/regress/tools/logsort_src/logsort.c
@@ -496,6 +496,21 @@ else
                   }
                token_stream_advance(t,1);  /*  advance past SELECT  */
                }
+            else if (token_stream_is_get(t))
+               {
+               /*  we are just after a GET with sortable output  */
+               headingcount = 0;
+               if (line_isblank(linebuf)) state = 10;
+               else if (line_is0rows(linebuf)) state = 0;
+               else if (line_iserror(linebuf)) state = 0;
+               else
+                  {
+                  printf("Unexpected line after a GET statement:\n");
+                  printf("%s",linebuf);
+                  state = 0;
+                  }
+               token_stream_advance(t,1);  /*  advance past GET  */
+               }
             else
                {
                /*  We are just after some other statement.  If the
@@ -691,6 +706,119 @@ else
             myFputs(linebuf,out,strip_stats_option,mightbestats(state));
             break;
             }
+         case 10:   /* after blank line after GET statement */
+            {
+            if (line_isheading(linebuf)) state = 11;
+            /* 0 rows selected after a blank line can happen with Trafodion sqlci */
+            else if (line_issqloperationcomplete(linebuf))
+               state = 0;  /* for Trafodion */
+            /* error message after a blank line can happen with Trafodion sqlci */
+            else if (line_iserror(linebuf))
+               state = 0;  /* for Trafodion */
+            /* warning messages occur after a blank line also in Trafodion sqlci */
+            else if (line_iswarning(linebuf))
+               state = 9;  /* there will be a blank line after the warning */
+            else
+               {
+               printf("Unexpected line after a GET statement:\n");
+               printf("%s",linebuf);
+               state = 0;
+               }
+            myFputs(linebuf,out,strip_stats_option,mightbestats(state));
+            break;
+            }
+         case 11:  /* after GET statement header text, e.g. "Tables in Schema TRAFODION.SCH" */
+            {
+            if (line_isgetheadingorfooting(linebuf))
+               {
+               headingcount++;
+               state = 12;
+               }
+            /* 0 rows selected after a blank line can happen with Trafodion sqlci */
+            else if (line_is0rows(linebuf))
+               state = 0;  /* for Trafodion */
+            /* error message after a blank line can happen with Trafodion sqlci */
+            else if (line_iserror(linebuf))
+               state = 0;  /* for Trafodion */
+            /* warning messages occur after a blank line also in Trafodion sqlci */
+            else if (line_iswarning(linebuf))
+               state = 9;  /* there will be a blank line after the warning */
+            else
+               {
+               printf("Unexpected line after a GET statement:\n");
+               printf("%s",linebuf);
+               state = 0;
+               }
+            myFputs(linebuf,out,strip_stats_option,mightbestats(state));
+            break;
+            }
+         case 12: /* after "===============" header line for GET statement */
+            {
+            if (line_isblank(linebuf))
+               {
+               state = 13;
+               line_within_row = 0;
+               }
+            else
+               {
+               printf("Unexpected line after a GET header:\n");
+               printf("%s",linebuf);
+               state = 0;
+               }
+            myFputs(linebuf,out,strip_stats_option,mightbestats(state));
+            break;
+            }
+         case 13:  /*  we are at a row of GET statement output */
+            {
+            if (line_isblank(linebuf))
+               {
+               /*  a blank line means no more GET output  */
+               
+               if (rw)  /* add any outstanding row to the list */
+                  {
+                  row_list_add(r,rw);
+                  rw = NULL;
+                  }
+
+               struct row *rw1;
+               char *returned_line;
+
+               while ((rw1 = row_list_remove_min(r)) != NULL)
+                  {
+                  while ((returned_line = row_remove(rw1)) != NULL)
+                     {
+                     myFputs(returned_line,out,strip_stats_option,mightbestats(state));
+                     }
+                  row_destroy(rw1);
+                  }
+
+               myFputs(linebuf,out,strip_stats_option,mightbestats(state));
+
+               /*  BUG - the test in the next statement should be:
+                   if (there are outstanding statements) ...
+                   But, need to write a new token_stream fn. to do this  */
+
+               if (token_stream_interesting(t)) state = 2;
+               else if (token_stream_is_get(t)) state = 2;
+               else state = 0;
+               }
+            else
+               {
+               if (line_within_row == headingcount)
+                  {
+                  row_list_add(r,rw);
+                  rw = NULL;
+                  line_within_row = 0;
+                  }
+               if (line_within_row == 0)
+                  {
+                  rw = row_create(headingcount);
+                  }
+               row_add(rw,linebuf);
+               line_within_row++;
+               }
+            break;
+            }
          default:
             {
             printf("Error:  got bad state %d.\n",state);
diff --git a/core/sql/regress/tools/logsort_src/tokstr.c b/core/sql/regress/tools/logsort_src/tokstr.c
index 8703ffa..f0603d5 100755
--- a/core/sql/regress/tools/logsort_src/tokstr.c
+++ b/core/sql/regress/tools/logsort_src/tokstr.c
@@ -56,7 +56,10 @@
 
 #define TOKEN_MXCI_DIRECTIVE 10   /* a SQL/MX MXCI directive */
 
-#define TOKEN_OTHER 11
+#define TOKEN_GET 11
+#define TOKEN_OBJECT_TYPE 12
+
+#define TOKEN_OTHER 13
 
 /*  parse states  */
 
@@ -79,6 +82,10 @@
 
 #define START_AFTER_NULL_STMT 13
 
+#define IN_GET 14
+#define IN_INTERESTING_GET 15
+#define FOUND_INTERESTING_GET 16
+
 /*
 
     token_stream_create
@@ -150,6 +157,7 @@ switch (state)
       else if (token_type == TOKEN_PREPARE) rc = IN_PREPARE;
       else if (token_type == TOKEN_EXECUTE) rc = IN_EXECUTE;
       else if (token_type == TOKEN_MXCI_DIRECTIVE) rc = START;  /* so we ignore directives */
+      else if (token_type == TOKEN_GET) rc = IN_GET;
       else if (token_type != TOKEN_SEMICOLON) rc = IN_OTHER;
       else rc = START_AFTER_NULL_STMT;
       break;
@@ -170,9 +178,11 @@ switch (state)
       else rc = IN_SELECT;
       break;
       }
+   case FOUND_INTERESTING_GET:
    case FOUND_SELECT_WITHOUT_ORDER_BY:
       {
       if (token_type == TOKEN_SELECT) rc = IN_SELECT;
+      else if (token_type == TOKEN_GET) rc = IN_GET;
       else if (token_type == TOKEN_PREPARE) rc = IN_PREPARE;
       else if (token_type == TOKEN_EXECUTE) rc = IN_EXECUTE;
       else if (token_type == TOKEN_MXCI_DIRECTIVE) rc = START; /* so we ignore MXCI directives */
@@ -281,6 +291,19 @@ switch (state)
       else if (token_type != TOKEN_SEMICOLON) rc = IN_OTHER;
       break;
       }
+   case IN_GET:
+      {
+      if (token_type == TOKEN_OBJECT_TYPE) rc = IN_INTERESTING_GET;
+      else if (token_type == TOKEN_SEMICOLON) rc = START;
+      /* else remain in IN_GET state */
+      break;
+      }
+   case IN_INTERESTING_GET:
+      {
+      if (token_type == TOKEN_SEMICOLON) rc = FOUND_INTERESTING_GET;
+      /* else remain in IN_INTERESTING_GET state */
+      break;
+      }
    default:
       {
       printf("Error:  unknown token type %d.\n",token_type);
@@ -322,7 +345,7 @@ else if (isalpha(*token))
    {
    int length;
    int i;
-   char buffer[10];
+   char buffer[20];
 
    *token_type_ptr = TOKEN_IDENTIFIER;
 
@@ -330,7 +353,7 @@ else if (isalpha(*token))
                         isdigit(*next) ||
                         (*next == '_');   next++) ;
    length = next - token;
-   if (length < 10)
+   if (length < 20)
       {
       for (i = 0; i < length; i++) buffer[i] = toupper(token[i]);
       buffer[i] = '\0';
@@ -346,6 +369,18 @@ else if (isalpha(*token))
       else if (strcmp(buffer,"PREPARE") == 0) *token_type_ptr = TOKEN_PREPARE;
       else if (strcmp(buffer,"FROM") == 0) *token_type_ptr = TOKEN_FROM;
       else if (strcmp(buffer,"EXECUTE") == 0) *token_type_ptr = TOKEN_EXECUTE;
+      else if (strcmp(buffer,"GET") == 0) *token_type_ptr = TOKEN_GET;
+      else if (strcmp(buffer,"TABLES") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"INDEXES") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"LIBRARIES") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"SCHEMAS") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"VIEWS") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"PRIVILEGES") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"FUNCTIONS") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"PROCEDURES") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"SEQUENCES") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"ROLES") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
+      else if (strcmp(buffer,"OBJECTS") == 0) *token_type_ptr = TOKEN_OBJECT_TYPE; /* for GET statement */
       }
    }
 else if (*token == ';')
@@ -497,13 +532,30 @@ while (*next != '\n')
       while ((*next == ' ') || (*next == '\t')) next++;
 
       if ((t->parsestate == FOUND_SELECT_WITHOUT_ORDER_BY)||
+          (t->parsestate == FOUND_INTERESTING_GET)||
           (t->parsestate == START))
          {
          /*  we have seen the end of a statement - record whether
              the statement was interesting                         */
-
-         t->stmt[t->last_stmt] =
-           (t->parsestate == FOUND_SELECT_WITHOUT_ORDER_BY);
+         
+         switch (t->parsestate)
+            {
+            case FOUND_SELECT_WITHOUT_ORDER_BY: 
+               {
+               t->stmt[t->last_stmt] = token_stream::SELECT_WITHOUT_ORDER_BY;
+               break;
+               }
+            case FOUND_INTERESTING_GET: 
+               {
+               t->stmt[t->last_stmt] = token_stream::INTERESTING_GET;
+               break;
+               }
+            default:
+               {
+               t->stmt[t->last_stmt] = token_stream::UNINTERESTING_STATEMENT;
+               break;
+               }
+            }
 
          t->last_stmt++;
          if (t->last_stmt == STMT_QUEUE_LENGTH) t->last_stmt = 0;
@@ -541,10 +593,30 @@ int token_stream_interesting(struct token_stream *t)
 
 {
 return (t->first_stmt != t->last_stmt) &&  /*  make sure at least one stmt  */
-       t->stmt[t->first_stmt];
+       (t->stmt[t->first_stmt] == token_stream::SELECT_WITHOUT_ORDER_BY);
 }
 
 
+/*
+
+    token_stream_is_get
+
+    This function determines whether the statement just found is
+    a GET statement with sortable output.
+
+    entry parameters:  t - the token stream
+
+    exit parameter:  returns TRUE if so, FALSE if not
+
+                                                                          */
+
+int token_stream_is_get(struct token_stream *t)
+
+{
+return (t->first_stmt != t->last_stmt) &&  /*  make sure at least one stmt  */
+       (t->stmt[t->first_stmt] == token_stream::INTERESTING_GET);
+}
+
 
 /*
 
diff --git a/core/sql/regress/tools/logsort_src/tokstr.h b/core/sql/regress/tools/logsort_src/tokstr.h
index 40b1ee1..741d40b 100755
--- a/core/sql/regress/tools/logsort_src/tokstr.h
+++ b/core/sql/regress/tools/logsort_src/tokstr.h
@@ -51,7 +51,9 @@ struct token_stream
                                 last_stmt                             */
    int last_stmt;           /*  next slot to add a statement in the queue  */
 
-   int stmt[STMT_QUEUE_LENGTH];  /*  a circular queue for statements  */
+   enum stmtState { SELECT_WITHOUT_ORDER_BY, INTERESTING_GET, UNINTERESTING_STATEMENT };
+
+   stmtState stmt[STMT_QUEUE_LENGTH];  /*  a circular queue for statements  */
    } ;
 
 /*  public function definitions  */
@@ -59,5 +61,6 @@ struct token_stream
 struct token_stream *token_stream_create(int ignore_order_by_option);
 int token_stream_add(struct token_stream *t,char *text);
 int token_stream_interesting(struct token_stream *t);
+int token_stream_is_get(struct token_stream *t);
 void token_stream_clear(struct token_stream *t);
 void token_stream_advance(struct token_stream *t,int advance_factor);