// // Mono.Data.Sqlite.SQLiteCommandBuilder.cs // // Author(s): // Robert Simpson (robert@blackcastlesoft.com) // // Adapted and modified for the Mono Project by // Marek Habersack (grendello@gmail.com) // // // Copyright (C) 2006 Novell, Inc (http://www.novell.com) // Copyright (C) 2007 Marek Habersack // // Permission is hereby granted, free of charge, to any person obtaining // a copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to // permit persons to whom the Software is furnished to do so, subject to // the following conditions: // // The above copyright notice and this permission notice shall be // included in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // /******************************************************** * 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! ********************************************************/ #if NET_2_0 namespace Mono.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 { private EventHandler _handler; /// /// 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) { SqliteDataAdapter adp = (SqliteDataAdapter)adapter; _handler = new EventHandler(RowUpdatingEventHandler); adp.RowUpdating += _handler; } 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(); } } } #endif