/// <exception cref="System.SqlSyntaxErrorException" /> public override void Process(CobarHint hint, string hintName, string sql) { var value = ParsePrimary(hint, sql); if (value is long) { value = (long)value; } //var properties = new Dictionary<string, object>(1); //properties[hintName] = value; try { switch (hintName) { case "table": hint.Table = value as string; break; case "replica": hint.Replica = Convert.ToInt32(value); break; default: throw new NotSupportedException(string.Format("hintName:{0},value:{1}", hintName, value)); } //INFO---SimpleHintParser //ParameterMapping.Mapping(hint, properties); } catch (Exception t) { throw new SqlSyntaxErrorException(t); } }
private void SkipSpace(CobarHint hint, string sql) { var ci = hint.CurrentIndex; for (;;) { switch (sql[ci]) { case ' ': case '\t': case '\n': case '\r': { hint.IncreaseCurrentIndex(); ++ci; break; } default: { goto skip_break; } } } skip_break: ; }
/// <exception cref="System.SqlSyntaxErrorException" /> public override void Process(CobarHint hint, string hintName, string sql) { Pair <int, int> pair = null; if (CurrentChar(hint, sql) == '[') { for (;;) { NextChar(hint, sql); pair = ParseDataNode(hint, sql); hint.AddDataNode(pair.Key, pair.Value); switch (CurrentChar(hint, sql)) { case ',': { continue; } case ']': { NextChar(hint, sql); return; } default: { throw new SqlSyntaxErrorException("err for dataNodeId: " + sql); } } } } pair = ParseDataNode(hint, sql); hint.AddDataNode(pair.Key, pair.Value); }
/// <summary>first char is not separator</summary> private Pair <int, int> ParseDataNode(CobarHint hint, string sql) { var start = hint.CurrentIndex; var ci = start; for (; IsDigit(sql[ci]); ++ci) { } var nodeIndex = Convert.ToInt32(Runtime.Substring(sql, start, ci)); var replica = RouteResultsetNode.DefaultReplicaIndex; hint.CurrentIndex = ci; if (CurrentChar(hint, sql) == '.') { NextChar(hint, sql); start = hint.CurrentIndex; ci = start; for (; IsDigit(sql[ci]); ++ci) { } replica = Convert.ToInt32(Runtime.Substring(sql, start, ci)); hint.CurrentIndex = ci; } return(new Pair <int, int>(nodeIndex, replica)); }
/// <exception cref="System.SqlSyntaxErrorException" /> public override void Process(CobarHint hint, string hintName, string sql) { Pair<int, int> pair = null; if (CurrentChar(hint, sql) == '[') { for (;;) { NextChar(hint, sql); pair = ParseDataNode(hint, sql); hint.AddDataNode(pair.Key, pair.Value); switch (CurrentChar(hint, sql)) { case ',': { continue; } case ']': { NextChar(hint, sql); return; } default: { throw new SqlSyntaxErrorException("err for dataNodeId: " + sql); } } } } pair = ParseDataNode(hint, sql); hint.AddDataNode(pair.Key, pair.Value); }
/// <exception cref="System.SqlSyntaxErrorException" /> public override void Process(CobarHint hint, string hintName, string sql) { string[] columns; if (NextChar(hint, sql) == '[') { hint.IncreaseCurrentIndex(); columns = Convert2String(ParseArray(hint, sql, -1)); } else { columns = new string[1]; columns[0] = (string)ParsePrimary(hint, sql); } object[][] values; switch (NextChar(hint, sql)) { case '[': { if (columns.Length == 1) { hint.IncreaseCurrentIndex(); var vs = ParseArray(hint, sql, -1); values = new object[vs.Length][]; for (var i = 0; i < vs.Length; ++i) { values[i] = new object[1] { vs[i] }; //values[i][0] = vs[i]; } } else { values = ParseArrayArray(hint, sql, columns.Length); } break; } default: { if (columns.Length == 1) { values = new object[1][] { new object[1] }; values[0][0] = ParsePrimary(hint, sql); } else { throw new SqlSyntaxErrorException("err for partitionOperand: " + sql); } break; } } hint.PartitionOperand = new Pair <string[], object[][]>(columns, values); if (CurrentChar(hint, sql) == ')') { hint.IncreaseCurrentIndex(); } }
/// <exception cref="System.SqlSyntaxErrorException" /> public override void Process(CobarHint hint, string hintName, string sql) { string[] columns; if (NextChar(hint, sql) == '[') { hint.IncreaseCurrentIndex(); columns = Convert2String(ParseArray(hint, sql, -1)); } else { columns = new string[1]; columns[0] = (string)ParsePrimary(hint, sql); } object[][] values; switch (NextChar(hint, sql)) { case '[': { if (columns.Length == 1) { hint.IncreaseCurrentIndex(); var vs = ParseArray(hint, sql, -1); values = new object[vs.Length][]; for (var i = 0; i < vs.Length; ++i) { values[i] = new object[1] {vs[i]}; //values[i][0] = vs[i]; } } else { values = ParseArrayArray(hint, sql, columns.Length); } break; } default: { if (columns.Length == 1) { values = new object[1][] {new object[1]}; values[0][0] = ParsePrimary(hint, sql); } else { throw new SqlSyntaxErrorException("err for partitionOperand: " + sql); } break; } } hint.PartitionOperand = new Pair<string[], object[][]>(columns, values); if (CurrentChar(hint, sql) == ')') { hint.IncreaseCurrentIndex(); } }
// index start from 1 // /*!cobar: $dataNodeId=0.0, $_table='offer'*/ // /*!cobar: $dataNodeId=[0,1,5.2], $_table='offer'*/ // /*!cobar: $_partitionOperand=('member_id'='m1'), $_table='offer'*/ // /*!cobar: $_partitionOperand=('member_id'=['m1','m2']), $_table='offer', // $_replica=2*/ // /*!cobar: $_partitionOperand=(['offer_id','group_id']=[123,'3c']), // $_table='offer'*/ // /*!cobar: // $_partitionOperand=(['offer_id','group_id']=[[123,'3c'],[234,'food']]), // $_table='offer'*/ /// <param name="offset"> /// index of first char of /// <see cref="CobarHintPrefix" /> /// </param> /// <exception cref="System.SqlSyntaxErrorException" /> public static CobarHint ParserCobarHint(string sql, int offset) { var hint = new CobarHint { CurrentIndex = offset + CobarHintPrefix.Length }; hint.Parse(sql); return(hint); }
/// <summary> /// current char is char after '[', after call, current char is char after /// ']' /// </summary> /// <param name="len">less than 0 for array length unknown</param> /// <exception cref="System.SqlSyntaxErrorException" /> private object[] ParseArray(CobarHint hint, string sql, int len) { object[] rst = null; IList <object> list = null; if (len >= 0) { rst = new object[len]; } else { list = new List <object>(); } for (var i = 0;; ++i) { var obj = ParsePrimary(hint, sql); if (len >= 0) { rst[i] = obj; } else { list.Add(obj); } switch (CurrentChar(hint, sql)) { case ']': { hint.IncreaseCurrentIndex(); if (len >= 0) { return(rst); } return(list.ToArray()); } case ',': { hint.IncreaseCurrentIndex(); break; } default: { throw new SqlSyntaxErrorException("err for partitionOperand array: " + sql); } } } }
/// <summary>first char is not separator</summary> private Pair<int, int> ParseDataNode(CobarHint hint, string sql) { var start = hint.CurrentIndex; var ci = start; for (; IsDigit(sql[ci]); ++ci) { } var nodeIndex = Convert.ToInt32(Runtime.Substring(sql, start, ci)); var replica = RouteResultsetNode.DefaultReplicaIndex; hint.CurrentIndex = ci; if (CurrentChar(hint, sql) == '.') { NextChar(hint, sql); start = hint.CurrentIndex; ci = start; for (; IsDigit(sql[ci]); ++ci) { } replica = Convert.ToInt32(Runtime.Substring(sql, start, ci)); hint.CurrentIndex = ci; } return new Pair<int, int>(nodeIndex, replica); }
/// <summary>current char is '[[', after call, current char is char after ']]'</summary> /// <exception cref="System.SqlSyntaxErrorException" /> private object[][] ParseArrayArray(CobarHint hint, string sql, int columnNum) { if (NextChar(hint, sql) == '[') { IList <object[]> list = new List <object[]>(); for (;;) { NextChar(hint, sql); list.Add(ParseArray(hint, sql, columnNum)); var c = CurrentChar(hint, sql); switch (c) { case ']': { hint.IncreaseCurrentIndex(); return(list.ToArray()); } case ',': { NextChar(hint, sql); break; } default: { throw new SqlSyntaxErrorException("err for partitionOperand array[]: " + sql); } } } } var rst = new[] { new object[columnNum] }; rst[0] = ParseArray(hint, sql, columnNum); return(rst); }
/// <exception cref="System.SqlSyntaxErrorException" /> protected internal virtual object ParsePrimary(CobarHint hint, string sql) { var c = CurrentChar(hint, sql); var ci = hint.CurrentIndex; switch (c) { case '\'': { var sb = new StringBuilder(); for (++ci;; ++ci) { c = sql[ci]; switch (c) { case '\'': { hint.CurrentIndex = ci + 1; return(sb.ToString()); } case '\\': { c = sql[++ci]; goto default; } default: { sb.Append(c); break; } } } #pragma warning disable CS0162 // 检测到无法访问的代码 goto case 'n'; #pragma warning restore CS0162 // 检测到无法访问的代码 } case 'n': case 'N': { hint.CurrentIndex = ci + "null".Length; return(null); } default: { if (IsDigit(c)) { var start = ci++; for (; IsDigit(sql[ci]); ++ci) { } hint.CurrentIndex = ci; return(long.Parse(Runtime.Substring(sql, start, ci))); } throw new SqlSyntaxErrorException("unknown primary in hint: " + sql); } } }
protected internal virtual char CurrentChar(CobarHint hint, string sql) { SkipSpace(hint, sql); return sql[hint.CurrentIndex]; }
protected internal virtual char CurrentChar(CobarHint hint, string sql) { SkipSpace(hint, sql); return(sql[hint.CurrentIndex]); }
/// <summary> /// hint's /// <see cref="CobarHint.GetCurrentIndex()" /> /// will be changed to index of /// next char after process /// </summary> /// <exception cref="System.SqlSyntaxErrorException" /> public abstract void Process(CobarHint hint, string hintName, string sql);
/// <summary>current char is not separator</summary> protected internal virtual char NextChar(CobarHint hint, string sql) { SkipSpace(hint, sql); SkipSpace(hint.IncreaseCurrentIndex(), sql); return(sql[hint.CurrentIndex]); }
/// <exception cref="System.SqlSyntaxErrorException" /> protected internal virtual object ParsePrimary(CobarHint hint, string sql) { var c = CurrentChar(hint, sql); var ci = hint.CurrentIndex; switch (c) { case '\'': { var sb = new StringBuilder(); for (++ci;; ++ci) { c = sql[ci]; switch (c) { case '\'': { hint.CurrentIndex = ci + 1; return sb.ToString(); } case '\\': { c = sql[++ci]; goto default; } default: { sb.Append(c); break; } } } #pragma warning disable CS0162 // 检测到无法访问的代码 goto case 'n'; #pragma warning restore CS0162 // 检测到无法访问的代码 } case 'n': case 'N': { hint.CurrentIndex = ci + "null".Length; return null; } default: { if (IsDigit(c)) { var start = ci++; for (; IsDigit(sql[ci]); ++ci) { } hint.CurrentIndex = ci; return long.Parse(Runtime.Substring(sql, start, ci)); } throw new SqlSyntaxErrorException("unknown primary in hint: " + sql); } } }
/// <summary>current char is '[[', after call, current char is char after ']]'</summary> /// <exception cref="System.SqlSyntaxErrorException" /> private object[][] ParseArrayArray(CobarHint hint, string sql, int columnNum) { if (NextChar(hint, sql) == '[') { IList<object[]> list = new List<object[]>(); for (;;) { NextChar(hint, sql); list.Add(ParseArray(hint, sql, columnNum)); var c = CurrentChar(hint, sql); switch (c) { case ']': { hint.IncreaseCurrentIndex(); return list.ToArray(); } case ',': { NextChar(hint, sql); break; } default: { throw new SqlSyntaxErrorException("err for partitionOperand array[]: " + sql); } } } } var rst = new[] {new object[columnNum]}; rst[0] = ParseArray(hint, sql, columnNum); return rst; }
/// <summary>current char is not separator</summary> protected internal virtual char NextChar(CobarHint hint, string sql) { SkipSpace(hint, sql); SkipSpace(hint.IncreaseCurrentIndex(), sql); return sql[hint.CurrentIndex]; }
// index start from 1 // /*!cobar: $dataNodeId=0.0, $_table='offer'*/ // /*!cobar: $dataNodeId=[0,1,5.2], $_table='offer'*/ // /*!cobar: $_partitionOperand=('member_id'='m1'), $_table='offer'*/ // /*!cobar: $_partitionOperand=('member_id'=['m1','m2']), $_table='offer', // $_replica=2*/ // /*!cobar: $_partitionOperand=(['offer_id','group_id']=[123,'3c']), // $_table='offer'*/ // /*!cobar: // $_partitionOperand=(['offer_id','group_id']=[[123,'3c'],[234,'food']]), // $_table='offer'*/ /// <param name="offset"> /// index of first char of /// <see cref="CobarHintPrefix" /> /// </param> /// <exception cref="System.SqlSyntaxErrorException" /> public static CobarHint ParserCobarHint(string sql, int offset) { var hint = new CobarHint { CurrentIndex = offset + CobarHintPrefix.Length }; hint.Parse(sql); return hint; }
/// <summary> /// current char is char after '[', after call, current char is char after /// ']' /// </summary> /// <param name="len">less than 0 for array length unknown</param> /// <exception cref="System.SqlSyntaxErrorException" /> private object[] ParseArray(CobarHint hint, string sql, int len) { object[] rst = null; IList<object> list = null; if (len >= 0) { rst = new object[len]; } else { list = new List<object>(); } for (var i = 0;; ++i) { var obj = ParsePrimary(hint, sql); if (len >= 0) { rst[i] = obj; } else { list.Add(obj); } switch (CurrentChar(hint, sql)) { case ']': { hint.IncreaseCurrentIndex(); if (len >= 0) return rst; return list.ToArray(); } case ',': { hint.IncreaseCurrentIndex(); break; } default: { throw new SqlSyntaxErrorException("err for partitionOperand array: " + sql); } } } }