/// <summary> /// Converts from <see cref="CompareOptions"/> to <see cref="UnicodeIndexFlags"/>. /// </summary> /// <param name="options">The value to convert.</param> /// <returns>A <see cref="UnicodeIndexFlags"/> value equivalent to <paramref name="options"/>.</returns> /// <exception cref="System.ArgumentException">CompareOptions.Ordinal is not supported;compareOptions</exception> internal static UnicodeIndexFlags UnicodeFlagsFromCompareOptions(CompareOptions options) { UnicodeIndexFlags unicodeflags = UnicodeIndexFlags.None; if (IsCompareOptionSet(options, CompareOptions.IgnoreCase)) { unicodeflags |= UnicodeIndexFlags.CaseInsensitive; } if (IsCompareOptionSet(options, CompareOptions.IgnoreKanaType)) { unicodeflags |= UnicodeIndexFlags.KanaInsensitive; } if (IsCompareOptionSet(options, CompareOptions.IgnoreNonSpace)) { unicodeflags |= UnicodeIndexFlags.AccentInsensitive; } if (IsCompareOptionSet(options, CompareOptions.IgnoreSymbols)) { unicodeflags |= UnicodeIndexFlags.IgnoreSymbols; } if (IsCompareOptionSet(options, CompareOptions.IgnoreWidth)) { unicodeflags |= UnicodeIndexFlags.WidthInsensitive; } if (IsCompareOptionSet(options, CompareOptions.StringSort)) { unicodeflags |= UnicodeIndexFlags.StringSort; } if (IsCompareOptionSet(options, CompareOptions.Ordinal)) { throw new ArgumentException("CompareOptions.Ordinal is not supported", "compareOptions"); } return(unicodeflags); }
/// <summary> /// Converts unicodeIndexFlags to a ulong, suitable for dwMapFlags. /// </summary> /// <param name="unicodeIndexFlags">A UnicodeIndexFlags value.</param> /// <returns>A value suitable for calling by LCMapString.</returns> internal static uint MapFlagsFromUnicodeIndexFlags(UnicodeIndexFlags unicodeIndexFlags) { return((uint)unicodeIndexFlags); }
/// <summary> /// Makes the <see cref="JET_OPENTEMPORARYTABLE"/> object to later open it. /// </summary> /// <param name="tableDefinition">The table definition.</param> /// <returns>The newly created <see cref="JET_OPENTEMPORARYTABLE"/> object.</returns> private JET_OPENTEMPORARYTABLE MakeOpenTemporaryTable(TableDefinition tableDefinition) { JET_OPENTEMPORARYTABLE openTemporaryTable = new JET_OPENTEMPORARYTABLE(); // allocate room for our columns int currentColumndef = 0; openTemporaryTable.ccolumn = tableDefinition.Columns.Count; openTemporaryTable.prgcolumndef = new JET_COLUMNDEF[openTemporaryTable.ccolumn]; openTemporaryTable.prgcolumnid = new JET_COLUMNID[openTemporaryTable.ccolumn]; for (int coldef = 0; coldef < openTemporaryTable.ccolumn; ++coldef) { openTemporaryTable.prgcolumndef[coldef] = new JET_COLUMNDEF(); } // first, collect all the key columns in order and put them as the // first columndefs. we have to do this to guarantee that the TT // is sorted properly foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { foreach (KeyColumn keyColumn in indexDefinition.KeyColumns) { ColumnDefinition columnDefinition = tableDefinition.Columns[keyColumn.Name]; openTemporaryTable.prgcolumndef[currentColumndef].coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition); openTemporaryTable.prgcolumndef[currentColumndef].cp = JET_CP.Unicode; openTemporaryTable.prgcolumndef[currentColumndef].cbMax = columnDefinition.MaxLength; openTemporaryTable.prgcolumndef[currentColumndef].grbit = (ColumndefGrbit)columnDefinition.Flags | ColumndefGrbit.TTKey | (keyColumn.IsAscending ? ColumndefGrbit.None : ColumndefGrbit.TTDescending); currentColumndef++; } } // next collect the rest of the columns and put them after the key // columns, skipping over the columns we already added foreach (ColumnDefinition columnDefinition in tableDefinition.Columns) { bool alreadyAdded = false; foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { foreach (KeyColumn keyColumn in indexDefinition.KeyColumns) { if (keyColumn.Name.ToLower(CultureInfo.InvariantCulture) == columnDefinition.Name.ToLower(CultureInfo.InvariantCulture)) { alreadyAdded = true; } } } if (!alreadyAdded) { openTemporaryTable.prgcolumndef[currentColumndef].coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition); openTemporaryTable.prgcolumndef[currentColumndef].cp = JET_CP.Unicode; openTemporaryTable.prgcolumndef[currentColumndef].cbMax = columnDefinition.MaxLength; openTemporaryTable.prgcolumndef[currentColumndef].grbit = Converter.ColumndefGrbitFromColumnFlags(columnDefinition.Flags); currentColumndef++; } } // set the index flags foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { openTemporaryTable.pidxunicode = new JET_UNICODEINDEX(); openTemporaryTable.pidxunicode.lcid = indexDefinition.CultureInfo.LCID; UnicodeIndexFlags unicodeIndexFlags = Converter.UnicodeFlagsFromCompareOptions(indexDefinition.CompareOptions); openTemporaryTable.pidxunicode.dwMapFlags = Converter.MapFlagsFromUnicodeIndexFlags(unicodeIndexFlags); } // infer the TT mode of operation and set its grbits accordingly bool haveColumnWithLongValue = false; foreach (ColumnDefinition columnDefinition in tableDefinition.Columns) { JET_coltyp coltyp = DatabaseCommon.ColtypFromColumnDefinition(columnDefinition); if (coltyp == JET_coltyp.LongText || coltyp == JET_coltyp.LongBinary) { haveColumnWithLongValue = true; } } bool haveIndexWithSortNullsHigh = false; foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { if ((indexDefinition.Flags & IndexFlags.SortNullsHigh) != 0) { haveIndexWithSortNullsHigh = true; } } if (tableDefinition.Type == TableType.Sort) { foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { if ((indexDefinition.Flags & (IndexFlags.Unique | IndexFlags.Primary)) == 0) { // External Sort without duplicate removal openTemporaryTable.grbit = Server2003Grbits.ForwardOnly | (haveColumnWithLongValue ? Windows7Grbits.IntrinsicLVsOnly : TempTableGrbit.None) | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } else { // External Sort TT with deferred duplicate removal openTemporaryTable.grbit = TempTableGrbit.Unique | (haveColumnWithLongValue ? Windows7Grbits.IntrinsicLVsOnly : TempTableGrbit.None) | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } } } else if (tableDefinition.Type == TableType.PreSortTemporary) { // Pre-sorted B+ Tree TT with deferred duplicate removal openTemporaryTable.grbit = TempTableGrbit.Indexed | TempTableGrbit.Unique | TempTableGrbit.Updatable | TempTableGrbit.Scrollable | (haveColumnWithLongValue ? Windows7Grbits.IntrinsicLVsOnly : TempTableGrbit.None) | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } else if (tableDefinition.Type == TableType.Temporary) { if (tableDefinition.Indices.Count != 0) { // B+ Tree TT with immediate duplicate removal openTemporaryTable.grbit = TempTableGrbit.Indexed | TempTableGrbit.Unique | TempTableGrbit.Updatable | TempTableGrbit.Scrollable | TempTableGrbit.ForceMaterialization | (haveIndexWithSortNullsHigh ? TempTableGrbit.SortNullsHigh : TempTableGrbit.None); } else { // B+ Tree TT with a sequential index openTemporaryTable.grbit = TempTableGrbit.Updatable | TempTableGrbit.Scrollable; } } // set the key construction parameters for the TT foreach (IndexDefinition indexDefinition in tableDefinition.Indices) { openTemporaryTable.cbKeyMost = indexDefinition.MaxKeyLength; openTemporaryTable.cbVarSegMac = 0; } // return the constructed JET_OPENTEMPORARYTABLE (whew!) return(openTemporaryTable); }