public static string ReadNextBasicExpression(PartReader input, out ExpressionType etype) { string s; s = input.NextPart(); if (s.Length > 0) { if ('\'' == s[0]) { if (s[s.Length - 1] == '\'') { etype = ExpressionType.STRING; return(s); } else { throw new Exception("Unterminated string: " + s); } } else if (char.IsDigit(s[0])) { etype = ExpressionType.NUMBER; return(s); } else if ("+" == s || "-" == s) { bool positive = "+" == s; s = input.NextPart(); if (0 == s.Length) { throw new Exception("Expected number after sign"); } etype = ExpressionType.NUMBER; return(positive ? s : ("-" + s)); } else if (0 == string.Compare("NULL", s, true)) { etype = ExpressionType.NULL; return("NULL"); } else if (char.IsLetter(s[0])) { string name = s; s = input.PeekPart(); if ("(" == s) { input.NextPart(); // Eat the "(". StringBuilder call = new StringBuilder(); call.Append(name); call.Append('('); s = input.NextPart(); if (")" != s) { bool prevident = false; int nparens = 1; for (; ;) { if ("(" == s) { nparens++; } bool thisident = (s.Length > 0 && (char.IsLetterOrDigit(s[0]) || '_' == s[0])); if (prevident && thisident) { call.Append(' '); } prevident = thisident; call.Append(s); s = input.NextPart(); if (")" == s) { if (0 == --nparens) { break; } } if (0 == s.Length) { throw new Exception("Expected ) after function"); } } } call.Append(')'); etype = ExpressionType.FUNCTION; return(call.ToString()); } else if (0 == string.Compare("AS", name, true)) { { StringBuilder sbas = new StringBuilder(); int asparens = 0; for (; ;) { //string s = s = input.PeekPart(); if (0 == s.Length || "," == s) { break; } else if ("(" == s) { asparens++; sbas.Append(input.NextPart()); } else if (")" == s) { if (0 == asparens) { break; } asparens--; sbas.Append(input.NextPart()); } else { sbas.Append(input.NextPart()); } } if (0 == sbas.Length) { throw new Exception("Expected type after AS"); } etype = ExpressionType.AS; return("'AS " + sbas.Replace("'", "''") + "'"); } } else { etype = ExpressionType.NAME; return(name); } } else { #if DEBUG //System.Diagnostics.Debugger.Launch(); #endif throw new Exception("Misunderstood value: " + s); } } etype = ExpressionType.NONE; return(""); }
public static string ReadNextBasicExpression(PartReader input) { ExpressionType etype; return(ReadNextBasicExpression(input, out etype)); }
public static string ReadNextBasicExpression(PartReader input) { ExpressionType etype; return ReadNextBasicExpression(input, out etype); }
public static string ReadNextBasicExpression(PartReader input, out ExpressionType etype) { string s; s = input.NextPart(); if (s.Length > 0) { if ('\'' == s[0]) { if (s[s.Length - 1] == '\'') { etype = ExpressionType.STRING; return s; } else { throw new Exception("Unterminated string: " + s); } } else if (char.IsDigit(s[0])) { etype = ExpressionType.NUMBER; return s; } else if ("+" == s || "-" == s) { bool positive = "+" == s; s = input.NextPart(); if (0 == s.Length) { throw new Exception("Expected number after sign"); } etype = ExpressionType.NUMBER; return positive ? s : ("-" + s); } else if (0 == string.Compare("NULL", s, true)) { etype = ExpressionType.NULL; return "NULL"; } else if (char.IsLetter(s[0])) { string name = s; s = input.PeekPart(); if ("(" == s) { input.NextPart(); // Eat the "(". StringBuilder call = new StringBuilder(); call.Append(name); call.Append('('); s = input.NextPart(); if (")" != s) { bool prevident = false; int nparens = 1; for (; ; ) { if ("(" == s) { nparens++; } bool thisident = (s.Length > 0 && (char.IsLetterOrDigit(s[0]) || '_' == s[0])); if (prevident && thisident) { call.Append(' '); } prevident = thisident; call.Append(s); s = input.NextPart(); if (")" == s) { if (0 == --nparens) { break; } } if (0 == s.Length) { throw new Exception("Expected ) after function"); } } } call.Append(')'); etype = ExpressionType.FUNCTION; return call.ToString(); } else if (0 == string.Compare("AS", name, true)) { { StringBuilder sbas = new StringBuilder(); int asparens = 0; for (; ; ) { //string s = s = input.PeekPart(); if (0 == s.Length || "," == s) { break; } else if ("(" == s) { asparens++; sbas.Append(input.NextPart()); } else if (")" == s) { if (0 == asparens) { break; } asparens--; sbas.Append(input.NextPart()); } else { sbas.Append(input.NextPart()); } } if (0 == sbas.Length) { throw new Exception("Expected type after AS"); } etype = ExpressionType.AS; return "'AS " + sbas.Replace("'", "''") + "'"; } } else { etype = ExpressionType.NAME; return name; } } else { #if DEBUG //System.Diagnostics.Debugger.Launch(); #endif throw new Exception("Misunderstood value: " + s); } } etype = ExpressionType.NONE; return ""; }
// _ReadNextLiteral kept for SET static ByteSlice _ReadNextLiteral(PartReader input, DbColumn TypeHint) { string op; op = input.NextPart(); if (op.Length > 0) { if ('\'' == op[0]) { if (op[op.Length - 1] == '\'') { if ("DateTime" == TypeHint.Type.Name) { DateTime dt = DateTime.Parse(op.Substring(1, op.Length - 2)); Int64 x = dt.Ticks; List<byte> buf = new List<byte>(1 + 8); buf.Add(0); Entry.ToBytesAppend64(x, buf); return ByteSlice.Prepare(buf); } else { string str = op.Substring(1, op.Length - 2).Replace("''", "'"); byte[] strbytes = System.Text.Encoding.Unicode.GetBytes(str); //List<byte> buf = new List<byte>(1 + strbytes.Length); List<byte> buf = new List<byte>(TypeHint.Type.Size); buf.Add(0); buf.AddRange(strbytes); // Pad up the end of the char to be the whole column size. while (buf.Count < TypeHint.Type.Size) { buf.Add(0); } return ByteSlice.Prepare(buf); } } else { throw new Exception("Unterminated string: " + op); } } else if (char.IsDigit(op[0])) { return ByteSlice.Prepare(_NumberLiteralToType(op, TypeHint)); } else if ("+" == op || "-" == op) { bool positive = "+" == op; op = input.NextPart(); if (0 == op.Length) { throw new Exception("Expected number after sign"); } return ByteSlice.Prepare(_NumberLiteralToType(positive ? op : ("-" + op), TypeHint)); } else { throw new Exception("Misunderstood value: " + op); } } return ByteSlice.Prepare(new byte[] { 0 }); }
// _ReadNextLiteral kept for SET static ByteSlice _ReadNextLiteral(PartReader input, DbColumn TypeHint) { string op; op = input.NextPart(); if (op.Length > 0) { if ('\'' == op[0]) { if (op[op.Length - 1] == '\'') { if ("DateTime" == TypeHint.Type.Name) { DateTime dt = DateTime.Parse(op.Substring(1, op.Length - 2)); Int64 x = dt.Ticks; List <byte> buf = new List <byte>(1 + 8); buf.Add(0); Entry.ToBytesAppend64(x, buf); return(ByteSlice.Prepare(buf)); } else { string str = op.Substring(1, op.Length - 2).Replace("''", "'"); byte[] strbytes = System.Text.Encoding.Unicode.GetBytes(str); //List<byte> buf = new List<byte>(1 + strbytes.Length); List <byte> buf = new List <byte>(TypeHint.Type.Size); buf.Add(0); buf.AddRange(strbytes); // Pad up the end of the char to be the whole column size. while (buf.Count < TypeHint.Type.Size) { buf.Add(0); } return(ByteSlice.Prepare(buf)); } } else { throw new Exception("Unterminated string: " + op); } } else if (char.IsDigit(op[0])) { return(ByteSlice.Prepare(_NumberLiteralToType(op, TypeHint))); } else if ("+" == op || "-" == op) { bool positive = "+" == op; op = input.NextPart(); if (0 == op.Length) { throw new Exception("Expected number after sign"); } return(ByteSlice.Prepare(_NumberLiteralToType(positive ? op : ("-" + op), TypeHint))); } else { throw new Exception("Misunderstood value: " + op); } } return(ByteSlice.Prepare(new byte[] { 0 })); }
// If not found, the column and type names are empty, and the size is 0. // Type ID is NULL and RowOffset is 0 if a function (aggregate or scalar) or literal. DbColumn GetDbColumn(PartReader reader, out string sdw) { Types.ExpressionType bexprtype; string bexpr = Types.ReadNextBasicExpression(reader, out bexprtype); switch (bexprtype) { case Types.ExpressionType.NAME: { int ci = DbColumn.IndexOf(cols, bexpr); if (-1 != ci) { sdw = colswidths[ci]; return cols[ci]; } } break; case Types.ExpressionType.NULL: { DbColumn c; c.Type = DbType.PrepareNull(); c.RowOffset = 0; c.ColumnName = bexpr; DisplayWidthFromType(c.Type, out sdw); return c; } break; case Types.ExpressionType.NUMBER: case Types.ExpressionType.STRING: { DbColumn c; { DbTypeID typeid; int sz = Types.LiteralToValueInfo(bexpr, out typeid); c.Type = DbType.Prepare(sz, typeid); } c.RowOffset = 0; c.ColumnName = bexpr; DisplayWidthFromType(c.Type, out sdw); return c; } break; case Types.ExpressionType.FUNCTION: { // First see if there's a column named this! { int ci = DbColumn.IndexOf(cols, bexpr); if (-1 != ci) { sdw = colswidths[ci]; return cols[ci]; } } int ip = bexpr.IndexOf('('); if (-1 == ip) { throw new Exception("DEBUG: Types.ExpressionType.FUNCTION: (-1 == ip)"); } int extsize = -1; int tsizenarg = -1; // tsize is only the size of this argument (0-based). int tsizelargestfrom = -1; // tsize is the largest argument starting here (0-based). string funcname = bexpr.Substring(0, ip); if (0 == string.Compare("AVG", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("STD", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("STD_SAMP", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("VAR_POP", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("VAR_SAMP", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("COUNT", funcname, true)) { extsize = 1 + 8; // LONG } else if (0 == string.Compare("COUNTDISTINCT", funcname, true)) { extsize = 1 + 8; // LONG } else if (0 == string.Compare("PI", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("LEN", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("ATN2", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("SUBSTRING", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("RAND", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("CHARINDEX", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("INSTR", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("PATINDEX", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("SIGN", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("ROUND", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("TRUNC", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("RADIANS", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("NVL", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("NVL2", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("SQRT", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("POWER", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("DEGREES", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("RADIANS", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("SYSDATE", funcname, true)) { extsize = 1 + 8; // DateTime } else if (0 == string.Compare("MONTHS_BETWEEN", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("DATEDIFF", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("ADD_MONTHS", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("LOG10", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("SQUARE", funcname, true)) { extsize = 1 + 9; // DOUBLE } else if (0 == string.Compare("DATEPART_YEAR", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("DATEPART_MONTH", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("DATEPART_DAY", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("DATEPART_HOUR", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("DATEPART_MINUTE", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("DATEPART_SECOND", funcname, true)) { extsize = 1 + 4; // INT } else if (0 == string.Compare("IIF", funcname, true)) { tsizelargestfrom = 1; } else if (0 == string.Compare("ADD", funcname, true)) { tsizelargestfrom = 0; } else if (0 == string.Compare("SUB", funcname, true)) { tsizelargestfrom = 0; } else if (0 == string.Compare("MUL", funcname, true)) { tsizelargestfrom = 0; } else if (0 == string.Compare("DIV", funcname, true)) { tsizelargestfrom = 0; } else if (0 == string.Compare("MOD", funcname, true)) { tsizelargestfrom = 0; } else if (0 == string.Compare("NULLIF", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("LEFT", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("RIGHT", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("RPAD", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("LPAD", funcname, true)) { tsizenarg = 0; } else if (0 == string.Compare("FORMAT", funcname, true)) { tsizenarg = 1 + (80 * 2); // CHAR(80) } #if DEBUG else if (0 == string.Compare("CAST", funcname, true)) { #if DEBUG //System.Diagnostics.Debugger.Launch(); #endif } #endif int totdw = 0; string args = bexpr.Substring(ip + 1, bexpr.Length - ip - 1 - 1); StringPartReader spargs = new StringPartReader(args); int tsize = 1; int narg = -1; for (; ; ) { Types.ExpressionType subetype; string sube = Types.ReadNextBasicExpression(spargs, out subetype); if (Types.ExpressionType.NONE == subetype) { if (1 != tsize) { throw new Exception("Expected expression in parameter list"); } break; } else { narg++; if (Types.ExpressionType.AS == subetype) { if (0 == string.Compare("CAST", funcname, true)) { int astsize; int aswidth; { // Remove "'AS " and "'" string sastype = sube.Substring(4, sube.Length - 4 - 1).Replace("''", "'"); DbType astype = DbType.Prepare(DbType.NormalizeName(sastype)); if (DbTypeID.NULL == astype.ID) { throw new Exception("Unexpedted AS type: " + sastype); } astsize = astype.Size; int xdw = DisplayWidthFromType(astype); aswidth = xdw; } tsize = astsize; totdw = aswidth; break; // Note: ignores anything after this, but that's OK here for CAST. } else { throw new Exception("AS not expected here"); } } else { string sargwidth; DbColumn argcol = GetDbColumn(sube, out sargwidth); int argwidth = int.Parse(sargwidth); #if DEBUG if (0 == argcol.Type.Size) { throw new Exception("Argument to function cannot be " + argcol.ColumnName + " (Type.Size=0)"); } #endif if (-1 != tsizelargestfrom) { if (narg >= tsizelargestfrom) { if (tsize < argcol.Type.Size) { tsize = argcol.Type.Size; totdw = argwidth; } } } else { if (-1 == tsizenarg || narg == tsizenarg) { tsize += argcol.Type.Size - 1; totdw += argwidth; } } } } string s = spargs.PeekPart(); if (s != ",") { if (0 == string.Compare("AS", s, true)) { continue; } if (0 != s.Length) { spargs.NextPart(); // Eat it. throw new Exception("Unexpected: " + s); } break; } spargs.NextPart(); // Eat the ','. } if (-1 != extsize) { tsize = extsize; } DbColumn c; c.Type = DbType.Prepare("DbFunction", tsize, DbTypeID.NULL); //(string TypeName, int TypeSize, DbTypeID TypeID) c.RowOffset = 0; c.ColumnName = bexpr; sdw = totdw.ToString(); return c; } break; default: //throw new InvalidOperationException("Unhandled column: " + bexpr); break; } { DbColumn c; c.Type = DbType.Prepare("", 0, DbTypeID.NULL); c.RowOffset = 0; c.ColumnName = bexpr + "(undefined)"; sdw = "0"; return c; } }