DbValue ExpressionToDbValue(string value, Types.ExpressionType etype) { switch (etype) { case Types.ExpressionType.FUNCTION: { int ilp = value.IndexOf('('); #if DEBUG if (-1 == ilp) { throw new Exception("DEBUG: ExpressionToDbValue: function expects ("); } if (!value.EndsWith(")")) { throw new Exception("DEBUG: ExpressionToDbValue: function expects )"); } #endif string fname = value.Substring(0, ilp); string sargs = value.Substring(ilp + 1, value.Length - ilp - 1 - 1); List <DbValue> args = new List <DbValue>(); StringPartReader argsparser = new StringPartReader(sargs); if (argsparser.PeekPart().Length != 0) { for (; ;) { if (0 == string.Compare("AS", argsparser.PeekPart(), true)) { argsparser.NextPart(); // Eat "AS". { StringBuilder sbas = new StringBuilder(); int asparens = 0; for (; ;) { string s = argsparser.PeekPart(); if (0 == s.Length || "," == s) { break; } else if ("(" == s) { asparens++; sbas.Append(argsparser.NextPart()); } else if (")" == s) { if (0 == asparens) { break; } asparens--; sbas.Append(argsparser.NextPart()); } else { sbas.Append(argsparser.NextPart()); } } if (0 == sbas.Length) { throw new Exception("Expected type after AS"); } args.Add(ExpressionToDbValue("'AS " + sbas.Replace("'", "''") + "'", Types.ExpressionType.AS)); } } else { string argvalue; Types.ExpressionType argetype; argvalue = Types.ReadNextBasicExpression(argsparser, out argetype); args.Add(ExpressionToDbValue(argvalue, argetype)); } { string s = argsparser.PeekPart(); if (s != ",") { if (0 == string.Compare("AS", s, true)) { continue; } if (s.Length != 0) { throw new Exception("Unexpected in function arguments: " + argsparser.RemainingString); } break; } } argsparser.NextPart(); // Eat the ','. } } return(new FuncEvalValue(this, fname, args)); } break; case Types.ExpressionType.NAME: { int FieldIndex = _IndexOfRowColType_ensure(value); return(new ColValue(this, ColumnTypes[FieldIndex])); } break; case Types.ExpressionType.NUMBER: case Types.ExpressionType.STRING: case Types.ExpressionType.AS: case Types.ExpressionType.NULL: { DbTypeID id; ByteSlice bs = Types.LiteralToValue(value, out id); return(new ImmediateValue(this, bs, DbType.Prepare(bs.Length, id))); } break; default: throw new Exception("Unexpected value: " + value); } }
DbValue ExpressionToDbValue(string value, Types.ExpressionType etype) { switch(etype) { case Types.ExpressionType.FUNCTION: { int ilp = value.IndexOf('('); #if DEBUG if (-1 == ilp) { throw new Exception("DEBUG: ExpressionToDbValue: function expects ("); } if (!value.EndsWith(")")) { throw new Exception("DEBUG: ExpressionToDbValue: function expects )"); } #endif string fname = value.Substring(0, ilp); string sargs = value.Substring(ilp + 1, value.Length - ilp - 1 - 1); List<DbValue> args = new List<DbValue>(); StringPartReader argsparser = new StringPartReader(sargs); if (argsparser.PeekPart().Length != 0) { for (; ; ) { if (0 == string.Compare("AS", argsparser.PeekPart(), true)) { argsparser.NextPart(); // Eat "AS". { StringBuilder sbas = new StringBuilder(); int asparens = 0; for (; ; ) { string s = argsparser.PeekPart(); if (0 == s.Length || "," == s) { break; } else if ("(" == s) { asparens++; sbas.Append(argsparser.NextPart()); } else if (")" == s) { if (0 == asparens) { break; } asparens--; sbas.Append(argsparser.NextPart()); } else { sbas.Append(argsparser.NextPart()); } } if (0 == sbas.Length) { throw new Exception("Expected type after AS"); } args.Add(ExpressionToDbValue("'AS " + sbas.Replace("'", "''") + "'", Types.ExpressionType.AS)); } } else { string argvalue; Types.ExpressionType argetype; argvalue = Types.ReadNextBasicExpression(argsparser, out argetype); args.Add(ExpressionToDbValue(argvalue, argetype)); } { string s = argsparser.PeekPart(); if (s != ",") { if (0 == string.Compare("AS", s, true)) { continue; } if (s.Length != 0) { throw new Exception("Unexpected in function arguments: " + argsparser.RemainingString); } break; } } argsparser.NextPart(); // Eat the ','. } } return new FuncEvalValue(this, fname, args); } break; case Types.ExpressionType.NAME: { int FieldIndex = _IndexOfRowColType_ensure(value); return new ColValue(this, ColumnTypes[FieldIndex]); } break; case Types.ExpressionType.NUMBER: case Types.ExpressionType.STRING: case Types.ExpressionType.AS: case Types.ExpressionType.NULL: { DbTypeID id; ByteSlice bs = Types.LiteralToValue(value, out id); return new ImmediateValue(this, bs, DbType.Prepare(bs.Length, id)); } break; default: throw new Exception("Unexpected value: " + value); } }
// 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; } }