diff --git a/CTP/sql/src/com/navercorp/cubridqa/cqt/common/SQLParser.java b/CTP/sql/src/com/navercorp/cubridqa/cqt/common/SQLParser.java index 042f9499..f4de6ee7 100644 --- a/CTP/sql/src/com/navercorp/cubridqa/cqt/common/SQLParser.java +++ b/CTP/sql/src/com/navercorp/cubridqa/cqt/common/SQLParser.java @@ -61,7 +61,8 @@ public static List parseSqlFile(String sqlFile, String codeset, boolean isN boolean isCall = false; boolean isNewStatement = true; boolean isQueryplan = false; - boolean isJoingraph = false; + boolean isJoingraph = false; + boolean isFullplan = false; LineScanner lineScanner = new LineScanner(); @@ -76,6 +77,8 @@ public static List parseSqlFile(String sqlFile, String codeset, boolean isN isQueryplan = true; } else if ("--@joingraph".equals(line.trim())) { isJoingraph = true; + } else if ("--@fullplan".equals(line.trim())) { + isFullplan = true; } else { String controlCmd = getControlCommand(line); if (controlCmd != null) { @@ -119,12 +122,14 @@ public static List parseSqlFile(String sqlFile, String codeset, boolean isN Sql sql = new Sql(connId, ret.toString(), paramList, isCall); sql.setQueryplan(isQueryplan); sql.setJoingraph(isJoingraph); + sql.setFullplan(isFullplan); list.add(sql); // initialize state variables isNewStatement = true; isQueryplan = false; isJoingraph = false; + isFullplan = false; ret.setLength(0); paramList = null; isCall = false; diff --git a/CTP/sql/src/com/navercorp/cubridqa/cqt/console/bean/Sql.java b/CTP/sql/src/com/navercorp/cubridqa/cqt/console/bean/Sql.java index 6e47e730..9545c735 100644 --- a/CTP/sql/src/com/navercorp/cubridqa/cqt/console/bean/Sql.java +++ b/CTP/sql/src/com/navercorp/cubridqa/cqt/console/bean/Sql.java @@ -44,6 +44,9 @@ public class Sql { // Only join graph xxx private boolean isJoingraph = false; + // Adds both join graph and query plan + private boolean isFullplan = false; + private int type; private String result = ""; @@ -171,4 +174,12 @@ public boolean isJoingraph() { public void setJoingraph(boolean isJoingraph) { this.isJoingraph = isJoingraph; } + + public boolean isFullplan() { + return isFullplan; + } + + public void setFullplan(boolean isFullplan) { + this.isFullplan = isFullplan; + } } diff --git a/CTP/sql/src/com/navercorp/cubridqa/cqt/console/dao/ConsoleDAO.java b/CTP/sql/src/com/navercorp/cubridqa/cqt/console/dao/ConsoleDAO.java index fce2bf99..daed83b9 100644 --- a/CTP/sql/src/com/navercorp/cubridqa/cqt/console/dao/ConsoleDAO.java +++ b/CTP/sql/src/com/navercorp/cubridqa/cqt/console/dao/ConsoleDAO.java @@ -613,7 +613,8 @@ private void executePrepareStatement(Connection conn, Sql sql, boolean isPrintQu } String script = sql.getScript().trim().toUpperCase(); boolean isOnlyJoinGraph = sql.isJoingraph(); - if (((isPrintQueryPlan && script.startsWith("SELECT")) || sql.isQueryplan()) || isOnlyJoinGraph) { + boolean isFullplan = sql.isFullplan(); + if (((isPrintQueryPlan && script.startsWith("SELECT")) || sql.isQueryplan()) || isOnlyJoinGraph || isFullplan) { Method method2 = ps.getClass().getMethod("setQueryInfo", new Class[] {boolean.class}); method2.invoke(ps, new Object[] {true}); @@ -627,13 +628,16 @@ private void executePrepareStatement(Connection conn, Sql sql, boolean isPrintQu isRs = ps.execute(); } getAllResult(ps, isRs, sql); - if (((isPrintQueryPlan && script.startsWith("SELECT")) || sql.isQueryplan()) || isOnlyJoinGraph) { + if (((isPrintQueryPlan && script.startsWith("SELECT")) || sql.isQueryplan()) || isOnlyJoinGraph || isFullplan) { Method method = ps.getClass().getMethod("getQueryplan", new Class[] {}); String queryPlan = (String) method.invoke(ps, new Object[] {}); queryPlan = queryPlan + System.getProperty("line.separator"); if (isOnlyJoinGraph) { queryPlan = StringUtil.replaceJoingraph(queryPlan); - } else { + } else if (isFullplan) { + queryPlan = StringUtil.replaceFullplan(queryPlan); + } + else { queryPlan = StringUtil.replaceQureyPlan(queryPlan); } sql.setResult(sql.getResult() + queryPlan); @@ -675,13 +679,17 @@ private void executeStatement(Connection conn, Sql sql, boolean isPrintQueryPlan getAllResult(st, isRs, sql); String script = sql.getScript().trim().toUpperCase(); boolean isOnlyJoinGraph = sql.isJoingraph(); - if (((isPrintQueryPlan && script.startsWith("SELECT")) || sql.isQueryplan()) || isOnlyJoinGraph) { + boolean isFullplan = sql.isFullplan(); + if (((isPrintQueryPlan && script.startsWith("SELECT")) || sql.isQueryplan()) || isOnlyJoinGraph || isFullplan) { Method method = st.getClass().getMethod("getQueryplan", stringType); String queryPlan = (String) method.invoke(st, new Object[] {sql.getScript()}); queryPlan = queryPlan + System.getProperty("line.separator"); if (isOnlyJoinGraph) { queryPlan = StringUtil.replaceJoingraph(queryPlan); - } else { + } else if (isFullplan) { + queryPlan = StringUtil.replaceFullplan(queryPlan); + } + else { queryPlan = StringUtil.replaceQureyPlan(queryPlan); } sql.setResult(sql.getResult() + queryPlan); diff --git a/CTP/sql/src/com/navercorp/cubridqa/cqt/console/util/StringUtil.java b/CTP/sql/src/com/navercorp/cubridqa/cqt/console/util/StringUtil.java index 3ba2c664..473d459d 100644 --- a/CTP/sql/src/com/navercorp/cubridqa/cqt/console/util/StringUtil.java +++ b/CTP/sql/src/com/navercorp/cubridqa/cqt/console/util/StringUtil.java @@ -269,6 +269,103 @@ public static String replaceJoingraph(String queryPlan) { return ret.toString(); } + /** + * replace the full query plan (query plan + join graph + query stmt) + * + * @param queryPlan + * @return + */ + public static String replaceFullplan(String queryPlan) { + if (queryPlan == null) { + return null; + } + + SystemModel systemModel = + (SystemModel) + XstreamHelper.fromXml( + EnvGetter.getenv("CTP_HOME") + + File.separator + + "sql/configuration/System.xml"); + StringBuilder ret = new StringBuilder(); + + String flag = "default"; + int stmtCount = 0; + String separator = System.getProperty("line.separator"); + BufferedReader reader = null; + try { + reader = new BufferedReader(new StringReader(queryPlan)); + + String message = reader.readLine(); + while (message != null) { + if (message.trim().equals("")) { + message = reader.readLine(); + continue; + } + + // Handle join graph section + if (message.startsWith("Join graph")) { + flag = "join"; + ret.append(message + separator); + message = reader.readLine(); + continue; + } + + // Handle query plan section + if (message.startsWith("Query plan:")) { + flag = "plan"; + ret.append(message + separator); + message = reader.readLine(); + continue; + } + + // Handle query statement section + if (message.startsWith("Query stmt:")) { + flag = "stmt"; + ret.append(message + separator); + stmtCount = 0; + message = reader.readLine(); + continue; + } + + // Append messages according to the current flag + if ("join".equals(flag)) { + // Modify join graph details if needed + message = message.replaceAll("sel [0-9]+\\.[0-9]+", "sel ?"); + ret.append(message + separator); + } else if ("plan".equals(flag) || "stmt".equals(flag)) { + if (systemModel.isQueryPlan()) { + ret.append(message + separator); + } else { + if ("plan".equals(flag)) { + message = message.replaceAll("[0-9]+", "?"); + ret.append(message + separator); + } else if ("stmt".equals(flag)) { + if (stmtCount == 0) { + message = message.replaceAll("[0-9]+", "?"); + ret.append(message + separator); + stmtCount++; + } else if (message.startsWith("/")) { + message = message.replaceAll("[0-9]+", "?"); + ret.append(message + separator); + } + } + } + } + + message = reader.readLine(); + } + } catch (Exception e) { + } finally { + if (reader != null) { + try { + reader.close(); + } catch (IOException e) { + } + } + } + return ret.toString(); + } + /** * translate byte array to Hex String . * diff --git a/CTP/sql_by_cci/execute.c b/CTP/sql_by_cci/execute.c index 33296271..a033f110 100644 --- a/CTP/sql_by_cci/execute.c +++ b/CTP/sql_by_cci/execute.c @@ -58,6 +58,7 @@ typedef struct SqlStateStruct struct { bool hasqp; bool onlyjg; /*join graph without queryplan */ + bool hasfullp; }; bool iscallwithoutvalue; @@ -988,7 +989,7 @@ readFile (char *fileName) int ascii1 = 0, ascii2 = 0; char line[MAX_SQL_LEN]; char sql_buf[MAXLINELENGH]; - bool hasqp = 0,hasjg = 0; + bool hasqp = 0, hasjg = 0, hasfullp = 0; //initial the total sql count. total_sql = 0; @@ -1010,11 +1011,16 @@ readFile (char *fileName) { hasqp = 1; } - else if (startswith(line, "--@joingraph")) + else if (startswith (line, "--@joingraph")) { hasjg = 1; hasqp = 1; } + else if (startswith (line, "--@fullplan")) + { + hasfullp = 1; + hasqp = 1; + } else if (startswithCI (line, "--+ server-message") || startswithCI (line, "--+server-message") || startswithCI (line, "--+ holdcas") || startswithCI (line, "--+holdcas")) @@ -1023,6 +1029,7 @@ readFile (char *fileName) strcpy (sqlstate[total_sql].sql, line); sqlstate[total_sql].hasqp = 0; sqlstate[total_sql].onlyjg = 0; + sqlstate[total_sql].hasfullp = 0; //if script like "? = call" sqlstate[total_sql].iscallwithoutvalue = 0; @@ -1055,6 +1062,7 @@ readFile (char *fileName) strcpy (sqlstate[total_sql].sql, sql_buf); sqlstate[total_sql].hasqp = hasqp; sqlstate[total_sql].onlyjg = hasjg; + sqlstate[total_sql].hasfullp = hasfullp; //if script like "? = call" sqlstate[total_sql].iscallwithoutvalue = startswith (line, "?"); @@ -1064,6 +1072,7 @@ readFile (char *fileName) sql_len = 0; hasqp = 0; hasjg = 0; + hasfullp = 0; } if (is_statement_end ()) @@ -1259,8 +1268,138 @@ formatjoingraph (FILE * fp, char *joingraph) free (p); } +void +formatfullplan (FILE * fp, char *queryPlan) +{ + char *str, *p; + int i, queryPlanLen, newline; + int isjoingraph = 0; + int isplan = 0; + int isstmt = 0; + + if (queryPlan == NULL) + { + return; + } + + queryPlanLen = strlen (queryPlan); + str = (char *) malloc (sizeof (char) * (queryPlanLen + 1)); + p = (char *) malloc (sizeof (char) * (queryPlanLen + 1)); + + if (str == NULL || p == NULL) + { + if (str != NULL) + { + free(str); + } + + if (p != NULL) + { + free(p); + } + + fprintf(stdout, "formatfullplan: malloc failure\n"); + return; + } + + memset (str, 0, sizeof (char) * (queryPlanLen + 1)); + memset (p, 0, sizeof (char) * (queryPlanLen + 1)); + + newline = 0; + for (i = 0; i < queryPlanLen; i++) + { + if (queryPlan[i] == '\n') + { + strncpy (str, queryPlan + newline, i - newline + 1); + str[i - newline + 1] = '\0'; + + strncpy (p, queryPlan + newline, i - newline + 1); + p[i - newline + 1] = '\0'; + newline = i + 1; + + trimline (p); + if (strlen (p) == 0) + { + continue; + } + + // Section Identification + if (startswith (p, "Join graph")) + { + isjoingraph = 1; + isplan = 0; + isstmt = 0; + fprintf (fp, "%s", str); + continue; + } + else if (startswith (p, "Query plan:")) + { + isplan = 1; + isjoingraph = 0; + isstmt = 0; + fprintf (fp, "%s", str); + continue; + } + else if (startswith (p, "Query stmt:")) + { + isstmt = 1; + isjoingraph = 0; + isplan = 0; + fprintf (fp, "%s", str); + continue; + } + else if (startswith (p, "Trace Statistics:")) + { + isjoingraph = 0; + isplan = 0; + isstmt = 0; + fprintf (fp, "%s", str); + continue; + } + + // Processing Based on Section + if (isjoingraph) + { + replace_substring (str, "sel [0-9]+\\.[0-9]+", "sel ?"); + fprintf (fp, "%s", str); + continue; + } + if (isplan) + { + trannum (str); + fprintf (fp, "%s", str); + continue; + } + if (isstmt == 1) + { + trannum (str); + fprintf (fp, "%s", str); + isstmt++; + continue; + } + else if (isstmt == 2) + { + trannum (str); + if (strindex (str, "skip ORDER BY") > -1 || strindex (str, "skip GROUP BY") > -1) + { + fprintf (fp, "%s", str); + isstmt = 0; + } + continue; + } + } + } + strncpy (str, queryPlan + newline, queryPlanLen - newline); + str[queryPlanLen - newline] = '\0'; + fprintf (fp, "%s", str); + + free (str); + free (p); +} + + int -dumptable (FILE * fp, int req, char con, bool hasqueryplan, bool onlyjoingraph) +dumptable (FILE * fp, int req, char con, bool hasqueryplan, bool onlyjoingraph, bool hasfullplan) { int res = 0; int ind = 0, index_count = 0, col_count = 0, setsize = -1, index_set = 0; @@ -1534,11 +1673,15 @@ dumptable (FILE * fp, int req, char con, bool hasqueryplan, bool onlyjoingraph) { formatjoingraph (fp, plan); } + else if (hasfullplan) + { + formatfullplan (fp, plan); + } else { formatplan (fp, plan); } - } + } } } @@ -1582,6 +1725,10 @@ dumptable (FILE * fp, int req, char con, bool hasqueryplan, bool onlyjoingraph) { formatjoingraph (fp, plan); } + else if (hasfullplan) + { + formatfullplan (fp, plan); + } else { formatplan (fp, plan); @@ -1789,6 +1936,7 @@ execute (FILE * fp, char conn, const SqlStateStruce *pSqlState) char *sql = pSqlState->sql; bool hasqueryplan = pSqlState->hasqp; bool onlyjoingraph = pSqlState->onlyjg; + bool hasfullplan = pSqlState->hasfullp; fprintf (fp, "===================================================\n"); @@ -1844,7 +1992,7 @@ execute (FILE * fp, char conn, const SqlStateStruce *pSqlState) if (cmd_type == CUBRID_STMT_SELECT || cmd_type == CUBRID_STMT_CALL || cmd_type == CUBRID_STMT_EVALUATE || cmd_type == CUBRID_STMT_GET_STATS) { - dumptable (fp, req, conn, hasqueryplan, onlyjoingraph); + dumptable (fp, req, conn, hasqueryplan, onlyjoingraph, hasfullplan); goto _END; } else if (cmd_type == CUBRID_STMT_UPDATE) @@ -1861,9 +2009,13 @@ execute (FILE * fp, char conn, const SqlStateStruce *pSqlState) if (res >= 0) { if (onlyjoingraph) - { + { formatjoingraph (fp, plan); } + else if (hasfullplan) + { + formatfullplan (fp, plan); + } else { formatplan (fp, plan); @@ -1893,7 +2045,7 @@ execute (FILE * fp, char conn, const SqlStateStruce *pSqlState) res_col_info = cci_get_result_info (req, &cmd_type, &col_count); if (cmd_type == CUBRID_STMT_SELECT || cmd_type == CUBRID_STMT_CALL) { - dumptable (fp, req, conn, hasqueryplan, onlyjoingraph); + dumptable (fp, req, conn, hasqueryplan, onlyjoingraph, hasfullplan); } else { @@ -1931,6 +2083,7 @@ executebind (FILE * fp, char conn, char *param, const SqlStateStruce *pSqlState) char *sql = pSqlState->sql; bool hasqueryplan = pSqlState->hasqp; bool onlyjoingraph = pSqlState->onlyjg; + bool hasfullplan = pSqlState->hasfullp; bool iscall = pSqlState->iscallwithoutvalue; fprintf (fp, "===================================================\n"); @@ -2055,7 +2208,7 @@ executebind (FILE * fp, char conn, char *param, const SqlStateStruce *pSqlState) res_col_info = cci_get_result_info (req, &cmd_type, &col_count); if (cmd_type == CUBRID_STMT_SELECT || cmd_type == CUBRID_STMT_CALL) { - dumptable (fp, req, conn, hasqueryplan, onlyjoingraph); + dumptable (fp, req, conn, hasqueryplan, onlyjoingraph, hasfullplan); } else { @@ -2075,7 +2228,7 @@ executebind (FILE * fp, char conn, char *param, const SqlStateStruce *pSqlState) res_col_info = cci_get_result_info (req, &cmd_type, &col_count); if (cmd_type == CUBRID_STMT_SELECT || cmd_type == CUBRID_STMT_CALL) { - dumptable (fp, req, conn, hasqueryplan, onlyjoingraph); + dumptable (fp, req, conn, hasqueryplan, onlyjoingraph, hasfullplan); } else {