OmniSciDB  2e3a973ef4
OmniSciEscapeParser.java
Go to the documentation of this file.
1 package com.omnisci.jdbc;
2 
3 import java.lang.reflect.InvocationTargetException;
4 import java.lang.reflect.Method;
5 import java.util.ArrayList;
6 import java.util.List;
7 import java.util.regex.Matcher;
8 import java.util.regex.Pattern;
9 
10 public class OmniSciEscapeParser {
11  private static final char[] QUOTE_OR_ALPHABETIC_MARKER = {'\"', '0'};
12  // private static final char[] QUOTE_OR_ALPHABETIC_MARKER_OR_PARENTHESIS = {'\"', '0',
13  // '('};
14  private static final char[] SINGLE_QUOTE = {'\''};
15 
16  private enum EscapeFunctions {
17  ESC_FUNCTION("\\s*fn\\s+([^ ]*?)\\s*\\(", "\\(\\s*(.*)\\s*\\)", null),
18  ESC_DATE("\\s*(d)\\s+", "('.*?')", "DATE "),
19  ESC_TIME("\\s*(t)\\s+", "('.*?')", "TIME "),
20  ESC_TIMESTAMP("\\s*(ts)\\s+", "('.*?')", "TIMESTAMP ");
21 
22  EscapeFunctions(String escapePattern, String argPattern, String replacementKeyword) {
23  this.escapePattern = Pattern.compile(escapePattern);
24  this.argPattern = Pattern.compile(argPattern);
25  this.replacementKeyword = replacementKeyword;
26  }
27 
28  private final Pattern escapePattern;
29  private final Pattern argPattern;
30  private final String replacementKeyword;
31 
32  private String call_escape_fn(String all_arguments, Method method) {
33  try {
34  StringBuilder sb = new StringBuilder();
35  List<CharSequence> parseArgs = new ArrayList<CharSequence>(3);
36  int bracket_cnt = 0;
37  StringBuilder args_sb = new StringBuilder();
38  for (int index = 0; index < all_arguments.length(); ++index) {
39  if (all_arguments.charAt(index) == ',' && bracket_cnt == 0) {
40  parseArgs.add(args_sb.toString());
41  args_sb.delete(0, args_sb.length());
42  continue;
43  }
44  if (all_arguments.charAt(index) == '(') {
45  bracket_cnt++;
46  } else if (all_arguments.charAt(index) == ')') {
47  bracket_cnt--;
48  }
49  args_sb.append(all_arguments.charAt(index));
50  }
51  // add the last argument.
52  parseArgs.add(args_sb.toString());
53  method.invoke(null, sb, parseArgs);
54  return sb.toString();
55  } catch (InvocationTargetException e) {
56  throw new RuntimeException("Invocation fn argument parse error" + e.getMessage());
57  } catch (IllegalAccessException ilE) {
58  throw new RuntimeException("Access fn argument error" + ilE.getMessage());
59  }
60  }
61 
62  private String makeMatch(String sql) {
63  Matcher matcher = escapePattern.matcher(sql);
64  if (matcher.find()) {
65  if (this == EscapeFunctions.ESC_DATE || this == EscapeFunctions.ESC_TIME
66  || this == EscapeFunctions.ESC_TIMESTAMP) {
67  matcher = argPattern.matcher(sql);
68  if (matcher.find()) {
69  String new_sql = this.replacementKeyword + matcher.group(1);
70  return new_sql;
71  }
72  } else if (this == EscapeFunctions.ESC_FUNCTION) {
73  String fn_name = matcher.group(1);
74  Method method = OmniSciEscapeFunctions.getFunction(fn_name);
75  matcher = argPattern.matcher(sql);
76  if (matcher.find()) {
77  if (method == null) {
78  String new_sql = fn_name + '(' + matcher.group(1) + ')';
79  return new_sql;
80  } else {
81  return call_escape_fn(matcher.group(1), method);
82  }
83  }
84  }
85  }
86  return null;
87  }
88  public static String simple(String arg) {
89  return arg;
90  }
91 
92  public static String function(String arg) {
93  return arg;
94  }
95  }
96 
97  private static class Pair {
98  public int start;
99  public int end;
100 
101  public Pair(int s) {
102  start = s;
103  }
104  }
105  private static String process_sql(String sql, Pair index) {
106  String value = sql.substring(index.start, index.end);
107 
108  boolean found_match = false;
109  for (EscapeFunctions xx : EscapeFunctions.values()) {
110  String newsql = xx.makeMatch(value);
111  if (newsql != null) {
112  sql = sql.substring(0, index.start) + newsql + " "
113  + sql.substring(index.end + 1, sql.length());
114  int x = newsql.length();
115  index.end = index.start + newsql.length();
116  found_match = true;
117  break;
118  }
119  }
120  if (!found_match) {
121  // it's an array. Prepend '{' here, because parser will remove the original brace.
122  sql = sql.substring(0, index.start) + "{" + sql.substring(index.start);
123  index.end += 1;
124  }
125  return sql;
126  }
127  public static String parse(String sql) {
128  Parser_return pR = parse(sql, 0);
129  if (pR.bracket_cnt != 0) {
130  throw new RuntimeException("Invalid java escape syntax - badly matched '}'");
131  }
132  return pR.sql_value;
133  }
134  static class Parser_return {
135  public String sql_value;
136  public int bracket_cnt;
137  public int end_idx;
138  }
139  private static Parser_return parse(String sql, int bracket_cnt) {
140  int index = 0;
141  boolean in_quote = false;
142 
143  do {
144  if (sql.charAt(index) == '\'') {
145  in_quote = !in_quote;
146  } else if (sql.charAt(index) == '{' && !in_quote) {
147  if (index + 1 == sql.length()) {
148  // What ever string we get should have had limit nnn
149  // added to the end and this test is veru unlikely
150  throw new RuntimeException("Invalid java escape syntax - badly matched '{'");
151  }
152  Parser_return pR = parse(sql.substring(index + 1), ++bracket_cnt);
153  bracket_cnt = pR.bracket_cnt;
154  String sql_snippet = pR.sql_value;
155  sql = sql.substring(0, index) + " " + sql_snippet;
156  index += pR.end_idx;
157  } else if (sql.charAt(index) == '}' && !in_quote) {
158  Pair ptr = new Pair(0);
159  ptr.end = index;
160  Parser_return pR = new Parser_return();
161  pR.sql_value = process_sql(sql, ptr);
162  pR.bracket_cnt = --bracket_cnt;
163  pR.end_idx = ptr.end + 1;
164  return pR;
165  }
166  index++;
167  } while (index < sql.length());
168  if (in_quote) {
169  throw new RuntimeException("Invalid java escape syntax - badly matched '''");
170  }
171 
172  Parser_return pR = new Parser_return();
173  pR.sql_value = sql;
174  pR.bracket_cnt = bracket_cnt;
175  pR.end_idx = sql.length();
176  return pR;
177  }
178 }
String call_escape_fn(String all_arguments, Method method)
EscapeFunctions(String escapePattern, String argPattern, String replacementKeyword)
static String process_sql(String sql, Pair index)
static Method getFunction(String functionName)
static Parser_return parse(String sql, int bracket_cnt)