//======================================================================================== // Parse() //======================================================================================== #region Parse private void Parse(int start, int delimIndex, StatementCollection statements) { if ((sql == null) || (sql.Length == 0) || (start >= sql.Length)) { return; } if (sql[start] == ' ') { start++; } // extract first keyword in query string word; int space = sql.IndexOf(' ', start); if (space < 0) { // found last word. now strip the final semicolon int end = sql.IndexOf(';', start); if (end < 0) { word = sql.Substring(start).Trim(); } else { word = sql.Substring(start, end - start).Trim(); } } else { word = sql.Substring(start, sql.IndexOf(' ', start) - start).ToUpper(); } // test extract keyword for important delimeters if (word.Equals("/")) { // ignore the / command Parse(start + 2, delimIndex, statements); } else if (word.Equals("EXIT")) { // ignore the EXIT command Parse(start + 5, delimIndex, statements); } else if (complexCmds.Contains(word) && IsPackageDef(start + word.Length + 1)) { // parse multi-depth DDL ParseComplex(ref start, statements); if (start < sql.Length) { Parse(start, delimIndex, statements); } } else { // TODO: use start-delimeter[] to determine end point rather than manually // looking for the next semi-colon (which might be embedded in a string) // simple query, seek end int end = IndexOfUnquoted(sql, start, ';'); string query; if (end < 0) { query = sql.Substring(start); } else { query = sql.Substring(start, end - start); } statements.Add(query.Trim()); if (end < 0) { return; } end++; if (end < sql.Length) { Parse(end, delimIndex + 1, statements); } } }
//======================================================================================== // ParseComplex() //======================================================================================== private void ParseComplex(ref int start, StatementCollection statements) { int i = start; int saveStart = start; int depth = 0; bool found = false; bool inString = false; char c = Char.MinValue; var token = new StringBuilder(); string word; while ((i < sql.Length) && !found) { c = sql[i]; if (inString) { if (c == '\'') { inString = false; } token.Append(c); } else if (c == ';') { if (depth < 0) { found = true; } else if (token.Length > 0) { word = token.ToString().ToUpper(); if (word.Equals("END")) { depth--; } if (depth < 0) { found = true; } } token.Length = 0; } else if (Char.IsWhiteSpace(c)) { word = token.ToString().ToUpper(); if (blockCmds.Contains(word)) { depth++; } else if (word.Equals("END")) { depth--; } token.Length = 0; } else { if (c == '\'') { inString = true; } token.Append(c); } i++; } var query = new StringBuilder(); if (found) { query.Append(sql.Substring(start, i - start)); if (query[query.Length - 1] != ';') { query.Append(';'); } start = i + 1; } else { query.Append(sql.Substring(start)); if (query[query.Length - 1] != ';') { query.Append(';'); } start = sql.Length; } if (isOptimized) { statements.Add(query.ToString()); } else { int a = (int)map[saveStart]; int b = (int)map[i - 1]; query.Length = 0; query.Append(text.Substring(a, b - a + 1)); if (query[query.Length - 1] != ';') { query.Append(';'); } statements.Add(query.ToString()); } }
//======================================================================================== // ExecuteExternalScript() //======================================================================================== private void ExecuteExternalScript(Query query) { isNested = true; try { string filnam = query.SQL.Substring(1); if (filnam[filnam.Length - 1] == ';') { filnam = filnam.Substring(0, filnam.Length - 1); } if (Path.GetDirectoryName(filnam) == String.Empty) { filnam = basePath + "\\" + filnam; } StreamReader reader = File.OpenText(filnam); string text = reader.ReadToEnd().Trim(); reader.Close(); if (text.Length == 0) { return; } string savePath = basePath; basePath = Path.GetDirectoryName(filnam); // create nested query collection processing... var queries = new QueryCollection(); var parser = new StatementParser(); StatementCollection statements = parser.Parse(text); // build collection of parsed queries Query q; System.Collections.Specialized.StringEnumerator e = statements.GetEnumerator(); while (e.MoveNext()) { q = new Query(e.Current); parser.ParseStatement(dbase, q, browser); queries.Add(q); } //[end create nested] // execute query collection try { foreach (Query q2 in queries) { ExecuteQuery(q2); } } catch (Exception exc) { Dialogs.ExceptionDialog.ShowException(exc); } finally { basePath = savePath; } } catch (Exception exc) { query.AddMessage(exc); } isNested = false; }