public Expression GetNode(ExpressionParser parser)
        {
            Lexem      lex = parser.Collection.CurrentLexem();
            Expression res = null;

            if (lex.LexemType == LexType.Command)
            {
                string lowerLexem = lex.LexemText.ToLower();
                if (ParserUtils.ParseCommandPhrase(parser.Collection, "create view", false, false))
                {
                    res = new CreateView();
                }
                if (ParserUtils.ParseCommandPhrase(parser.Collection, "create table", false, false))
                {
                    res = new CreateTable();
                }
                if (res == null && ParserUtils.ParseCommandPhrase(parser.Collection, "alter table", false, false))
                {
                    res = new AlterTable();
                }
                if (res == null && ParserUtils.ParseCommandPhrase(parser.Collection, "drop table", false, false))
                {
                    res = new DropTable();
                }
                if (res == null && ParserUtils.ParseCommandPhrase(parser.Collection, "drop index", false, false))
                {
                    res = new DropIndex();
                }
                if (res == null && (ParserUtils.ParseCommandPhrase(parser.Collection, "create unique index", false, false) ||
                                    ParserUtils.ParseCommandPhrase(parser.Collection, "create index", false, false)))
                {
                    res = new CreateIndex();
                }
                if (res == null)
                {
                    if (parser.Collection.GetNext() != null && parser.Collection.GetNext().IsSkobraOpen())
                    {
                        switch (lowerLexem)
                        {
                        case "count":
                            res = new CountExpr();
                            break;

                        case "sum":
                            res = new SumExpr();
                            break;

                        case "min":
                            res = new MinExpr();
                            break;

                        case "max":
                            res = new MaxExpr();
                            break;

                        case "avg":
                            res = new AvgExpr();
                            break;

                        case "lastinsertrowid":
                            res = new LastInsertRowidExpr();
                            break;

                        case "exists":
                            res = new ExistsExpr();
                            break;

                        case "any":
                            res = new AnyExpr();
                            break;
                        }
                    }

                    switch (lowerLexem)
                    {
                    case "between":    //не функция
                        res = new Between();
                        break;

                    case "select":
                        res = new SelectExpresion();
                        break;

                    case "update":
                        res = new UpdateStatement();
                        break;

                    case "insert":
                        res = new InsertStatement();
                        break;

                    case "delete":
                        res = new DeleteStatement();
                        break;
                    }
                }
            }
            if (res != null)
            {
                return(res);
            }
            return(res);
        }
        public static ExactType?Parse(LexemCollection collection)
        {
            ExactType res;
            var       lex = collection.CurrentLexem();

            if (lex.LexemType != LexType.Command)
            {
                collection.Error("Unknow data type", collection.CurrentLexem());
            }
            string       s      = lex.LexemText.ToLower();
            DbColumnType tp     = DbColumnType.Unknow;
            int          param1 = 0;
            int          param2 = 0;

            switch (s)
            {
            case "datetime":
                tp = DbColumnType.DateTime;
                ReadSub1Number(collection, out param1);    //ignore
                break;

            case "timestamp":
                tp = DbColumnType.DateTime;
                if (ParserUtils.ParseCommandPhrase(collection, "timestamp without time zone", true, false))
                {
                    tp = DbColumnType.DateTime;
                }
                if (ParserUtils.ParseCommandPhrase(collection, "timestamp with time zone", true, false))
                {
                    tp = DbColumnType.DateTimeWithTimeZone;
                }
                ReadSub1Number(collection, out param1);    //ignore
                break;

            case "date":
                tp = DbColumnType.Date;
                ReadSub1Number(collection, out param1);    //ignore
                break;

            case "time":
                tp = DbColumnType.Time;
                if (ParserUtils.ParseCommandPhrase(collection, "time without time zone", true, false))
                {
                    tp = DbColumnType.Time;
                }
                if (ParserUtils.ParseCommandPhrase(collection, "time with time zone", true, false))
                {
                    tp = DbColumnType.TimeWithTimeZome;
                }
                ReadSub1Number(collection, out param1);    //ignore
                break;

            case "int8":
            case "byte":
            case "tinyint":
                tp = DbColumnType.Byte;
                break;

            case "int16":
            case "smallint":
                tp = DbColumnType.SmallInt;
                break;

            case "int32":
            case "integer":
            case "int":
                tp = DbColumnType.Integer;
                break;

            case "float":
            case "real":
                tp = DbColumnType.Real;
                ReadSub1Number(collection, out param1);    //ignore
                break;

            case "double":
                ParserUtils.ParseCommandPhrase(collection, "double precision");
                tp = DbColumnType.Double;
                break;

            case "bigint":
            case "int64":
                tp = DbColumnType.BigInt;
                break;

            case "decimal":
            case "numeric":
                tp = DbColumnType.Numeric;
                ReadSub2Number(collection, out param1, out param2);
                break;

            case "nvarchar":
            case "varchar":
                tp = DbColumnType.VarChar;
                if (ReadSub1Number(collection, out param1))
                {
                    if (param1 == 0)
                    {
                        tp = DbColumnType.Text;
                    }
                }
                break;

            case "nchar":
            case "char":
                tp = DbColumnType.VarChar;
                if (!ReadSub1Number(collection, out param1))
                {
                    collection.ErrorUnexpected(collection.CurrentOrLast());
                }
                break;

            case "character":
                tp = DbColumnType.Char;
                if (ParserUtils.ParseCommandPhrase(collection, "character varying"))
                {
                    tp = DbColumnType.VarChar;
                }
                if (!ReadSub1Number(collection, out param1))
                {
                    collection.ErrorUnexpected(collection.CurrentOrLast());
                }
                break;

            case "text":
                tp = DbColumnType.Text;
                break;

            case "blob":
                tp = DbColumnType.Blob;
                break;

            case "bit":
            case "bool":
            case "boolean":
                tp = DbColumnType.Boolean;
                break;

            case "geometry":
                tp = DbColumnType.Geometry;
                break;

            case "geography":
                tp = DbColumnType.Geography;
                break;

            default:
                return(null);
            }
            res = ExactType.Create(tp);
            if (tp == DbColumnType.Numeric)
            {
                res.Precision = param1;
                res.Scale     = param2;
            }
            if (tp == DbColumnType.Char || tp == DbColumnType.VarChar)
            {
                res.MaxTextLength = param1;
            }
            return(res);
        }