/******************************************************** * ADO.NET 2.0 Data Provider for SQLite Version 3.X * Written by Robert Simpson (robert@blackcastlesoft.com) * * Released to the public domain, use at your own risk! ********************************************************/ namespace System.Data.SQLite { using System; using System.Data; using System.Data.Common; using System.Globalization; using System.ComponentModel; /// /// SQLite implementation of DbCommandBuilder. /// public sealed class SQLiteCommandBuilder : DbCommandBuilder { /// /// Default constructor /// public SQLiteCommandBuilder() : this(null) { } /// /// Initializes the command builder and associates it with the specified data adapter. /// /// public SQLiteCommandBuilder(SQLiteDataAdapter adp) { QuotePrefix = "["; QuoteSuffix = "]"; DataAdapter = adp; } /// /// Minimal amount of parameter processing. Primarily sets the DbType for the parameter equal to the provider type in the schema /// /// The parameter to use in applying custom behaviors to a row /// The row to apply the parameter to /// The type of statement /// Whether the application of the parameter is part of a WHERE clause protected override void ApplyParameterInfo(DbParameter parameter, DataRow row, StatementType statementType, bool whereClause) { SQLiteParameter param = (SQLiteParameter)parameter; param.DbType = (DbType)row[SchemaTableColumn.ProviderType]; } /// /// Returns a valid named parameter /// /// The name of the parameter /// Error protected override string GetParameterName(string parameterName) { return String.Format(CultureInfo.InvariantCulture, "@{0}", parameterName); } /// /// Returns a named parameter for the given ordinal /// /// The i of the parameter /// Error protected override string GetParameterName(int parameterOrdinal) { return String.Format(CultureInfo.InvariantCulture, "@param{0}", parameterOrdinal); } /// /// Returns a placeholder character for the specified parameter i. /// /// The index of the parameter to provide a placeholder for /// Returns a named parameter protected override string GetParameterPlaceholder(int parameterOrdinal) { return GetParameterName(parameterOrdinal); } /// /// Sets the handler for receiving row updating events. Used by the DbCommandBuilder to autogenerate SQL /// statements that may not have previously been generated. /// /// A data adapter to receive events on. protected override void SetRowUpdatingHandler(DbDataAdapter adapter) { if (adapter == base.DataAdapter) { ((SQLiteDataAdapter)adapter).RowUpdating -= new EventHandler(RowUpdatingEventHandler); } else { ((SQLiteDataAdapter)adapter).RowUpdating += new EventHandler(RowUpdatingEventHandler); } } private void RowUpdatingEventHandler(object sender, RowUpdatingEventArgs e) { base.RowUpdatingHandler(e); } /// /// Gets/sets the DataAdapter for this CommandBuilder /// public new SQLiteDataAdapter DataAdapter { get { return (SQLiteDataAdapter)base.DataAdapter; } set { base.DataAdapter = value; } } /// /// Returns the automatically-generated SQLite command to delete rows from the database /// /// public new SQLiteCommand GetDeleteCommand() { return (SQLiteCommand)base.GetDeleteCommand(); } /// /// Returns the automatically-generated SQLite command to delete rows from the database /// /// /// public new SQLiteCommand GetDeleteCommand(bool useColumnsForParameterNames) { return (SQLiteCommand)base.GetDeleteCommand(useColumnsForParameterNames); } /// /// Returns the automatically-generated SQLite command to update rows in the database /// /// public new SQLiteCommand GetUpdateCommand() { return (SQLiteCommand)base.GetUpdateCommand(); } /// /// Returns the automatically-generated SQLite command to update rows in the database /// /// /// public new SQLiteCommand GetUpdateCommand(bool useColumnsForParameterNames) { return (SQLiteCommand)base.GetUpdateCommand(useColumnsForParameterNames); } /// /// Returns the automatically-generated SQLite command to insert rows into the database /// /// public new SQLiteCommand GetInsertCommand() { return (SQLiteCommand)base.GetInsertCommand(); } /// /// Returns the automatically-generated SQLite command to insert rows into the database /// /// /// public new SQLiteCommand GetInsertCommand(bool useColumnsForParameterNames) { return (SQLiteCommand)base.GetInsertCommand(useColumnsForParameterNames); } /// /// Overridden to hide its property from the designer /// #if !PLATFORM_COMPACTFRAMEWORK [Browsable(false)] #endif public override CatalogLocation CatalogLocation { get { return base.CatalogLocation; } set { base.CatalogLocation = value; } } /// /// Overridden to hide its property from the designer /// #if !PLATFORM_COMPACTFRAMEWORK [Browsable(false)] #endif public override string CatalogSeparator { get { return base.CatalogSeparator; } set { base.CatalogSeparator = value; } } /// /// Overridden to hide its property from the designer /// #if !PLATFORM_COMPACTFRAMEWORK [Browsable(false)] #endif [DefaultValue("[")] public override string QuotePrefix { get { return base.QuotePrefix; } set { base.QuotePrefix = value; } } /// /// Overridden to hide its property from the designer /// #if !PLATFORM_COMPACTFRAMEWORK [Browsable(false)] #endif public override string QuoteSuffix { get { return base.QuoteSuffix; } set { base.QuoteSuffix = value; } } /// /// Places brackets around an identifier /// /// The identifier to quote /// The bracketed identifier public override string QuoteIdentifier(string unquotedIdentifier) { if (String.IsNullOrEmpty(QuotePrefix) || String.IsNullOrEmpty(QuoteSuffix) || String.IsNullOrEmpty(unquotedIdentifier)) return unquotedIdentifier; return QuotePrefix + unquotedIdentifier.Replace(QuoteSuffix, QuoteSuffix + QuoteSuffix) + QuoteSuffix; } /// /// Removes brackets around an identifier /// /// The quoted (bracketed) identifier /// The undecorated identifier public override string UnquoteIdentifier(string quotedIdentifier) { if (String.IsNullOrEmpty(QuotePrefix) || String.IsNullOrEmpty(QuoteSuffix) || String.IsNullOrEmpty(quotedIdentifier)) return quotedIdentifier; if (quotedIdentifier.StartsWith(QuotePrefix, StringComparison.InvariantCultureIgnoreCase) == false || quotedIdentifier.EndsWith(QuoteSuffix, StringComparison.InvariantCultureIgnoreCase) == false) return quotedIdentifier; return quotedIdentifier.Substring(QuotePrefix.Length, quotedIdentifier.Length - (QuotePrefix.Length + QuoteSuffix.Length)).Replace(QuoteSuffix + QuoteSuffix, QuoteSuffix); } /// /// Overridden to hide its property from the designer /// #if !PLATFORM_COMPACTFRAMEWORK [Browsable(false)] #endif public override string SchemaSeparator { get { return base.SchemaSeparator; } set { base.SchemaSeparator = value; } } /// /// Override helper, which can help the base command builder choose the right keys for the given query /// /// /// protected override DataTable GetSchemaTable(DbCommand sourceCommand) { using (IDataReader reader = sourceCommand.ExecuteReader(CommandBehavior.KeyInfo | CommandBehavior.SchemaOnly)) { DataTable schema = reader.GetSchemaTable(); // If the query contains a primary key, turn off the IsUnique property // for all the non-key columns if (HasSchemaPrimaryKey(schema)) ResetIsUniqueSchemaColumn(schema); // if table has no primary key we use unique columns as a fall back return schema; } } private bool HasSchemaPrimaryKey(DataTable schema) { DataColumn IsKeyColumn = schema.Columns[SchemaTableColumn.IsKey]; foreach (DataRow schemaRow in schema.Rows) { if ((bool)schemaRow[IsKeyColumn] == true) return true; } return false; } private void ResetIsUniqueSchemaColumn(DataTable schema) { DataColumn IsUniqueColumn = schema.Columns[SchemaTableColumn.IsUnique]; DataColumn IsKeyColumn = schema.Columns[SchemaTableColumn.IsKey]; foreach (DataRow schemaRow in schema.Rows) { if ((bool)schemaRow[IsKeyColumn] == false) schemaRow[IsUniqueColumn] = false; } schema.AcceptChanges(); } } }