/// <summary> /// Resets default for not nullable columns to empty string if it is null. Just to get behavior /// more like Query Browser. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="table">Table with data to post process.</param>> protected override void PostProcessData(DataConnectionWrapper connection, DataTable table) { if (connection == null) { throw new ArgumentNullException("connection"); } if (table == null) { throw new ArgumentNullException("table"); } // Call to base base.PostProcessData(connection, table); // Do not process table whithout rows if (table.Rows == null) { return; } // Reset default value for each not nullable column to empty string if // it is null foreach (DataRow column in table.Rows) { if (DataInterpreter.GetSqlBool(column, Attributes.Nullable).IsFalse && !DataInterpreter.IsNotNull(column, Attributes.Default)) { DataInterpreter.SetValueIfChanged(column, Attributes.Default, String.Empty); } } }
/// <summary> /// Extracts data from the document and forces view to refill. /// </summary> private void ExtractData() { // Reset current data columnsTable = indexesTable = indexColumnsTable = null; connectionRef = null; // Reset view ResetView(); // If document is empty, return if (Document == null) { return; } // Extract all necessary data columnsTable = Document.Columns; indexesTable = Document.Indexes; indexColumnsTable = Document.IndexColumns; connectionRef = Document.Connection; // Validate data Debug.Assert(columnsTable != null && indexesTable != null && indexColumnsTable != null && connectionRef != null, "Failed to extract necessary data!"); // Fill view with new data FillView(); }
/// <summary> /// Reads table with Database Objects which satisfy given restriction. Uses table enumeration for legacy /// version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just return base result if (serverVersion == null || serverVersion.Major >= 5) return base.ReadTable(connection, restrictions, sort);; // For legacy version enumerate tables DataTable result = TableDescriptor.Enumerate(connection, restrictions); // If result is empty, return it if (result == null) return null; // Add is updatable column result.Columns.Add(Attributes.IsUpdatable, typeof(string)); // Set is updatable to true for each row foreach (DataRow table in result.Rows) DataInterpreter.SetValueIfChanged(table, Attributes.IsUpdatable, DataInterpreter.True); // Finaly, return result return result; }
/// <summary> /// Builds enumerate SQL query for object of this type with given restrictions. For legacy version uses /// SHOW TABLE STATUS instead INFORMATION_SCHEMA. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">Restrictions to enumerated objects.</param> /// <param name="sort">Sort expression to use.</param> /// <returns>Enumerating SQL query string.</returns> protected override string BuildEnumerateSql(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just call base if (serverVersion == null || serverVersion.Major >= 5) { return(base.BuildEnumerateSql(connection, restrictions, sort)); } // Build SHOW TABLE STATUS StringBuilder query = new StringBuilder("SHOW TABLE STATUS"); // If there is a restriction on schema, apply it if (restrictions != null && restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1] as string)) { query.Append(" FROM "); QueryBuilder.WriteIdentifier(restrictions[1] as string, query); } // If there is a restriction on table, apply it if (restrictions != null && restrictions.Length >= 3) { QueryBuilder.WriteIfNotEmptyString(restrictions[2], " LIKE ", query); } // Return result return(query.ToString()); }
protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } if (connection.ServerVersion != null && RequiredVersion > connection.ServerVersion) { // This object requires a higher version of the MySql Server return(new DataTable()); } DbConnection conn = (DbConnection)connection.Connection.GetLockedProviderObject(); string[] rest = restrictions == null ? null : new string[restrictions.Length]; if (rest != null) { for (int x = 0; x < rest.Length; x++) { if (restrictions[x] != null) { rest[x] = restrictions[x].ToString(); } } } DataTable dt = conn.GetSchema("Procedures With Parameters", rest); connection.Connection.UnlockProviderObject(); return(dt); }
protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { DataTable dt = base.ReadTable(connection, restrictions, sort); return(MySqlConnectionSupport.ConvertAllBinaryColumns(dt)); }
/// <summary> /// Post process enumeration data. Check server version and add aditional processing for /// legacy version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="table">Table with data to post process.</param> protected override void PostProcessData(DataConnectionWrapper connection, DataTable table) { if (connection == null) { throw new ArgumentNullException("connection"); } if (table == null) { throw new ArgumentNullException("table"); } // Extract server version /* Version serverVersion = connection.ServerVersion; * * // For legacy version rename column returned from SHOW DATABASES to SCHEMA_NAME * if (serverVersion != null && serverVersion.Major < 5) * { * // Table is strange, call base method to try to process it * if (table.Columns == null || table.Columns.Count != 1) * { * Debug.Fail("Table has invalid columns list. It was not returned by SHOW DATABASES!"); * base.PostProcessData(connection, table); * return; * } * * // Rename only one column to SCHEMA_NAME * table.Columns[0].ColumnName = Attributes.Schema; * } * * base.PostProcessData(connection, table);*/ }
/// <summary> /// Returns CREATE DATABASE statement for given schema. /// </summary> /// <param name="connection">Connection to use to execute query.</param> /// <param name="schema">DataRow with information about schema.</param> /// <returns>Returns CREATE DATABASE statement for given schema.</returns> private string GetCreateDatabase(DataConnectionWrapper connection, DataRow schema) { // Extract schema and table name string schemaName = DataInterpreter.GetString(schema, Attributes.Schema); if (String.IsNullOrEmpty(schemaName)) { Debug.Fail("Unable to get schema name"); return(String.Empty); } // Build SHOW CREATE DATABASE StringBuilder query = new StringBuilder(); query.Append("SHOW CREATE DATABASE "); QueryBuilder.WriteIdentifier(schemaName, query); // Execute query and check result table DataTable createDatabase = connection.ExecuteSelectTable(query.ToString()); if (createDatabase == null || createDatabase.Rows.Count <= 0) { Debug.Fail("Failed to read CREATE TABLE query!"); return(String.Empty); } // Extract result string result = DataInterpreter.GetString(createDatabase.Rows[0], "Create Database"); // Dispose table and exit createDatabase.Dispose(); return(result); }
/// <summary> /// In extention method we replace DbNull's on ReturnValue. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="table">Table with data to extend.</param> protected override void PostProcessData(DataConnectionWrapper connection, DataTable table) { if (connection == null) { throw new ArgumentNullException("connection"); } if (table == null) { throw new ArgumentNullException("table"); } // Replacing null values with empty strings; it's required for return // values of functions are anonymous and therefore have null names. Null // values are forbidden for primary key columns foreach (DataRow dr in table.Rows) { if (dr[Attributes.Name] == DBNull.Value) { dr[Attributes.Name] = "ReturnValue"; } } // Call to base method base.PostProcessData(connection, table); }
/// <summary> /// Returns string array of supported table engines. /// </summary> /// <param name="document">Document object for which we need standard values.</param> /// <param name="connection">Connection to use for standard values extraction.</param> /// <returns>Returns string array of supported character sets.</returns> protected override string[] ReadStandartValues(IDocument document, DataConnectionWrapper connection) { if (connection == null) { throw new ArgumentNullException("connection"); } return(connection.GetEngines()); }
/// <summary> /// Enumerates columns with given restrictions into DataTable. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <returns> /// Returns DataTable which contains all columns which satisfy given restrictions. /// </returns> public static DataTable Enumerate(DataConnectionWrapper connection, object[] restrictions) { if (connection == null) { throw new ArgumentNullException("connection"); } return(ObjectDescriptor.EnumerateObjects(connection, TypeName, restrictions)); }
/// <summary> /// Returns DataTable with description of table's columns. /// </summary> /// <param name="connection">Connection object to use for queries.</param> /// <param name="restrictions">Restrictions on table and propably on column.</param> /// <param name="sort">Sort string to use.</param> /// <returns>Returns DataTable with description of table's columns.</returns> private DataTable ReadColumnsForTable(DataConnectionWrapper connection, object[] restrictions, string sort) { // Execute base method DataTable result = base.ReadTable(connection, restrictions, sort); // hackity, hack, hack. We are just doing this so we can avoid having to rewrite a ton // of code to use a data reader to work around the server stupid binary issues. result = ConvertTableIfNecessary(result); // If result is null, exit if (result == null) { return(null); } // Extract table name string table = restrictions[2] as string; // For legacy version rename columns RenameColumn("Field", Attributes.Name, result); RenameColumn("Type", Attributes.ColumnType, result); RenameColumn("Null", Attributes.Nullable, result); RenameColumn("Key", Attributes.ColumnKey, result); RenameColumn("Default", Attributes.Default, result); RenameColumn("Extra", Attributes.Extra, result); // Calculate schema name string schema; if (restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1] as string)) { schema = restrictions[1] as string; } else { schema = connection.Schema; } // Add catalog, schema and type column result.Columns.Add(Attributes.Schema, typeof(string)); result.Columns.Add(Attributes.Table, typeof(string)); // Set schema and table name for each row foreach (DataRow column in result.Rows) { DataInterpreter.SetValueIfChanged(column, Attributes.Schema, schema); DataInterpreter.SetValueIfChanged(column, Attributes.Table, table); // Empty value in IS_NULABLE column means NO if (!DataInterpreter.IsNotEmptyString(column, Attributes.Nullable)) { DataInterpreter.SetValueIfChanged(column, Attributes.Nullable, DataInterpreter.False); } } // Finaly, return result return(result); }
/// <summary> /// Reads list of indexes using SHOW INDEX FROM query. Enumerates tables using /// given restrictions first and then reads indexes for each table. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); DataTable result = PrepareTable(); // Fill restrictions for the tables object[] tableRestrictions = restrictions; // If necessary, cut the restrictions if (restrictions != null && restrictions.Length > 3) { tableRestrictions = new object[3]; tableRestrictions[0] = restrictions[0]; tableRestrictions[1] = restrictions[1]; tableRestrictions[2] = restrictions[2]; } // Read tables DataTable tables = ObjectDescriptor.EnumerateObjects(connection, TableDescriptor.TypeName, tableRestrictions, sort); if (tables == null || tables.Rows == null) return result; // StringBuilder for query StringBuilder query = new StringBuilder(EnumerateSql); // Extract indexes for all tables foreach (DataRow table in tables.Rows) { // Truncate query if (query.Length > EnumerateSql.Length) query.Remove(EnumerateSql.Length, query.Length - EnumerateSql.Length); // Write table idintifier QueryBuilder.WriteIdentifier( DataInterpreter.GetStringNotNull(table, TableDescriptor.Attributes.Schema), DataInterpreter.GetStringNotNull(table, TableDescriptor.Attributes.Name), query); // Execute query to select indexes DataTable indexes = connection.ExecuteSelectTable(query.ToString()); if (indexes == null || indexes.Rows == null) { Debug.Fail("Failed to read indexes using query:\n" + query.ToString()); continue; } // Fetch data FetchData(restrictions, table, indexes, result); } // Accept changes for result result.AcceptChanges(); // Return resulting table return result; }
/// <summary> /// Reads table with Database Objects which satisfy given restriction. Base implementation /// uses direct SQL query to the INFORMATION_SCHEMA. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just return base result if (serverVersion == null || serverVersion.Major >= 5) { return(base.ReadTable(connection, restrictions, sort)); } // Temporary table to store result DataTable merged = new DataTable(); // Enumerate all tables DataTable tables = TableDescriptor.Enumerate(connection, restrictions); // If there is now tables, return empty table with columns if (tables == null || tables.Rows == null || tables.Rows.Count <= 0) { return(merged); } // Calculate column restrriction object column = restrictions != null && restrictions.Length >= 4 ? restrictions[3] : null; // Enumerate columns for each table foreach (DataRow tableRow in tables.Rows) { // Enumerate columns DataTable columns = ReadColumnsForTable( connection, new object[] { null, DataInterpreter.GetString(tableRow, TableDescriptor.Attributes.Schema), DataInterpreter.GetString(tableRow, TableDescriptor.Attributes.Name), column }, sort); // Merge results if any if (columns != null) { merged.Merge(columns); } } // Return results return(merged); }
/// <summary> /// Enumerates database object of given type with given restrictions into /// DataTable. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="typeName">The type name for objects to be enumerated</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <returns> /// Returns DataTable which contains all database objects of given type which /// satisfy given restrictions. /// </returns> public static DataTable EnumerateObjects(DataConnectionWrapper connection, string typeName, object[] restrictions) { if (connection == null) { throw new ArgumentNullException("connection"); } if (typeName == null) { throw new ArgumentNullException("typeName"); } return(EnumerateObjects(connection, typeName, restrictions, null)); }
/// <summary> /// Returns string with CREATE TABLE sql for the table which owns this index. /// </summary> /// <param name="connection">Connection to use to execute query.</param> /// <param name="row">DataRow with information about index.</param> /// <returns>Returns string with CREATE TABLE sql for this table.</returns> private static string GetCreateTableQuery(DataConnectionWrapper connection, DataRow row) { // Extract schema and table name string schemaName = DataInterpreter.GetString(row, Attributes.Schema); string tableName = DataInterpreter.GetString(row, Attributes.Table); if (String.IsNullOrEmpty(schemaName) || String.IsNullOrEmpty(tableName)) { Debug.Fail("Unable to get table or schema name"); return(String.Empty); } return(TableDescriptor.GetCreateTableQuery(connection, schemaName, tableName)); }
/// <summary> /// Reads table with Database Objects which satisfy given restriction. Base implementation /// uses direct SQL query to the INFORMATION_SCHEMA. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected virtual DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } if (connection.ServerVersion != null && RequiredVersion > connection.ServerVersion) { // This object requires a higher version of the MySql Server return(new DataTable()); } return(connection.ExecuteSelectTable(BuildEnumerateSql(connection, restrictions, sort))); }
/// <summary> /// Returns enumeration SQL template for a given server version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <returns>Returns enumeration SQL template for a given server version.</returns> protected override string GetEnumerateSqlTemplate(DataConnectionWrapper connection) { if (connection == null) throw new ArgumentNullException("connection"); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just call base if( serverVersion == null || serverVersion.Major >= 5 ) return base.GetEnumerateSqlTemplate(connection); // For legacy version use SHOW DATABASES return EnumerateSqlTemplate; // "SHOW DATABASES LIKE {1}"; }
/// <summary> /// Returns string array of supported collations for document character sets. /// </summary> /// <param name="document">Document object for which we need standard values.</param> /// <param name="connection">Connection to use for standard values extraction.</param> /// <returns>Returns string array of supported collations for document character sets.</returns> protected override string[] ReadStandartValues(IDocument document, DataConnectionWrapper connection) { if (document == null) throw new ArgumentNullException("document"); if (connection == null) throw new ArgumentNullException("connection"); // Extract provider, if available ICharacterSetProvider provider = (document as ICharacterSetProvider); // If provider not availabel return all collations. if (provider == null) return connection.GetCollations(); // Return collations for provider cahracter set return connection.GetCollationsForCharacterSet(provider.CharcterSet); }
/// <summary> /// Builds enumerate SQL query for object of this type with given restrictions. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">Restrictions to enumerated objects.</param> /// <param name="sort">Sort expression to use.</param> /// <returns>Enumerating SQL query string.</returns> protected virtual string BuildEnumerateSql(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } // Extract enumeration SQL information from the descriptor string sqlTemplate = GetEnumerateSqlTemplate(connection); string[] defaultRestrictions = GetDefaultRestrictions(connection); if (String.IsNullOrEmpty(sqlTemplate) || defaultRestrictions == null) { Debug.Fail("Failed to get enumeration SQL information for object type '" + TypeName + "'"); throw new NotSupportedException(String.Format( CultureInfo.CurrentCulture, Resources.Error_UnableToGetEnumerationSql, TypeName)); } // Get formated SQL string sqlStatement = FormatSqlString(sqlTemplate, restrictions, defaultRestrictions); // Check builded statement Debug.Assert(!String.IsNullOrEmpty(sqlStatement), "Failed to build enumeration statement!"); if (String.IsNullOrEmpty(sqlStatement)) { throw new NotSupportedException(String.Format( CultureInfo.CurrentCulture, Resources.Error_UnableToGetEnumerationSql, TypeName)); } // Append ORDER BY if any string sortExpression = !String.IsNullOrEmpty(sort) ? sort : DefaultSortString; if (!String.IsNullOrEmpty(sortExpression)) { return(String.Format("{0} ORDER BY {1}", sqlStatement, sortExpression)); } // Retrun results return(sqlStatement); }
/// <summary> /// In extention method we replace DbNull's on ReturnValue. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="table">Table with data to extend.</param> protected override void PostProcessData(DataConnectionWrapper connection, DataTable table) { if (connection == null) throw new ArgumentNullException("connection"); if (table == null) throw new ArgumentNullException("table"); // Replacing null values with empty strings; it's required for return // values of functions are anonymous and therefore have null names. Null // values are forbidden for primary key columns foreach (DataRow dr in table.Rows) { if (dr[Attributes.Name] == DBNull.Value) dr[Attributes.Name] = "ReturnValue"; } // Call to base method base.PostProcessData(connection, table); }
/// <summary> /// Extracts field values for given DataRow. Base implementation simply uses Parser /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration</param> /// <param name="row">DataRow to extract values</param> /// <returns>Returns field values for a given DataRow</returns> protected virtual Dictionary <string, string> ExtractOptions(DataConnectionWrapper connection, DataRow row) { if (connection == null) { throw new ArgumentNullException("connection"); } if (row == null) { throw new ArgumentNullException("row"); } // Check a field string (if empty, returns empty dictionary) if (String.IsNullOrEmpty(FieldsStringName)) { return(new Dictionary <string, string>()); } return(Parser.ExtractFieldsDictionary(row, FieldsStringName)); }
/// <summary> /// Uses connection GetSchema instead of direct query to INFORMATION_SCHEMA. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } if (String.IsNullOrEmpty(CollectionName)) { throw new NotSupportedException(Resources.Error_NoCollectionName); } if (connection.ServerVersion != null && RequiredVersion > connection.ServerVersion) { // This object requires a higher version of the MySql Server return(new DataTable()); } return(connection.GetSchema(CollectionName, restrictions)); }
/// <summary> /// Returns default enumerate restrictions for a given server version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <returns>Returns default enumerate restrictions for a given server version.</returns> protected override string[] GetDefaultRestrictions(DataConnectionWrapper connection) { if (connection == null) { throw new ArgumentNullException("connection"); } // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just call base if (serverVersion == null || serverVersion.Major >= 5) { return(base.GetDefaultRestrictions(connection)); } // For legacy version return array with current conection information return(new string[] { "'" + connection.ServerName + "'", "'" + connection.Schema + "'" }); }
/// <summary> /// Returns enumeration SQL template for a given server version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <returns>Returns enumeration SQL template for a given server version.</returns> protected override string GetEnumerateSqlTemplate(DataConnectionWrapper connection) { if (connection == null) { throw new ArgumentNullException("connection"); } // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just call base if (serverVersion == null || serverVersion.Major >= 5) { return(base.GetEnumerateSqlTemplate(connection)); } // For legacy version use SHOW DATABASES return(EnumerateSqlTemplate); // "SHOW DATABASES LIKE {1}"; }
/// <summary> /// Main method. Builds collection of supported standard values. /// </summary> /// <param name="context"> /// Context for standard values extraction. Used to get underlying document /// object. /// </param> /// <returns>Returns the collection of the supported standard values.</returns> public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context) { if (context == null) { Debug.Fail("Context not specified!"); return(null); } if (!(context.Instance is IDocument)) { Debug.Fail("Context has no document!"); return(null); } // Visual Studio doesn't like exceptions here try { // Extract document from the context IDocument document = context.Instance as IDocument; // Extracting connection if (document.Hierarchy == null || document.Hierarchy.Connection == null) { Debug.Fail(Resources.Error_InvalidDocumentNoFacadeOrWrapper); return(null); } DataConnectionWrapper connection = document.Hierarchy.Connection; // Call virtual method to extract values string[] values = ReadStandartValues(document, connection); if (values == null) { return(null); } return(new StandardValuesCollection(values)); } catch (Exception e) { Debug.Fail("Error enumerating default values!", e.ToString()); return(null); } }
/// <summary> /// Enumerates database object of given type with given restrictions into /// DataTable. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="typeName">The type name for objects to be enumerated</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns> /// Returns DataTable which contains all database objects of given type which /// satisfy given restrictions. /// </returns> public static DataTable EnumerateObjects(DataConnectionWrapper connection, string typeName, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } if (typeName == null) { throw new ArgumentNullException("typeName"); } // Get object descriptor for given type ObjectDescriptor descriptor = ObjectDescriptorFactory.Instance.CreateDescriptor(typeName) as ObjectDescriptor; if (descriptor == null) { Debug.Fail("Unsupported object type '" + typeName + "'"); throw new NotSupportedException(String.Format( CultureInfo.CurrentCulture, Resources.Error_ObjectTypeNotSupported, typeName)); } // Read objects DataTable result = descriptor.ReadTable(connection, restrictions, sort); if (result == null) { Debug.Fail("Failed to read data!"); return(null); } // Perform post-processing descriptor.PostProcessData(connection, result); result.AcceptChanges(); // Return result return(result); }
/// <summary> /// Returns string with CREATE TABLE sql for table by gicen schema name and table name. /// </summary> /// <param name="connection">Connection to use to execute query.</param> /// <param name="schemaName">Name of table schema.</param> /// <param name="tableName">Name of the table.</param> /// <returns>Returns string with CREATE TABLE sql for this table.</returns> public static string GetCreateTableQuery(DataConnectionWrapper connection, string schemaName, string tableName) { if (connection == null) { throw new ArgumentNullException("connection"); } if (String.IsNullOrEmpty(schemaName)) { throw new ArgumentException(Resources.Error_EmptyString, "schemaName"); } if (String.IsNullOrEmpty(tableName)) { throw new ArgumentException(Resources.Error_EmptyString, "tableName"); } // Build SHOW CREATE TABLE table StringBuilder query = new StringBuilder(); query.Append("SHOW CREATE TABLE "); QueryBuilder.WriteIdentifier(schemaName, tableName, query); // Execute query and check table IDataReader reader = connection.ExecuteReader(query.ToString(), false, CommandBehavior.Default); if (reader == null || !reader.Read()) { Debug.Fail("Failed to read CREATE TABLE query!"); return(String.Empty); } // Extract result string result = reader.GetString(1); reader.Close(); return(result); }
/// <summary> /// Reads table with Database Objects which satisfy given restriction. Uses table enumeration for legacy /// version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) { throw new ArgumentNullException("connection"); } // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just return base result if (serverVersion == null || serverVersion.Major >= 5) { return(base.ReadTable(connection, restrictions, sort)); } ; // For legacy version enumerate tables DataTable result = TableDescriptor.Enumerate(connection, restrictions); // If result is empty, return it if (result == null) { return(null); } // Add is updatable column result.Columns.Add(Attributes.IsUpdatable, typeof(string)); // Set is updatable to true for each row foreach (DataRow table in result.Rows) { DataInterpreter.SetValueIfChanged(table, Attributes.IsUpdatable, DataInterpreter.True); } // Finaly, return result return(result); }
/// <summary> /// Returns string array of supported collations for document character sets. /// </summary> /// <param name="document">Document object for which we need standard values.</param> /// <param name="connection">Connection to use for standard values extraction.</param> /// <returns>Returns string array of supported collations for document character sets.</returns> protected override string[] ReadStandartValues(IDocument document, DataConnectionWrapper connection) { if (document == null) { throw new ArgumentNullException("document"); } if (connection == null) { throw new ArgumentNullException("connection"); } // Extract provider, if available ICharacterSetProvider provider = (document as ICharacterSetProvider); // If provider not availabel return all collations. if (provider == null) { return(connection.GetCollations()); } // Return collations for provider cahracter set return(connection.GetCollationsForCharacterSet(provider.CharcterSet)); }
/// <summary> /// Post process enumeration data. Base implementation adds primary key to /// the table and calculate fields /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration</param> /// <param name="table">A table with data to post process</param> protected virtual void PostProcessData(DataConnectionWrapper connection, DataTable table) { if (connection == null) { throw new ArgumentNullException("connection"); } if (table == null) { throw new ArgumentNullException("table"); } // Adding table columns ExtendData(connection, table); // Validate read data if (!ValidateAttributesTable(table)) { throw new Exception(Resources.Error_AttributesAreMissing); } // Add primary key AddPrimaryKey(table); }
/// <summary> /// Reads table with Database Objects which satisfy given restriction. Applies filter for aditional restriction /// if MySQL version is less then 5.0. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); // Use base method to read table DataTable first_result = base.ReadTable(connection, restrictions, sort); // fixup collation names DataTable result = MySqlConnectionSupport.ConvertAllBinaryColumns(first_result); // If there is now result from bas, return immediately if (result == null) return result; // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just call base if (serverVersion == null || serverVersion.Major >= 5) return result; // For legacy version apply restrictions to result manualy (first slot - character set name, third slot - flag is default) // At first check if there is any restrictions if (restrictions == null || restrictions.Length <= 0) return result; if (String.IsNullOrEmpty(restrictions[0] as String) && (restrictions.Length < 3 || String.IsNullOrEmpty(restrictions[2] as String))) return result; // Iterates through rows and filter them foreach (DataRow collation in result.Select()) { // Apply character set name filter if (!String.IsNullOrEmpty(restrictions[0] as String) && !DataInterpreter.CompareInvariant( restrictions[0] as String, DataInterpreter.GetStringNotNull(collation, Attributes.CharacterSetName))) { collation.Delete(); continue; } // Apply is_default constraint if (restrictions.Length >= 3 && !String.IsNullOrEmpty(restrictions[2] as String) && !DataInterpreter.CompareInvariant( restrictions[2] as String, DataInterpreter.GetStringNotNull(collation, Attributes.IsDefault))) { collation.Delete(); continue; } } // Accept changes and return results result.AcceptChanges(); return result; }
/// <summary> /// Post process enumeration data. Base implementation adds primary key to /// the table and calculate fields /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration</param> /// <param name="table">A table with data to post process</param> protected virtual void PostProcessData(DataConnectionWrapper connection, DataTable table) { if (connection == null) throw new ArgumentNullException("connection"); if (table == null) throw new ArgumentNullException("table"); // Adding table columns ExtendData(connection, table); // Validate read data if (!ValidateAttributesTable(table)) throw new Exception(Resources.Error_AttributesAreMissing); // Add primary key AddPrimaryKey(table); }
/// <summary> /// Exdents table data with additional information. Base implementation adds /// attributes of this database object /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="table">Table with data to extend.</param> protected virtual void ExtendData(DataConnectionWrapper connection, DataTable table) { if (connection == null) throw new ArgumentNullException("connection"); if (table == null) throw new ArgumentNullException("table"); if (Fields == null || Fields.Count <= 0) // No known fields return; // Add columns for fields Debug.Assert(table.Columns != null, "Table has empty column collection!"); Dictionary<string, FieldAttribute> added = new Dictionary<string, FieldAttribute>(); foreach (KeyValuePair<string, FieldAttribute> field in Fields) { // If column is already exists, skip it if (table.Columns.Contains(field.Key)) continue; // Add column for field AddFieldColumn(table, field.Key, field.Value.FieldType); // Add entry to added dictionary added[field.Key] = field.Value; } // Calculate field values for each row Dictionary<string, string> fieldValues; foreach (DataRow row in table.Rows) { // Parsing field string fieldValues = ExtractOptions(connection, row); if (fieldValues == null || fieldValues.Count <= 0) continue; // Adding a field foreach (KeyValuePair<string, FieldAttribute> field in added) { // Skip empty option names and columns which was in result before option adding. if (string.IsNullOrEmpty(field.Value.OptionName)) continue; AddFieldValue(row, field.Key, field.Value.OptionName, field.Value.FieldType, fieldValues); } } }
protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { DataTable dt = base.ReadTable(connection, restrictions, sort); return MySqlConnectionSupport.ConvertAllBinaryColumns(dt); }
/// <summary> /// Returns string array of supported character sets. /// </summary> /// <param name="document">Document object for which we need standard values.</param> /// <param name="connection">Connection to use for standard values extraction.</param> /// <returns>Returns string array of supported character sets.</returns> protected override string[] ReadStandartValues(IDocument document, DataConnectionWrapper connection) { if (connection == null) throw new ArgumentNullException("connection"); return connection.GetCharacterSets(); }
/// <summary> /// Parses create table and extract values for on delete and on update fields. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="row">DataRow to extract values.</param> /// <returns>Returns field values for given DataRow.</returns> protected override Dictionary<string, string> ExtractOptions(DataConnectionWrapper connection, DataRow row) { if (connection == null) throw new ArgumentNullException("connection"); if (row == null) throw new ArgumentNullException("row"); // Call to base Dictionary<string, string> result = base.ExtractOptions(connection, row); if (result == null) result = new Dictionary<string, string>(); // Restrict by default result.Add(OnDeleteField, RESTRICT); result.Add(OnUpdateField, RESTRICT); // Extract CREATE TABLE sql string createTableQuery = GetCreateTableQuery(connection, row); if (String.IsNullOrEmpty(createTableQuery)) return result; int pos = LocateFlagsPosition(row, createTableQuery); if (pos < 0) { Debug.Fail("Unable to locate begining of the flags!"); return result; } // Read first token, if not ON, then exit. string token = Parser.ExtractToken(createTableQuery, pos); if (!DataInterpreter.CompareInvariant(token, ON)) return result; // Read value for the first field pos += token.Length + 1; string value = ReadAndFillAction(createTableQuery, pos, result); if (value == null) return result; // Read value for the second field (note that ON DELETE and ON UPDATE has the same length) pos += OnDelete.Length + value.Length + 2; value = ReadAndFillAction(createTableQuery, pos, result); // Return result return result; }
/// <summary> /// Abstract method for reading standard values using connection and document /// objects. /// </summary> /// <param name="document">Document object for which we need standard values.</param> /// <param name="connection">Connection to use for standard values extraction.</param> /// <returns>Returns string array with standard values.</returns> protected abstract string[] ReadStandartValues(IDocument document, DataConnectionWrapper connection);
/// <summary> /// Returns default enumerate restrictions for a given server version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <returns>Returns default enumerate restrictions for a given server version.</returns> protected override string[] GetDefaultRestrictions(DataConnectionWrapper connection) { if (connection == null) throw new ArgumentNullException("connection"); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just call base if (serverVersion == null || serverVersion.Major >= 5) return base.GetDefaultRestrictions(connection); // For legacy version return array with current conection information return new string[] { "", "'%'" }; }
/// <summary> /// Builds enumerate SQL query for object of this type with given restrictions. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">Restrictions to enumerated objects.</param> /// <param name="sort">Sort expression to use.</param> /// <returns>Enumerating SQL query string.</returns> protected virtual string BuildEnumerateSql(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); // Extract enumeration SQL information from the descriptor string sqlTemplate = GetEnumerateSqlTemplate(connection); string[] defaultRestrictions = GetDefaultRestrictions(connection); if (String.IsNullOrEmpty(sqlTemplate) || defaultRestrictions == null) { Debug.Fail("Failed to get enumeration SQL information for object type '" + TypeName + "'"); throw new NotSupportedException(String.Format( CultureInfo.CurrentCulture, Resources.Error_UnableToGetEnumerationSql, TypeName)); } // Get formated SQL string sqlStatement = FormatSqlString(sqlTemplate, restrictions, defaultRestrictions); // Check builded statement Debug.Assert(!String.IsNullOrEmpty(sqlStatement), "Failed to build enumeration statement!"); if (String.IsNullOrEmpty(sqlStatement)) throw new NotSupportedException(String.Format( CultureInfo.CurrentCulture, Resources.Error_UnableToGetEnumerationSql, TypeName)); // Append ORDER BY if any string sortExpression = !String.IsNullOrEmpty(sort) ? sort : DefaultSortString; if (!String.IsNullOrEmpty(sortExpression)) return String.Format("{0} ORDER BY {1}", sqlStatement, sortExpression); // Retrun results return sqlStatement; }
/// <summary> /// Extracts option values for given DataRow. For legacy version calculate aditional fields by parsing type /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="row">DataRow to extract values.</param> /// <returns>Returns field values for given DataRow.</returns> protected override Dictionary <string, string> ExtractOptions(DataConnectionWrapper connection, DataRow row) { if (connection == null) { throw new ArgumentNullException("connection"); } if (row == null) { throw new ArgumentNullException("row"); } // Call base method Dictionary <string, string> result = base.ExtractOptions(connection, row); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just return base result if (serverVersion == null || serverVersion.Major >= 5) { return(result); } // Add an ordinal option result[OrdinalOption] = ExtractRowIndex(row); // Extract data type string datatype = DataInterpreter.GetStringNotNull(row, Attributes.ColumnType); Debug.Assert(datatype.Length > 0, "Empty data type!"); // Calculate MySQL type string mySqlType = datatype; // Remove unsigned int pos = mySqlType.IndexOf(" unsigned"); if (pos >= 0) { mySqlType = mySqlType.Remove(pos); } // Remove zerofill pos = mySqlType.IndexOf(" zerofill"); if (pos >= 0) { mySqlType = mySqlType.Remove(pos); } // Add MySQL type option Debug.Assert(!String.IsNullOrEmpty(mySqlType), "MySQL type is empty!"); result[MySqlTypeOption] = mySqlType; // Add a primary key option if (DataInterpreter.CompareInvariant("PRI", DataInterpreter.GetStringNotNull(row, Attributes.ColumnKey))) { result[PrimaryKeyOption] = DataInterpreter.True; } // Add an unsigned option if (datatype.IndexOf(" unsigned") >= 0) { result[UnsignedOption] = DataInterpreter.True; } // Add a zerofill option if (datatype.IndexOf(" zerofill") >= 0) { result[ZerofillOption] = DataInterpreter.True; } // Add a datatype option result[DataTypeOption] = datatype; // TODO: Parse create table for right character set // Add a character set option if (!String.IsNullOrEmpty(connection.DefaultCharacterSet)) { result[CharacterSetOption] = connection.DefaultCharacterSet; } // Add collation field if (!String.IsNullOrEmpty(connection.DefaultCollation)) { result[CollationOption] = connection.DefaultCollation; } // Finaly, return result return(result); }
/// <summary> /// Extracts field values for given DataRow. Base implementation simply uses Parser /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration</param> /// <param name="row">DataRow to extract values</param> /// <returns>Returns field values for a given DataRow</returns> protected virtual Dictionary<string, string> ExtractOptions(DataConnectionWrapper connection, DataRow row) { if (connection == null) throw new ArgumentNullException("connection"); if (row == null) throw new ArgumentNullException("row"); // Check a field string (if empty, returns empty dictionary) if (String.IsNullOrEmpty(FieldsStringName)) return new Dictionary<string, string>(); return Parser.ExtractFieldsDictionary(row, FieldsStringName); }
/// <summary> /// Extracts data from the document and forces view to refill. /// </summary> private void ExtractData() { // Reset current data columnsTable = foreignKeysTable = foreignKeyColumnsTable = null; connectionRef = null; // Reset view ResetView(); // If document is empty, return if (Document == null) return; // Extract all necessary data columnsTable = Document.Columns; foreignKeysTable = Document.ForeignKeys; foreignKeyColumnsTable = Document.ForeignKeysColumns; connectionRef = Document.Connection; // Validate data Debug.Assert( columnsTable != null && foreignKeysTable != null && foreignKeyColumnsTable != null && connectionRef != null, "Failed to extract necessary data!"); // Fill view with new data FillView(); }
/// <summary> /// Parses create table and extracts index kind (INDEX, PRIMARY, UNIQUE, SPATIAL, FULLTEXT). /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="row">DataRow to extract values.</param> /// <returns>Returns field values for given DataRow.</returns> protected override Dictionary<string, string> ExtractOptions(DataConnectionWrapper connection, System.Data.DataRow row) { if (connection == null) throw new ArgumentNullException("connection"); if (row == null) throw new ArgumentNullException("row"); // Call to base Dictionary<string, string> result = base.ExtractOptions(connection, row); // Default is index result[IndexKindField] = INDEX; // Check if this is primary key if (DataInterpreter.GetSqlBool(row, Attributes.Primary)) { result[IndexKindField] = PRIMARY; return result; } // Check if this is unique constraint if (DataInterpreter.GetSqlBool(row, Attributes.Unique)) { result[IndexKindField] = UNIQUE; return result; } // Extract CREATE TABLE sql string createTableQuery = GetCreateTableQuery(connection, row); if (String.IsNullOrEmpty(createTableQuery)) return result; // Locate beginig of the definition. int pos = LocateDefinition(row, createTableQuery); if (pos < 0) { Debug.Fail("Unable to locate begining of the definition!"); return result; } // Truncate and trim string createTableQuery = createTableQuery.Substring(0, pos).Trim(); // Check for spatial if (createTableQuery.EndsWith(SPATIAL, StringComparison.InvariantCultureIgnoreCase)) result[IndexKindField] = SPATIAL; // Check for fulltext if (createTableQuery.EndsWith(FULLTEXT, StringComparison.InvariantCultureIgnoreCase)) result[IndexKindField] = FULLTEXT; return result; }
/// <summary> /// Post process enumeration data. Check server version and add aditional processing for /// legacy version. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="table">Table with data to post process.</param> protected override void PostProcessData(DataConnectionWrapper connection, DataTable table) { if (connection == null) throw new ArgumentNullException("connection"); if (table == null) throw new ArgumentNullException("table"); // Extract server version /* Version serverVersion = connection.ServerVersion; // For legacy version rename column returned from SHOW DATABASES to SCHEMA_NAME if (serverVersion != null && serverVersion.Major < 5) { // Table is strange, call base method to try to process it if (table.Columns == null || table.Columns.Count != 1) { Debug.Fail("Table has invalid columns list. It was not returned by SHOW DATABASES!"); base.PostProcessData(connection, table); return; } // Rename only one column to SCHEMA_NAME table.Columns[0].ColumnName = Attributes.Schema; } base.PostProcessData(connection, table);*/ }
/// <summary> /// Builds enumerate SQL query for object of this type with given restrictions. For legacy version uses /// SHOW TABLE STATUS instead INFORMATION_SCHEMA. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">Restrictions to enumerated objects.</param> /// <param name="sort">Sort expression to use.</param> /// <returns>Enumerating SQL query string.</returns> protected override string BuildEnumerateSql(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just call base if (serverVersion == null || serverVersion.Major >= 5) return base.BuildEnumerateSql(connection, restrictions, sort); // Build SHOW TABLE STATUS StringBuilder query = new StringBuilder("SHOW TABLE STATUS"); // If there is a restriction on schema, apply it if (restrictions != null && restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1] as string)) { query.Append(" FROM "); QueryBuilder.WriteIdentifier(restrictions[1] as string, query); } // If there is a restriction on table, apply it if (restrictions != null && restrictions.Length >= 3) QueryBuilder.WriteIfNotEmptyString(restrictions[2], " LIKE ", query); // Return result return query.ToString(); }
/// <summary> /// Enumerates engines with given restrictions into DataTable. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <returns> /// Returns DataTable which contains all engines which satisfy given restrictions. /// </returns> public static DataTable Enumerate(DataConnectionWrapper connection, object[] restrictions) { if (connection == null) throw new ArgumentNullException("connection"); return ObjectDescriptor.EnumerateObjects(connection, TypeName, restrictions); }
/// <summary> /// Reads table with Database Objects which satisfy given restriction. Base implementation /// uses direct SQL query to the INFORMATION_SCHEMA. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just return base result if (serverVersion == null || serverVersion.Major >= 5) return base.ReadTable(connection, restrictions, sort); // Execute base method DataTable result; try { result = base.ReadTable(connection, restrictions, sort); } catch(DbException) { // This most probably meanes that table is not exists. Return empty table on this return new DataTable(); } // If result is null, exit if (result == null) return null; // For legacy version rename columns RenameColumn("Name", Attributes.Name, result); RenameColumn("Version", Attributes.Version, result); RenameColumn("Row_format", Attributes.RowFormat, result); RenameColumn("Rows", Attributes.TableRows, result); RenameColumn("Avg_row_length", Attributes.AverageRowLength, result); RenameColumn("Data_length", Attributes.DataLength, result); RenameColumn("Max_data_length", Attributes.MaxDataLength, result); RenameColumn("Index_length", Attributes.IndexLength, result); RenameColumn("Data_free", Attributes.DataFree, result); RenameColumn("Auto_increment", Attributes.AutoIncrement, result); RenameColumn("Create_time", Attributes.CreateDateTime, result); RenameColumn("Update_time", Attributes.UpdateDateTime, result); RenameColumn("Check_time", Attributes.CheckDateTime, result); RenameColumn("Create_options", Attributes.CreateOptions, result); RenameColumn("Comment", Attributes.Comments, result); // Engine was called type before 4.1.2 if (serverVersion < new Version(4, 1, 2)) RenameColumn("Type", Attributes.Engine, result); else RenameColumn("Engine", Attributes.Engine, result); // Engine collation and checksum are implemented only in 4.1.1 if (serverVersion < new Version(4, 1, 1)) { result.Columns.Add(Attributes.Collation, typeof(string)); result.Columns.Add(Attributes.Checksum, typeof(Int64)); } else { RenameColumn("Collation", Attributes.Collation, result); RenameColumn("Checksum", Attributes.Checksum, result); } // Calculate schema name string schema; if (restrictions != null && restrictions.Length >= 2 && !String.IsNullOrEmpty(restrictions[1] as string)) schema = restrictions[1] as string; else schema = connection.Schema; // Add catalog, schema and type column result.Columns.Add(Attributes.Database, typeof(string)); result.Columns.Add(Attributes.Schema, typeof(string)); result.Columns.Add(Attributes.Type, typeof(string)); // Set schema and type name for each row foreach (DataRow table in result.Rows) { DataInterpreter.SetValueIfChanged(table, Attributes.Schema, schema); DataInterpreter.SetValueIfChanged(table, Attributes.Type, "BASE TABLE"); } // Finaly, return result return result; }
/// <summary> /// Extracts field values for given DataRow. For legacy version extract server name, character set and collation. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="row">DataRow to extract values.</param> /// <returns>Returns field values for given DataRow.</returns> protected override Dictionary<string, string> ExtractOptions(DataConnectionWrapper connection, DataRow row) { if (connection == null) throw new ArgumentNullException("connection"); if (row == null) throw new ArgumentNullException("row"); // Call base to extract fields Dictionary<string, string> result = base.ExtractOptions(connection, row); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just return base results if (serverVersion == null || serverVersion.Major >= 5) return result; // Add server name result[ServerField] = connection.ServerName; //Extract CREATE DATABASE string createDatabase = GetCreateDatabase(connection, row); if (String.IsNullOrEmpty(createDatabase)) return result; // Extract default character set Parser.ExtractAdvancedFieldToken(result, createDatabase, "DEFAULT CHARACTER SET ", DefaultCharsetField); // If default character set is not extracted, return if (!result.ContainsKey(DefaultCharsetField)) return result; // Extract default collation Parser.ExtractAdvancedFieldToken(result, createDatabase, "COLLATE ", DefaultCollationField); // If default collation is not extracted, use default collation for character set if (!result.ContainsKey(DefaultCollationField)) { // Extract default character set field string defaultCharSet = result[DefaultCharsetField]; // Extract default collation for this character set if (!String.IsNullOrEmpty(defaultCharSet)) { string defaultCollation = connection.GetDefaultCollationForCharacterSet(defaultCharSet); if (!String.IsNullOrEmpty(defaultCollation)) result[DefaultCollationField] = defaultCollation; } } // Return result return result; }
/// <summary> /// Extracts field values for given DataRow. Base implementation simply uses Parser. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="row">DataRow to extract values.</param> /// <returns>Returns field values for given DataRow.</returns> protected override Dictionary<string, string> ExtractOptions(DataConnectionWrapper connection, DataRow row) { if (connection == null) throw new ArgumentNullException("connection"); if (row == null) throw new ArgumentNullException("row"); // Call to base Dictionary<string, string> result = base.ExtractOptions(connection, row); if (result == null) result = new Dictionary<string, string>(); // Extract CREATE TABLE sql string createTableQuery = GetCreateTableQuery(connection, row); if (String.IsNullOrEmpty(createTableQuery)) return result; // Extract a connection field Parser.ExtractAdvancedFieldUnquoted(result, createTableQuery, ConnectionQueryPart, ConnectionField); // Extract an insert method field Parser.ExtractAdvancedFieldToken(result, createTableQuery, InsertMethodQueryPart, InsertMethodField); // Extract a union field Parser.ExtractAdvancedFieldUnbraced(result, createTableQuery, UnionQueryPart, UnionField); // Extract the DATA_DIRECTORY field Parser.ExtractAdvancedFieldUnquoted(result, createTableQuery, DataDirectoryQueryPart, DataDirectoryField); // Extract the INDEX_DIRECTORY field Parser.ExtractAdvancedFieldUnquoted(result, createTableQuery, IndexDirectoryQueryPart, IndexDirectoryField); // For legacy version calculate character set // Extract server version Version serverVersion = connection.ServerVersion; // For MySQL greater then 4.1.1 we can calculate character set if (serverVersion != null && serverVersion.Major < 5 && serverVersion >= new Version(4, 1, 1)) { // Extract collation string collation = DataInterpreter.GetString(row, Attributes.Collation); if (!String.IsNullOrEmpty(collation)) { string characterSet = connection.GetCharacterSetForCollation(collation); if (!String.IsNullOrEmpty(characterSet)) result[CharacterSetField] = characterSet; } } // Return results return result; }
/// <summary> /// Extracts field values for given DataRow. For legacy version extract server name, character set and collation. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="row">DataRow to extract values.</param> /// <returns>Returns field values for given DataRow.</returns> protected override Dictionary <string, string> ExtractOptions(DataConnectionWrapper connection, DataRow row) { if (connection == null) { throw new ArgumentNullException("connection"); } if (row == null) { throw new ArgumentNullException("row"); } // Call base to extract fields Dictionary <string, string> result = base.ExtractOptions(connection, row); // Extract server version Version serverVersion = connection.ServerVersion; // For latest version just return base results if (serverVersion == null || serverVersion.Major >= 5) { return(result); } // Add server name result[ServerField] = connection.ServerName; //Extract CREATE DATABASE string createDatabase = GetCreateDatabase(connection, row); if (String.IsNullOrEmpty(createDatabase)) { return(result); } // Extract default character set Parser.ExtractAdvancedFieldToken(result, createDatabase, "DEFAULT CHARACTER SET ", DefaultCharsetField); // If default character set is not extracted, return if (!result.ContainsKey(DefaultCharsetField)) { return(result); } // Extract default collation Parser.ExtractAdvancedFieldToken(result, createDatabase, "COLLATE ", DefaultCollationField); // If default collation is not extracted, use default collation for character set if (!result.ContainsKey(DefaultCollationField)) { // Extract default character set field string defaultCharSet = result[DefaultCharsetField]; // Extract default collation for this character set if (!String.IsNullOrEmpty(defaultCharSet)) { string defaultCollation = connection.GetDefaultCollationForCharacterSet(defaultCharSet); if (!String.IsNullOrEmpty(defaultCollation)) { result[DefaultCollationField] = defaultCollation; } } } // Return result return(result); }
/// <summary> /// Returns string with CREATE TABLE sql for this table. /// </summary> /// <param name="connection">Connection to use to execute query.</param> /// <param name="row">DataRow with information about table.</param> /// <returns>Returns string with CREATE TABLE sql for this table.</returns> private static string GetCreateTableQuery(DataConnectionWrapper connection, DataRow row) { // Extract schema and table name string schemaName = DataInterpreter.GetString(row, Attributes.Schema); string tableName = DataInterpreter.GetString(row, Attributes.Name); if (String.IsNullOrEmpty(schemaName) || String.IsNullOrEmpty(tableName)) { Debug.Fail("Unable to get table or schema name"); return String.Empty; } return GetCreateTableQuery(connection, schemaName, tableName); }
/// <summary> /// Returns string with CREATE TABLE sql for table by gicen schema name and table name. /// </summary> /// <param name="connection">Connection to use to execute query.</param> /// <param name="schemaName">Name of table schema.</param> /// <param name="tableName">Name of the table.</param> /// <returns>Returns string with CREATE TABLE sql for this table.</returns> public static string GetCreateTableQuery(DataConnectionWrapper connection, string schemaName, string tableName) { if (connection == null) throw new ArgumentNullException("connection"); if (String.IsNullOrEmpty(schemaName)) throw new ArgumentException(Resources.Error_EmptyString, "schemaName"); if (String.IsNullOrEmpty(tableName)) throw new ArgumentException(Resources.Error_EmptyString, "tableName"); // Build SHOW CREATE TABLE table StringBuilder query = new StringBuilder(); query.Append("SHOW CREATE TABLE "); QueryBuilder.WriteIdentifier(schemaName, tableName, query); // Execute query and check table IDataReader reader = connection.ExecuteReader(query.ToString(), false, CommandBehavior.Default); if (reader == null || !reader.Read()) { Debug.Fail("Failed to read CREATE TABLE query!"); return String.Empty; } // Extract result string result = reader.GetString(1); reader.Close(); return result; }
protected override DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); if (connection.ServerVersion != null && RequiredVersion > connection.ServerVersion) // This object requires a higher version of the MySql Server return new DataTable(); DbConnection conn = (DbConnection)connection.Connection.GetLockedProviderObject(); string[] rest = restrictions == null ? null : new string[restrictions.Length]; if (rest != null) for (int x = 0; x < rest.Length; x++) if (restrictions[x] != null) rest[x] = restrictions[x].ToString(); DataTable dt = conn.GetSchema("Procedures With Parameters", rest); connection.Connection.UnlockProviderObject(); return dt; }
/// <summary> /// Exdents table data with additional information. Base implementation adds /// attributes of this database object /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="table">Table with data to extend.</param> protected virtual void ExtendData(DataConnectionWrapper connection, DataTable table) { if (connection == null) { throw new ArgumentNullException("connection"); } if (table == null) { throw new ArgumentNullException("table"); } if (Fields == null || Fields.Count <= 0) { // No known fields return; } // Add columns for fields Debug.Assert(table.Columns != null, "Table has empty column collection!"); Dictionary <string, FieldAttribute> added = new Dictionary <string, FieldAttribute>(); foreach (KeyValuePair <string, FieldAttribute> field in Fields) { // If column is already exists, skip it if (table.Columns.Contains(field.Key)) { continue; } // Add column for field AddFieldColumn(table, field.Key, field.Value.FieldType); // Add entry to added dictionary added[field.Key] = field.Value; } // Calculate field values for each row Dictionary <string, string> fieldValues; foreach (DataRow row in table.Rows) { // Parsing field string fieldValues = ExtractOptions(connection, row); if (fieldValues == null || fieldValues.Count <= 0) { continue; } // Adding a field foreach (KeyValuePair <string, FieldAttribute> field in added) { // Skip empty option names and columns which was in result before option adding. if (string.IsNullOrEmpty(field.Value.OptionName)) { continue; } AddFieldValue(row, field.Key, field.Value.OptionName, field.Value.FieldType, fieldValues); } } }
/// <summary> /// Returns CREATE DATABASE statement for given schema. /// </summary> /// <param name="connection">Connection to use to execute query.</param> /// <param name="schema">DataRow with information about schema.</param> /// <returns>Returns CREATE DATABASE statement for given schema.</returns> private string GetCreateDatabase(DataConnectionWrapper connection, DataRow schema) { // Extract schema and table name string schemaName = DataInterpreter.GetString(schema, Attributes.Schema); if (String.IsNullOrEmpty(schemaName)) { Debug.Fail("Unable to get schema name"); return String.Empty; } // Build SHOW CREATE DATABASE StringBuilder query = new StringBuilder(); query.Append("SHOW CREATE DATABASE "); QueryBuilder.WriteIdentifier(schemaName, query); // Execute query and check result table DataTable createDatabase = connection.ExecuteSelectTable(query.ToString()); if (createDatabase == null || createDatabase.Rows.Count <= 0) { Debug.Fail("Failed to read CREATE TABLE query!"); return String.Empty; } // Extract result string result = DataInterpreter.GetString(createDatabase.Rows[0], "Create Database"); // Dispose table and exit createDatabase.Dispose(); return result; }
/// <summary> /// Enumerates database object of given type with given restrictions into /// DataTable. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="typeName">The type name for objects to be enumerated</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns> /// Returns DataTable which contains all database objects of given type which /// satisfy given restrictions. /// </returns> public static DataTable EnumerateObjects(DataConnectionWrapper connection, string typeName, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); if (typeName == null) throw new ArgumentNullException("typeName"); // Get object descriptor for given type ObjectDescriptor descriptor = ObjectDescriptorFactory.Instance.CreateDescriptor(typeName) as ObjectDescriptor; if (descriptor == null) { Debug.Fail("Unsupported object type '" + typeName + "'"); throw new NotSupportedException(String.Format( CultureInfo.CurrentCulture, Resources.Error_ObjectTypeNotSupported, typeName)); } // Read objects DataTable result = descriptor.ReadTable(connection, restrictions, sort); if (result == null) { Debug.Fail("Failed to read data!"); return null; } // Perform post-processing descriptor.PostProcessData(connection, result); result.AcceptChanges(); // Return result return result; }
/// <summary> /// Reads table with Database Objects which satisfy given restriction. Base implementation /// uses direct SQL query to the INFORMATION_SCHEMA. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <param name="sort">Sort expresion to append after ORDER BY clause.</param> /// <returns>Returns table with Database Objects which satisfy given restriction.</returns> protected virtual DataTable ReadTable(DataConnectionWrapper connection, object[] restrictions, string sort) { if (connection == null) throw new ArgumentNullException("connection"); if (connection.ServerVersion != null && RequiredVersion > connection.ServerVersion) // This object requires a higher version of the MySql Server return new DataTable(); return connection.ExecuteSelectTable(BuildEnumerateSql(connection, restrictions, sort)); }
/// <summary> /// Completes identifier for new object. Last element of id array considered as the name of new object. This /// method sequentially generates new names in form {template}{N} and checks for existing object with same name. /// To check it this method tries to enumerate objects with restriction to whole id. /// </summary> /// <param name="hierarchy">Server explorer facade object used to check for existen objects.</param> /// <param name="typeName">Object type name.</param> /// <param name="id">Array with object identifier.</param> /// <param name="template">Template for the new object identifier.</param> public static void CompleteNewObjectID(ServerExplorerFacade hierarchy, string typeName, ref object[] id, string template) { if (hierarchy == null) { throw new ArgumentNullException("hierarchy"); } if (typeName == null) { throw new ArgumentNullException("typeName"); } if (id == null) { throw new ArgumentNullException("id"); } if (String.IsNullOrEmpty(template)) { throw new ArgumentException(Resources.Error_EmptyString, "template"); } // Retrieve connection information DataConnectionWrapper connection = hierarchy.Connection; Debug.Assert(connection != null, "Empty connection object!"); if (connection == null) { return; } // Calculate "name" part of identifier (it is the last part) int nameIdPart = id.Length - 1; Debug.Assert(nameIdPart >= 0, "Could not complete empty identifier!"); if (nameIdPart < 0) { return; } // Initialize search context int objectIndex = 0; DataTable objectTable = null; bool objectsFounded = false; // Generate object name in <typeName><N> style do { // Build exact identifier id[nameIdPart] = template + (++objectIndex).ToString(CultureInfo.InvariantCulture); objectsFounded = false; try { // Look for exisiting object with this identifier objectTable = EnumerateObjects(connection, typeName, id, null); objectsFounded = objectTable != null && objectTable.Rows != null && objectTable.Rows.Count > 0; } finally { // Release resources if (objectTable != null) { objectTable.Dispose(); } objectTable = null; } // Look for registered document (may be second new object) objectsFounded = objectsFounded || hierarchy.HasDocument(typeName, id); } // Trying while objects are exists and objectIndex less when MaxObjectIndex while (objectsFounded && objectIndex < MaxObjectIndex); }
/// <summary> /// Enumerates database object of given type with given restrictions into /// DataTable. /// </summary> /// <param name="connection">The DataConnectionWrapper to be used for enumeration.</param> /// <param name="typeName">The type name for objects to be enumerated</param> /// <param name="restrictions">The restrictions to be putted on the retrieved objects set.</param> /// <returns> /// Returns DataTable which contains all database objects of given type which /// satisfy given restrictions. /// </returns> public static DataTable EnumerateObjects(DataConnectionWrapper connection, string typeName, object[] restrictions) { if (connection == null) throw new ArgumentNullException("connection"); if (typeName == null) throw new ArgumentNullException("typeName"); return EnumerateObjects(connection, typeName, restrictions, null); }