/// <summary> /// Creates new stored function identifier template without name part. /// </summary> /// <param name="hierarchy">Server explorer facade object to be used for Server Explorer hierarchy interaction.</param> /// <param name="typeName">Object type name to create identifier.</param> /// <returns>Returns new stored function identifier template without name part.</returns> protected override object[] CreateNewIDBase(ServerExplorerFacade hierarchy, string typeName) { if (hierarchy == null) { throw new ArgumentNullException("hierarchy"); } if (typeName == null) { throw new ArgumentNullException("typeName"); } // Only stored procedures are supported if (!DataInterpreter.CompareInvariant(typeName, StoredProcDescriptor.TypeName)) { throw new NotSupportedException(String.Format( CultureInfo.CurrentCulture, Resources.Error_ObjectTypeNotSupported, typeName)); } // Get default schema string schema = hierarchy.Connection.Schema; Debug.Assert(!String.IsNullOrEmpty(schema), "Failed to retrive schema name!"); if (schema == null) { return(null); } return(new object[] { null, schema, null }); }
/// <summary> /// Creates a new user defined function identifier template /// </summary> /// <param name="hierarchy">A server explorer facade object to interact with /// Server Explorer hierarchy</param> /// <param name="typeName">An object type name to create</param> /// <returns>Returns a new user defined function identifier template</returns> protected override object[] CreateNewIDBase(ServerExplorerFacade hierarchy, string typeName) { if (hierarchy == null) { throw new ArgumentNullException("hierarchy"); } if (typeName == null) { throw new ArgumentNullException("typeName"); } // Checking a type name if (!DataInterpreter.CompareInvariant(typeName, UdfDescriptor.TypeName)) { throw new NotSupportedException( String.Format( CultureInfo.CurrentCulture, Resources.Error_ObjectTypeNotSupported, typeName) ); } // Get a default schema string schema = hierarchy.Connection.Schema; if (schema == null) { return(null); } return(new object[] { null, null }); }
/// <summary> /// Fills available values for index comboboxes /// </summary> private void FillComboboxes() { // Fill index kind combobox indexKindSelect.Tag = Index.IndexKind; FillCombobox(indexKindSelect, Document.GetSupportedIndexKinds()); // If indexes are not supported at all, disable add button bool enabled = indexKindSelect.Items.Count > 0; addButton.Enabled = enabled; // If selected index is primary key, add it to the list of available kinds and select if (DataInterpreter.CompareInvariant(SelectedIndexName, IndexDescriptor.PRIMARY)) { indexKindSelect.Items.Add(IndexDescriptor.PRIMARY); indexKindSelect.SelectedItem = IndexDescriptor.PRIMARY; } // Fill index types indexTypeSelect.Tag = Index.IndexType; FillCombobox(indexTypeSelect, Document.GetSupportedIndexTypes()); // Disable combobox if only one type is supported indexTypeSelect.Enabled = indexTypeSelect.Items.Count > 1; }
/// <summary> /// Handles mouse movements and makes checkboxes hot. /// </summary> /// <param name="e">Makes checkboses hot.</param> protected override void OnMouseMove(DataGridViewCellMouseEventArgs e) { if (this.DataGridView == null || e == null || e.RowIndex < 0 || e.RowIndex >= this.DataGridView.RowCount) { return; } // Get hot flag name string hotFlag = GetHotFlagName(e.Location, e.RowIndex); // Skip if nothing changed if (DataInterpreter.CompareInvariant(hotItem, hotFlag)) { base.OnMouseMove(e); return; } // Store old hot item string oldHotItem = hotItem; // Store new hot item hotItem = hotFlag; // Invalidate old hot item, if any InvalidateItem(e.ColumnIndex, e.RowIndex, oldHotItem); // Invalidate new hot item, if any InvalidateItem(e.ColumnIndex, e.RowIndex, hotItem); }
/// <summary> /// Returns true if given engine has status. /// </summary> /// <param name="engine">Engine name to check.</param> /// <returns>Returns true if given engine has status.</returns> private bool HasStatus(string engine) { foreach (string candidate in HasStatusList) { if (DataInterpreter.CompareInvariant(engine, candidate)) { return(true); } } return(false); }
/// <summary> /// Fetches data from the results of the SHOW INDEX FROM query to the /// DataTable with database objects descriptions. /// </summary> /// <param name="restrictions">Restricton to apply to the read objects.</param> /// <param name="table">DataRow with table descriptions for which indexes are enumerated.</param> /// <param name="indexes">DataTable with results of the SHOW INDEX FROM.</param> /// <param name="result">DataTable to fill with data.</param> protected virtual void FetchData(object[] restrictions, DataRow table, DataTable indexes, DataTable result) { if (table == null) { throw new ArgumentNullException("table"); } if (indexes == null) { throw new ArgumentNullException("indexes"); } if (result == null) { throw new ArgumentNullException("result"); } // Iterate through results of SHOW INDEX FROM foreach (DataRow index in indexes.Rows) { // Only first columns should be considered if (DataInterpreter.GetInt(index, SeqInIndex) != 1) { continue; } // Apply restrictions on the index name, if any if (!CheckIndexName(restrictions, index)) { continue; } // Create new index row DataRow row = result.NewRow(); // Fill row with data DataInterpreter.SetValueIfChanged(row, Attributes.Database, null); DataInterpreter.SetValueIfChanged(row, Attributes.Schema, table[TableDescriptor.Attributes.Schema]); DataInterpreter.SetValueIfChanged(row, Attributes.Table, index[Table]); DataInterpreter.SetValueIfChanged(row, Attributes.Name, index[KeyName]); DataInterpreter.SetValueIfChanged(row, Attributes.Unique, DataInterpreter.GetInt(index, NonUnique) == 0 ? DataInterpreter.True : DataInterpreter.False); DataInterpreter.SetValueIfChanged(row, Attributes.Primary, DataInterpreter.CompareInvariant(DataInterpreter.GetStringNotNull(index, KeyName), PRIMARY) ? DataInterpreter.True : DataInterpreter.False); DataInterpreter.SetValueIfChanged(row, Attributes.IndexType, index[IndexType]); // Add filled index row to the results table result.Rows.Add(row); } }
/// <summary> /// Fills details view with data for selected index /// </summary> private void FillSelectedIndexView() { // If selected index is empty, reset view and exit if (SelectedIndex == null) { ResetSelectedIndexView(); return; } // Lock selected index updates lockUpdate = true; // Fill comboboxes FillComboboxes(); // Fill index name indexNameText.DataSource = SelectedIndex; // If index is primary, need to disable combo-boxes and text boxes bool enable = !DataInterpreter.CompareInvariant(SelectedIndexName, IndexDescriptor.PRIMARY); indexNameText.Enabled = enable; indexKindSelect.Enabled = enable; indexTypeSelect.Enabled = indexTypeSelect.Enabled && enable; // If not enabled, there is no value for index kind to select and we should add it if (!enable && !indexKindSelect.Items.Contains(IndexDescriptor.PRIMARY)) { indexKindSelect.Items.Add(IndexDescriptor.PRIMARY); } // In other case PRIMARY is not allowed else if (indexKindSelect.Items.Contains(IndexDescriptor.PRIMARY)) { indexKindSelect.Items.Remove(IndexDescriptor.PRIMARY); } // Enable index settings indexSettingsGroup.Enabled = true; // Attach grid view to filtered datasource AttachIndexColumns(); // Select index kind and type indexKindSelect.SelectedItem = SelectedIndex[Index.IndexKind]; indexTypeSelect.SelectedItem = SelectedIndex[Index.IndexType]; // Unlock selected index updates lockUpdate = false; }
/// <summary> /// Validates a cell of the columns grid /// </summary> private void OnCellValidating(object sender, DataGridViewCellValidatingEventArgs e) { // Checking only column names if (e.ColumnIndex != columnNameColumn.Index) { return; } // Getting a cell value DataGridViewCell cell = columnsDataGrid[e.ColumnIndex, e.RowIndex]; string cellValue = cell.EditedFormattedValue as string; // A column name can't be empty if (string.IsNullOrEmpty(cellValue)) { e.Cancel = true; string errorMessage = String.Format(Resources.Error_EmptyColumnName, Document.Name); UIHelper.ShowError(errorMessage); isValid = false; return; } // Checking if this cell name duplicates another column name foreach (DataGridViewRow row in columnsDataGrid.Rows) { // Skip current row if (row.Index == e.RowIndex) { continue; } // Extract column name string columnName = row.Cells[e.ColumnIndex].Value as string; if (string.IsNullOrEmpty(columnName)) { continue; } if (DataInterpreter.CompareInvariant(cellValue, columnName)) { e.Cancel = true; string errorMessage = String.Format(Resources.Error_DuplicateColumnName, cellValue); UIHelper.ShowError(errorMessage); isValid = false; return; } } }
/// <summary> /// Extracts information about all availabel table engines from the DataTable. /// </summary> /// <param name="table">DataTable object with data</param> private void FillTableEngines(DataTable table) { // Iterate through all engines foreach (DataRow engine in table.Rows) { // Extract values string name = DataInterpreter.GetString(engine, EngineDescriptor.Attributes.Name); SqlBoolean isSupported = DataInterpreter.GetSqlBool(engine, EngineDescriptor.Attributes.IsSupported); if (engine["Support"].Equals("DISABLED")) { isSupported = false; } // Validate name if (String.IsNullOrEmpty(name)) { Debug.Fail("Empty engine name!"); continue; } // Check if engine is not supported if (isSupported.IsFalse) { continue; } // Replacing MRG_MyISAM by more readable MERGE if (DataInterpreter.CompareInvariant(name, TableDescriptor.MRG_MyISAM)) { name = TableDescriptor.MERGE; } // Default engine founded (not YES and not NO - DEFAULT) if (isSupported.IsNull) { Debug.Assert(String.IsNullOrEmpty(defaultEngineVal), "Duplicated default engine!"); defaultEngineVal = name; } // Add engine to collaection if (!enginesList.Contains(name)) { enginesList.Add(name); } } }
/// <summary> /// Creates a query for creation or alteration of a view /// </summary> /// <param name="sb">StringBuilder to write the query in</param> /// <param name="actionName">The name of the requested action</param> private void CreateQuery(StringBuilder sb, string actionName) { // Adding the name of the action sb.Append(actionName); // Adding an algorithm if (Algorithm != Algorithms.UNDEFINED) { sb.Append(" ALGORITHM = "); sb.Append(Algorithm.ToString()); } // Adding definer if not current user string definer = DataInterpreter.GetStringNotNull(Attributes, View.Definer); if (!DataInterpreter.CompareInvariant(definer, CurretnUser)) { QueryBuilder.WriteUserNameIfNotEmpty(definer, " DEFINER = ", sb); } // Adding security type, if are not empty QueryBuilder.WriteIfNotEmptyString(Attributes, View.SecurityType, " SQL SECURITY ", sb, false); // Adding definition of a view sb.Append(" VIEW "); QueryBuilder.WriteIdentifier(Attributes, View.Name, sb); sb.Append(" AS "); sb.AppendLine(); QueryBuilder.WriteValue(Attributes, View.Definition, sb, false); // Adding check options if (CheckOption != CheckOptions.NONE) { sb.AppendLine(); sb.Append(" WITH "); sb.Append(CheckOption.ToString()); sb.Append(" CHECK OPTION"); } }
/// <summary> /// Returns identifier of the object for the given node. /// </summary> /// <param name="hierarchy">Server explorer facade object to be used for Server Explorer hierarchy interaction.</param> /// <param name="item">Item identifier.</param> /// <returns>Returns array with multipart identifier for the object.</returns> protected override object[] GetObjectID(ServerExplorerFacade hierarchy, string typeName, int item) { if (hierarchy == null) { throw new ArgumentNullException("hierarchy"); } if (item < 0) { throw new ArgumentOutOfRangeException("item"); } if (typeName == null) { throw new ArgumentNullException("typeName"); } // If this is not a table or a view, data editing is not supported. if (!DataInterpreter.CompareInvariant(typeName, TableDataDescriptor.TypeName)) { return(null); } // ID is the object ID of the hierarchy item return(hierarchy.GetObjectIdentifier(item)); }
/// <summary> /// Checks object type for the given node (must be Table or View) and returns TableData /// it if checking succeeds. /// </summary> /// <param name="hierarchy">Server explorer facade object to be used for Server Explorer hierarchy interaction.</param> /// <param name="item">Item identifier.</param> /// <returns> /// Returns TableData if object type name of given hierarchy item is Table or View. /// Otherwize returns null. /// </returns> protected override string GetObjectType(ServerExplorerFacade hierarchy, int item) { if (hierarchy == null) { throw new ArgumentNullException("hierarchy"); } if (item < 0) { throw new ArgumentOutOfRangeException("item"); } // Get type of the current node string typeName = hierarchy.GetObjectType(item); // If this is a table or a view, data editing is supported. if (DataInterpreter.CompareInvariant(typeName, TableDescriptor.TypeName) || DataInterpreter.CompareInvariant(typeName, ViewDescriptor.TypeName)) { return(TableDataDescriptor.TypeName); } // Else data editing is not supported return(null); }
/// <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> /// Paint single flags item. /// </summary> /// <param name="graphics">The Graphics used to paint the DataGridViewCell.</param> /// <param name="checkBoxBounds">Rectangel that contains the bounds for checkbox</param> /// <param name="cellStyle">A DataGridViewCellStyle that contains formatting and style information about the cell.</param> /// <param name="text">Text of item to paint.</param> /// <param name="state">Check state of item to paint.</param> /// <param name="paint">True if check box should be painted.</param> /// <returns>Returns the end (right coordinate) of the drawed checkbox.</returns> private int PaintItem(Graphics graphics, Rectangle checkBoxBounds, DataGridViewCellStyle cellStyle, string text, bool state, bool paint) { //Calculate check box location. Point glyphLocation = new Point(checkBoxBounds.Left + CheckBoxMargin, checkBoxBounds.Top); // Initial flags to use for text in checkbox. TextFormatFlags flags = TextFormatFlags.SingleLine | TextFormatFlags.EndEllipsis | TextFormatFlags.PreserveGraphicsClipping | TextFormatFlags.NoPrefix; // Determine if should paint as hot flag bool isHot = DataInterpreter.CompareInvariant(text, hotItem); //Trace.WriteLine("Item " + text + " " + isHot.ToString()); //Trace.WriteLine("Hot item " + hotItem); CheckBoxState cbState = state ? (isHot ? CheckBoxState.CheckedHot : CheckBoxState.CheckedNormal) : (isHot ? CheckBoxState.UncheckedHot : CheckBoxState.UncheckedNormal); // Calculate check box glyph size. Size checkBoxSize = CheckBoxRenderer.GetGlyphSize(graphics, cbState); // Apply alingment switch (cellStyle.Alignment) { case DataGridViewContentAlignment.BottomCenter: glyphLocation.Y = checkBoxBounds.Bottom; flags |= TextFormatFlags.Bottom | TextFormatFlags.HorizontalCenter; break; case DataGridViewContentAlignment.BottomLeft: glyphLocation.Y = checkBoxBounds.Bottom; flags |= TextFormatFlags.Bottom | TextFormatFlags.Left; break; case DataGridViewContentAlignment.BottomRight: glyphLocation.Y = checkBoxBounds.Bottom; flags |= TextFormatFlags.Bottom | TextFormatFlags.Right; break; case DataGridViewContentAlignment.MiddleCenter: glyphLocation.Y = checkBoxBounds.Top + (checkBoxBounds.Height - checkBoxSize.Height) / 2; flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter; break; case DataGridViewContentAlignment.MiddleLeft: glyphLocation.Y = checkBoxBounds.Top + (checkBoxBounds.Height - checkBoxSize.Height) / 2; flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Left; break; case DataGridViewContentAlignment.MiddleRight: glyphLocation.Y = checkBoxBounds.Top + (checkBoxBounds.Height - checkBoxSize.Height) / 2; flags |= TextFormatFlags.VerticalCenter | TextFormatFlags.Right; break; case DataGridViewContentAlignment.TopCenter: glyphLocation.Y = checkBoxBounds.Top; flags |= TextFormatFlags.Top | TextFormatFlags.HorizontalCenter; break; case DataGridViewContentAlignment.TopLeft: glyphLocation.Y = checkBoxBounds.Top; flags |= TextFormatFlags.Top | TextFormatFlags.Left; break; case DataGridViewContentAlignment.TopRight: glyphLocation.Y = checkBoxBounds.Top; flags |= TextFormatFlags.Top | TextFormatFlags.Right; break; default: glyphLocation.Y = checkBoxBounds.Top; flags |= TextFormatFlags.Top | TextFormatFlags.Left; break; } // Add check boxe to the list checkboxes.Add(text, new Rectangle(glyphLocation, checkBoxSize)); // Calculate bounds for text Rectangle textBounds = new Rectangle( // Draw text after glyph plus small margin. checkBoxBounds.Left + 2 * CheckBoxMargin + checkBoxSize.Width, checkBoxBounds.Top, checkBoxBounds.Width - (2 * CheckBoxMargin + checkBoxSize.Width), checkBoxBounds.Height); // Darw checkbox only if we should to draw it and have enought space for glyph // and text if (paint && checkBoxBounds.Height >= checkBoxSize.Height && checkBoxBounds.Height >= cellStyle.Font.Height) { using (Region clipRegion = graphics.Clip) { // Draw checkbox CheckBoxRenderer.DrawCheckBox(graphics, glyphLocation, textBounds, text, cellStyle.Font, flags, false, cbState); graphics.Clip = clipRegion; } } // Calculate and return right coordinate for drawed checkbox with margin return(checkBoxSize.Width + TextRenderer.MeasureText(text, cellStyle.Font).Width + CheckBoxMargin); }
/// <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> /// Reads one action flag and initialize proper field. /// </summary> /// <param name="sql">String with CREATE TABLE script.</param> /// <param name="pos">Position of the field to read in the string.</param> /// <param name="fields">Dictionary with fields to right to.</param> /// <returns>Returns read value.</returns> private static string ReadAndFillAction(string sql, int pos, Dictionary <string, string> fields) { // Read field name from sql string token = Parser.ExtractToken(sql, pos); if (token == null) { return(null); } // Select field name for dictionary string fieldName = null; if (DataInterpreter.CompareInvariant(token, Delete)) { fieldName = OnDeleteField; } if (DataInterpreter.CompareInvariant(token, Update)) { fieldName = OnUpdateField; } // Check if field recognized if (fieldName == null) { return(null); } // Read value from sql (note that DELETE and UPDATE has the same length) token = Parser.ExtractToken(sql, pos + Delete.Length + 1); // Determine value string value = null; if (DataInterpreter.CompareInvariant(token, RESTRICT)) { value = RESTRICT; } if (DataInterpreter.CompareInvariant(token, CASCADE)) { value = CASCADE; } if (DataInterpreter.CompareInvariant(token, "SET")) { value = SETNULL; } if (DataInterpreter.CompareInvariant(token, "NO")) { value = NOACTION; } // Check if value recognized if (value == null) { return(null); } // Set field and return value fields[fieldName] = value; return(value); }
/// <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); }