/********************************************************
* 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 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
{
///
/// 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();
}
}
}