/// <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 ConnectToDatabaseAsync(string connectDbStatement, CancellationToken cancellationToken = default) { // 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 ProvideConnectionAsync(cancellationToken).ConfigureAwait(false); }
/// <summary> /// Parses the SQL code and loads the SQL statements into the StringCollection <see cref="Results"/>. /// </summary> /// <returns>The number of statements found.</returns> public int Parse() { _results.Clear(); foreach (var statement in _parser.Parse()) { if (IsSetTermStatement(statement.CleanText, out var newParserToken)) { _parser.Tokens = new[] { newParserToken }; continue; } if (statement.CleanText != string.Empty) { var type = GetStatementType(statement.CleanText); if (type != null) { statement.SetStatementType((SqlStatementType)type); _results.Add(statement); continue; } } if (statement.Text.Trim() != string.Empty) { var unknownStatementEventArgs = new UnknownStatementEventArgs(statement); UnknownStatement?.Invoke(this, unknownStatementEventArgs); if (unknownStatementEventArgs.Handled && !unknownStatementEventArgs.Ignore) { statement.SetStatementType(unknownStatementEventArgs.NewStatementType); _results.Add(statement); continue; } else if (!unknownStatementEventArgs.Handled && unknownStatementEventArgs.Ignore) { continue; } else if (unknownStatementEventArgs.Handled && unknownStatementEventArgs.Ignore) { throw new InvalidOperationException($"Both {nameof(UnknownStatementEventArgs.Handled)} and {nameof(UnknownStatementEventArgs.Ignore)} should not be set."); } else { throw new ArgumentException($"The type of the SQL statement could not be determined. See also {nameof(UnknownStatement)} event.{Environment.NewLine}Statement: {statement.Text}."); } } } return(_results.Count); }
/// <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 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 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 CreateDatabaseAsync(string createDatabaseStatement, CancellationToken cancellationToken = default) { // 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 FbConnection.CreateDatabaseAsync(_connectionString.ToString(), pageSize : pageSize, cancellationToken : cancellationToken).ConfigureAwait(false); _requiresNewConnection = true; await ProvideConnectionAsync(cancellationToken).ConfigureAwait(false); }