public FbScript(string script)
        {
            if (script == null)
            {
                throw new ArgumentNullException();
            }

            _results       = new FbStatementCollection();
            _parser        = new SqlStringParser(script);
            _parser.Tokens = new[] { ";" };
        }
        /// <summary>
        /// Updates the connection string with the data parsed from the parameter and opens a connection
        /// to the database.
        /// </summary>
        /// <param name="connectDbStatement"></param>
        private async Task ConnectToDatabase(string connectDbStatement, AsyncWrappingCommonArgs async)
        {
            // CONNECT 'filespec'
            // [USER 'username']
            // [PASSWORD 'password']
            // [CACHE int]
            // [ROLE 'rolename']
            var parser = new SqlStringParser(connectDbStatement);

            parser.Tokens = StandardParseTokens;
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpperInvariant() != "CONNECT")
                {
                    throw new ArgumentException("Malformed isql CONNECT statement. Expected keyword CONNECT but something else was found.");
                }
                enumerator.MoveNext();
                _connectionString.Database = enumerator.Current.Text.Replace("'", string.Empty);
                while (enumerator.MoveNext())
                {
                    switch (enumerator.Current.Text.ToUpperInvariant())
                    {
                    case "USER":
                        enumerator.MoveNext();
                        _connectionString.UserID = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "PASSWORD":
                        enumerator.MoveNext();
                        _connectionString.Password = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "CACHE":
                        enumerator.MoveNext();
                        break;

                    case "ROLE":
                        enumerator.MoveNext();
                        _connectionString.Role = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    default:
                        throw new ArgumentException("Unexpected token '" + enumerator.Current.Text + "' on isql CONNECT statement.");
                    }
                }
            }
            _requiresNewConnection = true;
            await ProvideConnection(async).ConfigureAwait(false);
        }
        /// <summary>
        /// Updates the connection string with the data parsed from the parameter and opens a connection
        /// to the database.
        /// </summary>
        /// <param name="connectDbStatement"></param>
        protected void ConnectToDatabase(string connectDbStatement)
        {
            // CONNECT 'filespec'
            // [USER 'username']
            // [PASSWORD 'password']
            // [CACHE int]
            // [ROLE 'rolename']
            SqlStringParser parser = new SqlStringParser(connectDbStatement);

            parser.Tokens = new[] { " ", "\r\n", "\n", "\r" };
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpperInvariant() != "CONNECT")
                {
                    throw new ArgumentException("Malformed isql CONNECT statement. Expected keyword CONNECT but something else was found.");
                }
                enumerator.MoveNext();
                _connectionString.Database = enumerator.Current.Text.Replace("'", string.Empty);
                while (enumerator.MoveNext())
                {
                    switch (enumerator.Current.Text.ToUpperInvariant())
                    {
                    case "USER":
                        enumerator.MoveNext();
                        _connectionString.UserID = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "PASSWORD":
                        enumerator.MoveNext();
                        _connectionString.Password = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "CACHE":
                        enumerator.MoveNext();
                        break;

                    case "ROLE":
                        enumerator.MoveNext();
                        _connectionString.Role = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    default:
                        throw new ArgumentException("Unexpected token '" + enumerator.Current.Text + "' on isql CONNECT statement.");
                    }
                }
            }
            _requiresNewConnection = true;
            ProvideConnection();
        }
        /// <summary>
        /// Parses the isql statement SET NAMES and sets the character set to current connection string.
        /// </summary>
        /// <param name="setNamesStatement">The set names statement.</param>
        private void SetNames(string setNamesStatement)
        {
            // SET NAMES charset
            var parser = new SqlStringParser(setNamesStatement);

            parser.Tokens = StandardParseTokens;
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpperInvariant() != "SET")
                {
                    throw new ArgumentException("Malformed isql SET statement. Expected keyword SET but something else was found.");
                }
                enumerator.MoveNext();                 // NAMES
                enumerator.MoveNext();
                _connectionString.Charset = enumerator.Current.Text;
            }
        }
        /// <summary>
        /// Parses the isql statement SET NAMES and sets the character set to current connection string.
        /// </summary>
        /// <param name="setNamesStatement">The set names statement.</param>
        protected void SetNames(string setNamesStatement)
        {
            // SET NAMES charset
            SqlStringParser parser = new SqlStringParser(setNamesStatement);

            parser.Tokens = new[] { " ", "\r\n", "\n", "\r" };
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpper(CultureInfo.InvariantCulture) != "SET")
                {
                    throw new ArgumentException("Malformed isql SET statement. Expected keyword SET but something else was found.");
                }
                enumerator.MoveNext();                 // NAMES
                enumerator.MoveNext();
                _connectionString.Charset = enumerator.Current.Text;
            }
        }
        /// <summary>
        /// Parses the isql statement SET SQL DIALECT and sets the dialect set to current connection string.
        /// </summary>
        /// <param name="setSqlDialectStatement">The set sql dialect statement.</param>
        private void SetSqlDialect(string setSqlDialectStatement)
        {
            // SET SQL DIALECT dialect
            var parser = new SqlStringParser(setSqlDialectStatement);

            parser.Tokens = StandardParseTokens;
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpperInvariant() != "SET")
                {
                    throw new ArgumentException("Malformed isql SET statement. Expected keyword SET but something else was found.");
                }
                enumerator.MoveNext();                 // SQL
                enumerator.MoveNext();                 // DIALECT
                enumerator.MoveNext();
                int.TryParse(enumerator.Current.Text, out var dialect);
                _connectionString.Dialect = dialect;
            }
        }
        /// <summary>
        /// Parses the isql statement SET SQL DIALECT and sets the dialect set to current connection string.
        /// </summary>
        /// <param name="setSqlDialectStatement">The set sql dialect statement.</param>
        protected void SetSqlDialect(string setSqlDialectStatement)
        {
            // SET SQL DIALECT dialect
            SqlStringParser parser = new SqlStringParser(setSqlDialectStatement);

            parser.Tokens = new[] { " ", "\r\n", "\n", "\r" };
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpper(CultureInfo.InvariantCulture) != "SET")
                {
                    throw new ArgumentException("Malformed isql SET statement. Expected keyword SET but something else was found.");
                }
                enumerator.MoveNext();                 // SQL
                enumerator.MoveNext();                 // DIALECT
                enumerator.MoveNext();
                int dialect = 3;
                int.TryParse(enumerator.Current.Text, out dialect);
                _connectionString.Dialect = dialect;
            }
        }
        /// <summary>
        /// Parses the isql statement SET AUTODDL and sets the character set to current connection string.
        /// </summary>
        /// <param name="setAutoDdlStatement">The set names statement.</param>
        private void SetAutoDdl(string setAutoDdlStatement, ref bool autoCommit)
        {
            // SET AUTODDL [ON | OFF]
            var parser = new SqlStringParser(setAutoDdlStatement);

            parser.Tokens = StandardParseTokens;
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpperInvariant() != "SET")
                {
                    throw new ArgumentException("Malformed isql SET statement. Expected keyword SET but something else was found.");
                }
                enumerator.MoveNext();                 // AUTO
                if (enumerator.MoveNext())
                {
                    var onOff = enumerator.Current.Text.ToUpperInvariant();
                    if (onOff == "ON")
                    {
                        autoCommit = true;
                    }
                    else if (onOff == "OFF")
                    {
                        autoCommit = false;
                    }
                    else
                    {
                        throw new ArgumentException("Expected the ON or OFF but something else was found.");
                    }
                }
                else
                {
                    autoCommit = !autoCommit;
                }
            }
        }
        /// <summary>
        /// Parses the isql statement CREATE DATABASE and creates the database and opens a connection to the recently created database.
        /// </summary>
        /// <param name="createDatabaseStatement">The create database statement.</param>
        private async Task CreateDatabase(string createDatabaseStatement, AsyncWrappingCommonArgs async)
        {
            // CREATE {DATABASE | SCHEMA} 'filespec'
            // [USER 'username' [PASSWORD 'password']]
            // [PAGE_SIZE [=] int]
            // [LENGTH [=] int [PAGE[S]]]
            // [DEFAULT CHARACTER SET charset]
            // [<secondary_file>];
            var pageSize = 0;
            var parser   = new SqlStringParser(createDatabaseStatement);

            parser.Tokens = StandardParseTokens;
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpperInvariant() != "CREATE")
                {
                    throw new ArgumentException("Malformed isql CREATE statement. Expected keyword CREATE but something else was found.");
                }
                enumerator.MoveNext();                 // {DATABASE | SCHEMA}
                enumerator.MoveNext();
                _connectionString.Database = enumerator.Current.Text.Replace("'", string.Empty);
                while (enumerator.MoveNext())
                {
                    switch (enumerator.Current.Text.ToUpperInvariant())
                    {
                    case "USER":
                        enumerator.MoveNext();
                        _connectionString.UserID = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "PASSWORD":
                        enumerator.MoveNext();
                        _connectionString.Password = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "PAGE_SIZE":
                        enumerator.MoveNext();
                        if (enumerator.Current.Text == "=")
                        {
                            enumerator.MoveNext();
                        }
                        int.TryParse(enumerator.Current.Text, out pageSize);
                        break;

                    case "DEFAULT":
                        enumerator.MoveNext();
                        if (enumerator.Current.Text.ToUpperInvariant() != "CHARACTER")
                        {
                            throw new ArgumentException("Expected the keyword CHARACTER but something else was found.");
                        }

                        enumerator.MoveNext();
                        if (enumerator.Current.Text.ToUpperInvariant() != "SET")
                        {
                            throw new ArgumentException("Expected the keyword SET but something else was found.");
                        }

                        enumerator.MoveNext();
                        _connectionString.Charset = enumerator.Current.Text;
                        break;
                    }
                }
            }
            await async.AsyncSyncCall((cs, ps, ct) => FbConnection.CreateDatabaseAsync(cs, pageSize: ps, cancellationToken: ct), (cs, ps) => FbConnection.CreateDatabase(cs, pageSize: ps), _connectionString.ToString(), pageSize).ConfigureAwait(false);

            _requiresNewConnection = true;
            await ProvideConnection(async).ConfigureAwait(false);
        }
        /// <summary>
        /// Parses the isql statement CREATE DATABASE and creates the database and opens a connection to the recently created database.
        /// </summary>
        /// <param name="createDatabaseStatement">The create database statement.</param>
        protected void CreateDatabase(string createDatabaseStatement)
        {
            // CREATE {DATABASE | SCHEMA} 'filespec'
            // [USER 'username' [PASSWORD 'password']]
            // [PAGE_SIZE [=] int]
            // [LENGTH [=] int [PAGE[S]]]
            // [DEFAULT CHARACTER SET charset]
            // [<secondary_file>];
            var pageSize = 0;
            var parser   = new SqlStringParser(createDatabaseStatement);

            parser.Tokens = new[] { " ", "\r\n", "\n", "\r" };
            using (var enumerator = parser.Parse().GetEnumerator())
            {
                enumerator.MoveNext();
                if (enumerator.Current.Text.ToUpperInvariant() != "CREATE")
                {
                    throw new ArgumentException("Malformed isql CREATE statement. Expected keyword CREATE but something else was found.");
                }
                enumerator.MoveNext();                 // {DATABASE | SCHEMA}
                enumerator.MoveNext();
                _connectionString.Database = enumerator.Current.Text.Replace("'", string.Empty);
                while (enumerator.MoveNext())
                {
                    switch (enumerator.Current.Text.ToUpperInvariant())
                    {
                    case "USER":
                        enumerator.MoveNext();
                        _connectionString.UserID = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "PASSWORD":
                        enumerator.MoveNext();
                        _connectionString.Password = enumerator.Current.Text.Replace("'", string.Empty);
                        break;

                    case "PAGE_SIZE":
                        enumerator.MoveNext();
                        if (enumerator.Current.Text == "=")
                        {
                            enumerator.MoveNext();
                        }
                        int.TryParse(enumerator.Current.Text, out pageSize);
                        break;

                    case "DEFAULT":
                        enumerator.MoveNext();
                        if (enumerator.Current.Text.ToUpperInvariant() != "CHARACTER")
                        {
                            throw new ArgumentException("Expected the keyword CHARACTER but something else was found.");
                        }

                        enumerator.MoveNext();
                        if (enumerator.Current.Text.ToUpperInvariant() != "SET")
                        {
                            throw new ArgumentException("Expected the keyword SET but something else was found.");
                        }

                        enumerator.MoveNext();
                        _connectionString.Charset = enumerator.Current.Text;
                        break;
                    }
                }
            }
            FbConnection.CreateDatabase(_connectionString.ToString(), pageSize, true, false);
            _requiresNewConnection = true;
            ProvideConnection();
        }
		public FbScript(string script)
		{
			_results = new FbStatementCollection();
			_parser = new SqlStringParser(script);
			_parser.Tokens = new[] { ";" };
		}