/// <summary>
 /// Asynchronously mutates a row atomically based on the output of a predicate Reader filter.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="rowKey"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// <para>
 /// This method simply delegates to <see cref="CheckAndMutateRowAsync(CheckAndMutateRowRequest, CallSettings)"/>.
 /// </para>
 /// </remarks>
 /// <param name="tableName">
 /// The unique name of the table to which the conditional mutation should be
 /// applied. Must not be null.
 /// </param>
 /// <param name="rowKey">
 /// The key of the row to which the conditional mutation should be applied.
 /// Must not be empty.
 /// </param>
 /// <param name="predicateFilter">
 /// The filter to be applied to the contents of the specified row. Depending
 /// on whether or not any results are yielded, <paramref name="trueMutations"/> may or may not
 /// be executed. If null, checks that the row contains any values at all.
 /// </param>
 /// <param name="trueMutations">
 /// Changes to be atomically applied to the specified row if <paramref name="predicateFilter"/>
 /// yields at least one cell when applied to <paramref name="rowKey"/>. Entries are applied in
 /// order, meaning that earlier mutations can be masked by later ones.
 /// Must contain at least one entry and at most 100000.  Must not be null, or contain null elements.
 /// </param>
 /// <returns>
 /// The response from trying to mutate the row.
 /// </returns>
 public virtual Task <CheckAndMutateRowResponse> CheckAndMutateRowAsync(
     TableName tableName,
     BigtableByteString rowKey,
     RowFilter predicateFilter,
     params Mutation[] trueMutations) =>
 CheckAndMutateRowAsync(
     CreateCheckAndMutateRowRequest(tableName, rowKey, predicateFilter, trueMutations, falseMutations: null));
        private static CheckAndMutateRowRequest CreateCheckAndMutateRowRequest(
            TableName tableName,
            BigtableByteString rowKey,
            RowFilter predicateFilter,
            IEnumerable <Mutation> trueMutations,
            IEnumerable <Mutation> falseMutations)
        {
            GaxPreconditions.CheckNotNull(tableName, nameof(tableName));
            GaxPreconditions.CheckArgument(rowKey.Length != 0, nameof(rowKey), "The row key must not empty");

            var request = new CheckAndMutateRowRequest
            {
                TableNameAsTableName = tableName,
                RowKey          = rowKey.Value,
                PredicateFilter = predicateFilter,
                TrueMutations   = { Utilities.ValidateCollection(trueMutations, nameof(trueMutations), allowNullCollection: true) },
                FalseMutations  = { Utilities.ValidateCollection(falseMutations, nameof(falseMutations), allowNullCollection: true) }
            };

            GaxPreconditions.CheckArgument(
                request.TrueMutations.Count + request.FalseMutations.Count != 0,
                nameof(trueMutations),
                "There must be at least one mutation.");
            return(request);
        }
 /// <summary>
 /// Asynchronously modifies a row atomically on the server. The method reads the latest existing version
 /// and value from the specified columns and writes a new entry based on
 /// pre-defined read/modify/write rules. The new value for the version is the
 /// greater of the previous value's version or the current server version. The method
 /// returns the new contents of all modified cells.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that the server version is based on the current timestamp since the Unix epoch, so for
 /// columns which are updated using ReadModifyWriteRow, other reads and writes of those columns
 /// should use <see cref="BigtableVersion"/> values constructed from DateTime values, as opposed
 /// to using a custom versioning scheme with 64-bit values.
 /// </para>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="rowKey"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// <para>
 /// This method simply delegates to <see cref="ReadModifyWriteRowAsync(ReadModifyWriteRowRequest, CallSettings)"/>.
 /// </para>
 /// </remarks>
 /// <param name="tableName">
 /// The unique name of the table to which the read/modify/write rules should be
 /// applied. Must not be null.
 /// </param>
 /// <param name="rowKey">
 /// The key of the row to which the read/modify/write rules should be applied.
 /// Must not be empty.
 /// </param>
 /// <param name="rules">
 /// Rules specifying how the specified row's contents are to be transformed
 /// into writes. Entries are applied in order, meaning that earlier rules will
 /// affect the results of later ones.  Must not be null, or contain null
 /// elements.
 /// </param>
 /// <param name="callSettings">
 /// If not null, applies overrides to this RPC call.
 /// </param>
 /// <returns>
 /// The response from modifying the row.
 /// </returns>
 public virtual Task <ReadModifyWriteRowResponse> ReadModifyWriteRowAsync(
     TableName tableName,
     BigtableByteString rowKey,
     IEnumerable <ReadModifyWriteRule> rules,
     CallSettings callSettings = null) =>
 ReadModifyWriteRowAsync(
     CreateReadModifyWriteRowRequest(tableName, rowKey, rules),
     callSettings);
Exemple #4
0
 /// <summary>
 /// Rule specifying that <paramref name="incrementAmount"/> be added to the existing value.
 /// If the targeted cell is unset, it will be treated as containing a zero.
 /// Otherwise, the targeted cell must contain an 8-byte value (interpreted
 /// as a 64-bit big-endian signed integer), or the entire request will fail.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>,
 /// so <paramref name="columnQualifier"/> can be specified using a string as well and
 /// its UTF-8 representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="familyName">
 /// The name of the family to which the read/modify/write should be applied.
 /// Must match `[-_.a-zA-Z0-9]+`
 /// </param>
 /// <param name="columnQualifier">
 /// The qualifier of the column to which the read/modify/write should be
 /// applied. Can be any byte string, including the empty string.
 /// </param>
 /// <param name="incrementAmount">
 /// The amount to increment the existing cell value.
 /// </param>
 /// <returns>
 /// The increment amount rule.
 /// </returns>
 public static ReadModifyWriteRule Increment(
     string familyName, BigtableByteString columnQualifier, long incrementAmount) =>
 new ReadModifyWriteRule
 {
     FamilyName      = Utilities.ValidateFamilyName(familyName),
     ColumnQualifier = columnQualifier.Value,
     IncrementAmount = incrementAmount
 };
Exemple #5
0
 /// <summary>
 /// Rule specifying that <paramref name="appendValue"/> be appended to the existing value.
 /// If the targeted cell is unset, it will be treated as containing the empty string.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>,
 /// so <paramref name="columnQualifier"/> can be specified using a string as well and
 /// its UTF-8 representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="familyName">
 /// The name of the family to which the read/modify/write should be applied.
 /// Must match `[-_.a-zA-Z0-9]+`
 /// </param>
 /// <param name="columnQualifier">
 /// The qualifier of the column to which the read/modify/write should be
 /// applied. Can be any byte string, including the empty string.
 /// </param>
 /// <param name="appendValue">
 /// The value to append to the existing cell value.
 /// </param>
 /// <returns>
 /// The append value rule.
 /// </returns>
 public static ReadModifyWriteRule Append(
     string familyName, BigtableByteString columnQualifier, BigtableByteString appendValue) =>
 new ReadModifyWriteRule
 {
     FamilyName      = Utilities.ValidateFamilyName(familyName),
     ColumnQualifier = columnQualifier.Value,
     AppendValue     = appendValue.Value
 };
 /// <summary>
 /// Asynchronously mutates a row atomically. Cells already present in the row are left
 /// unchanged unless explicitly changed by <paramref name="mutations"/>.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="rowKey"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// <para>
 /// This method simply delegates to <see cref="MutateRowAsync(MutateRowRequest, CallSettings)"/>.
 /// </para>
 /// </remarks>
 /// <param name="tableName">
 /// The unique name of the table to which the mutation should be applied. Must not be null.
 /// </param>
 /// <param name="rowKey">
 /// The key of the row to which the mutation should be applied. Must not be empty.
 /// </param>
 /// <param name="mutations">
 /// Changes to be atomically applied to the specified row. Entries are applied
 /// in order, meaning that earlier mutations can be masked by later ones.
 /// Must contain at least one entry and at most 100000. Must not be null, or contain null
 /// elements.
 /// </param>
 /// <param name="callSettings">
 /// If not null, applies overrides to this RPC call.
 /// </param>
 /// <returns>
 /// The response from mutating the row.
 /// </returns>
 public virtual Task <MutateRowResponse> MutateRowAsync(
     TableName tableName,
     BigtableByteString rowKey,
     IEnumerable <Mutation> mutations,
     CallSettings callSettings = null) =>
 MutateRowAsync(
     CreateMutateRowRequest(tableName, rowKey, mutations),
     callSettings);
 /// <summary>
 /// Mutates a row atomically based on the output of a predicate Reader filter.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="rowKey"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// <para>
 /// This method simply delegates to <see cref="CheckAndMutateRow(CheckAndMutateRowRequest, CallSettings)"/>.
 /// </para>
 /// </remarks>
 /// <param name="tableName">
 /// The unique name of the table to which the conditional mutation should be
 /// applied. Must not be null.
 /// </param>
 /// <param name="rowKey">
 /// The key of the row to which the conditional mutation should be applied.
 /// Must not be empty.
 /// </param>
 /// <param name="predicateFilter">
 /// The filter to be applied to the contents of the specified row. Depending
 /// on whether or not any results are yielded, either <paramref name="trueMutations"/> or
 /// <paramref name="falseMutations"/> will be executed. If null, checks that the row contains
 /// any values at all.
 /// </param>
 /// <param name="trueMutations">
 /// Changes to be atomically applied to the specified row if <paramref name="predicateFilter"/>
 /// yields at least one cell when applied to <paramref name="rowKey"/>. Entries are applied in
 /// order, meaning that earlier mutations can be masked by later ones.
 /// Must contain at least one entry if <paramref name="falseMutations"/> is null or empty, and
 /// at most 100000. Can be null or empty, but must not contain null elements.
 /// </param>
 /// <param name="falseMutations">
 /// Changes to be atomically applied to the specified row if <paramref name="predicateFilter"/>
 /// does not yield any cells when applied to <paramref name="rowKey"/>. Entries are applied in
 /// order, meaning that earlier mutations can be masked by later ones.
 /// Must contain at least one entry if <paramref name="trueMutations"/> is null or empty, and
 /// at most 100000. Can be null or empty, but must not contain null elements.
 /// </param>
 /// <param name="callSettings">
 /// If not null, applies overrides to this RPC call.
 /// </param>
 /// <returns>
 /// The response from trying to mutate the row.
 /// </returns>
 public virtual CheckAndMutateRowResponse CheckAndMutateRow(
     TableName tableName,
     BigtableByteString rowKey,
     RowFilter predicateFilter,
     IEnumerable <Mutation> trueMutations,
     IEnumerable <Mutation> falseMutations,
     CallSettings callSettings = null) =>
 CheckAndMutateRow(
     CreateCheckAndMutateRowRequest(tableName, rowKey, predicateFilter, trueMutations, falseMutations),
     callSettings);
Exemple #8
0
        /// <summary>
        /// Creates a <see cref="MutateRowsRequest.Types.Entry"/> to use with MutateRows requests.
        /// Each Entry is an atomic, ordered set of mutations for a particular row.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="rowKey"/> can
        /// be specified using a string as well and its UTF-8 representations will be used.
        /// </para>
        /// </remarks>
        /// <param name="rowKey">
        /// The key of the row to which the <paramref name="mutations"/> should be applied. Must not be empty.
        /// </param>
        /// <param name="mutations">
        /// Changes to be atomically applied to the specified row. Mutations are
        /// applied in order, meaning that earlier mutations can be masked by
        /// later ones. You must specify at least one mutation. Must not be null, or contain null
        /// elements.
        /// </param>
        /// <returns>The MutateRows entry describing mutations for a single row.</returns>
        /// <seealso cref="BigtableClient.MutateRows(MutateRowsRequest, Api.Gax.Grpc.CallSettings)"/>
        /// <seealso cref="BigtableClient.MutateRows(TableName, MutateRowsRequest.Types.Entry[])"/>
        /// <seealso cref="BigtableClient.MutateRows(TableName, System.Collections.Generic.IEnumerable{MutateRowsRequest.Types.Entry}, Api.Gax.Grpc.CallSettings)"/>
        public static MutateRowsRequest.Types.Entry CreateEntry(BigtableByteString rowKey, params Mutation[] mutations)
        {
            GaxPreconditions.CheckArgument(rowKey.Length != 0, nameof(rowKey), "The row key must not empty");
            var entry = new MutateRowsRequest.Types.Entry
            {
                RowKey    = (ByteString)rowKey,
                Mutations = { Utilities.ValidateCollection(mutations, nameof(mutations)) }
            };

            GaxPreconditions.CheckArgument(
                entry.Mutations.Count != 0, nameof(mutations), "There must be at least one entry.");
            return(entry);
        }
 /// <summary>
 /// Creates a <see cref="Mutation"/> which deletes cells from the specified column, optionally
 /// restricting the deletions to a given version range.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>,
 /// so <paramref name="columnQualifier"/> can be specified using a string as well and
 /// its UTF-8 representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="familyName">
 /// The name of the family from which cells should be deleted.
 /// Must match `[-_.a-zA-Z0-9]+`
 /// </param>
 /// <param name="columnQualifier">
 /// The qualifier of the column from which cells should be deleted.
 /// Can be any byte string, including the empty string.
 /// </param>
 /// <param name="versionRange">
 /// [Optional] The range of versions within which cells should be deleted.
 /// If unspecified, all versions will be deleted.
 /// </param>
 /// <returns>The created Mutation instance.</returns>
 public static Mutation DeleteFromColumn(
     string familyName,
     BigtableByteString columnQualifier,
     BigtableVersionRange versionRange = null) =>
 new Mutation
 {
     DeleteFromColumn = new Mutation.Types.DeleteFromColumn
     {
         FamilyName      = ValidateFamilyName(familyName),
         ColumnQualifier = columnQualifier.Value,
         TimeRange       = versionRange.ToTimestampRange()
     }
 };
 /// <summary>
 /// Creates a <see cref="Mutation"/> which sets the value of the specified cell.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>,
 /// so <paramref name="columnQualifier"/> or <paramref name="value"/> can be specified
 /// using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="familyName">
 /// The name of the family into which new data should be written.
 /// Must match `[-_.a-zA-Z0-9]+`
 /// </param>
 /// <param name="columnQualifier">
 /// The qualifier of the column into which new data should be written.
 /// Can be any byte string, including the empty string.
 /// </param>
 /// <param name="value">
 /// The value to be written into the specified cell.
 /// </param>
 /// <param name="version">
 /// [Optional] The version of the cell into which new data should be written.
 /// If unspecified, the version will be initialized from the current UTC time.
 /// </param>
 /// <returns>The created Mutation instance.</returns>
 public static Mutation SetCell(
     string familyName,
     BigtableByteString columnQualifier,
     BigtableByteString value,
     BigtableVersion?version = null) =>
 new Mutation
 {
     SetCell = new Mutation.Types.SetCell
     {
         FamilyName      = Utilities.ValidateFamilyName(familyName),
         ColumnQualifier = columnQualifier.Value,
         Value           = value.Value,
         TimestampMicros = (version ?? new BigtableVersion(DateTime.UtcNow)).Micros
     }
 };
 /// <summary>
 /// Creates a <see cref="Mutation"/> which sets the value of the specified cell.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>,
 /// so <paramref name="columnQualifier"/> or <paramref name="value"/> can be specified
 /// using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="familyName">
 /// The name of the family into which new data should be written.
 /// Must match `[-_.a-zA-Z0-9]+`
 /// </param>
 /// <param name="columnQualifier">
 /// The qualifier of the column into which new data should be written.
 /// Can be any byte string, including the empty string.
 /// </param>
 /// <param name="value">
 /// The value to be written into the specified cell.
 /// </param>
 /// <param name="version">
 /// [Optional] The version of the cell into which new data should be written.
 /// If unspecified, the version will be initialized from the current UTC time.
 /// </param>
 /// <returns>The created Mutation instance.</returns>
 public static Mutation SetCell(
     string familyName,
     BigtableByteString columnQualifier,
     BigtableByteString value,
     BigtableVersion?version = null) =>
 new Mutation
 {
     SetCell = new Mutation.Types.SetCell
     {
         FamilyName      = ValidateFamilyName(familyName),
         ColumnQualifier = columnQualifier.Value,
         Value           = value.Value,
         TimestampMicros = version.ToTimestampMicros()
     }
 };
        private static ReadModifyWriteRowRequest CreateReadModifyWriteRowRequest(
            TableName tableName,
            BigtableByteString rowKey,
            IEnumerable <ReadModifyWriteRule> rules)
        {
            GaxPreconditions.CheckNotNull(tableName, nameof(tableName));
            GaxPreconditions.CheckArgument(rowKey.Length != 0, nameof(rowKey), "The row key must not empty");

            var request = new ReadModifyWriteRowRequest
            {
                TableNameAsTableName = tableName,
                RowKey = rowKey.Value,
                Rules  = { Utilities.ValidateCollection(rules, nameof(rules)) }
            };

            GaxPreconditions.CheckArgument(
                request.Rules.Count != 0, nameof(rules), "There must be at least one entry.");
            return(request);
        }
        /// <summary>
        /// Asynchronously returns the contents of the requested row, optionally applying the specified Reader filter.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method simply delegates to <see cref="ReadRows(TableName, RowSet, RowFilter, long?, CallSettings)"/>
        /// and takes the single row result or null if no rows are returned.
        /// </para>
        /// </remarks>
        /// <param name="tableName">
        /// The unique name of the table from which to read. Must not be null.
        /// </param>
        /// <param name="rowKey">
        /// The key of the row to read. Must not be empty.
        /// </param>
        /// <param name="filter">
        /// The filter to apply to the contents of the specified row. If null,
        /// reads the entirety of the row.
        /// </param>
        /// <param name="callSettings">
        /// If not null, applies overrides to this RPC call.
        /// </param>
        /// <returns>
        /// The row from the server or null if it does not exist.
        /// </returns>
        public virtual async Task <Row> ReadRowAsync(
            TableName tableName,
            BigtableByteString rowKey,
            RowFilter filter          = null,
            CallSettings callSettings = null)
        {
            GaxPreconditions.CheckNotNull(tableName, nameof(tableName));
            GaxPreconditions.CheckArgument(rowKey.Length != 0, nameof(rowKey), "The row key must not empty");

            var response = ReadRows(
                tableName,
                new RowSet {
                RowKeys = { rowKey.Value }
            },
                filter,
                callSettings: callSettings);

            return(await response.AsAsyncEnumerable().SingleOrDefault().ConfigureAwait(false));
        }
        /// <summary>
        /// Asynchronously returns the contents of the requested row, optionally applying the specified Reader filter.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method simply delegates to <see cref="ReadRows(TableName, RowSet, RowFilter, long?, CallSettings)"/>
        /// and takes the single row result or null if no rows are returned.
        /// </para>
        /// </remarks>
        /// <param name="tableName">
        /// The unique name of the table from which to read. Must not be null.
        /// </param>
        /// <param name="rowKey">
        /// The key of the row to read. Must not be empty.
        /// </param>
        /// <param name="filter">
        /// The filter to apply to the contents of the specified row. If null,
        /// reads the entirety of the row.
        /// </param>
        /// <param name="callSettings">
        /// If not null, applies overrides to this RPC call.
        /// </param>
        /// <returns>
        /// The row from the server or null if it does not exist.
        /// </returns>
        public virtual async Task <Row> ReadRowAsync(
            TableName tableName,
            BigtableByteString rowKey,
            RowFilter filter          = null,
            CallSettings callSettings = null)
        {
            GaxPreconditions.CheckNotNull(tableName, nameof(tableName));
            GaxPreconditions.CheckArgument(rowKey.Length != 0, nameof(rowKey), "The row key must not empty");

            var response = ReadRows(
                tableName,
                new RowSet {
                RowKeys = { rowKey.Value }
            },
                filter,
                callSettings: callSettings);

            // Equivalent to using SingleOrDefaultAsync, but avoids a System.Linq.Async dependency.
            var enumerator = response.GetAsyncEnumerator(default);
Exemple #15
0
            public override RowMergeState HandleChunk(RowAsyncEnumerator owner, CellChunk chunk)
            {
                owner.Assert(chunk.RowKey != null && !chunk.RowKey.IsEmpty, "NewRow must have a rowKey");
                owner.Assert(chunk.FamilyName != null, "NewRow must have a family");
                owner.Assert(chunk.Qualifier != null, "NewRow must have a qualifier");
                owner.Assert(
                    owner._currentCell.Row == null || BigtableByteString.Compare(owner._currentCell.Row.Key, chunk.RowKey) < 0,
                    "NewRow key must be greater than the previous row's");

                // WARNING: owner._currentCell is a struct value. Do not extract as a local (which will make a copy).
                owner._currentCell.Row = new Row {
                    Key = chunk.RowKey
                };
                owner._currentCell.Family    = null;
                owner._currentCell.Column    = null;
                owner._currentCell.Timestamp = 0;
                owner._currentCell.Labels    = null;

                // auto transition
                return(NewCell.Instance.HandleChunk(owner, chunk));
            }
Exemple #16
0
        // TODO: Add additional ValueRange... methods to take start/end values?

        /// <summary>
        /// Creates a new <see cref="RowFilter"/> instance which matches only cells
        /// with values that satisfy the given regular expression.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Note that, since cell values can contain arbitrary bytes, the `\C` escape
        /// sequence must be used if a true wildcard is desired. The `.` character
        /// will not match the new line character `\n`, which may be present in a
        /// binary value.
        /// </para>
        /// <para>
        /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>,
        /// so <paramref name="regex"/> can be specified using a string as well and its UTF-8
        /// representations will be used.
        /// </para>
        /// </remarks>
        /// <param name="regex">
        /// The RE2 regex used to match cell values.
        /// </param>
        /// <returns>The created row filter.</returns>
        public static RowFilter ValueRegex(BigtableByteString regex) =>
        new RowFilter
        {
            ValueRegexFilter = regex.Value
        };
Exemple #17
0
 /// <summary>
 /// Creates a new <see cref="RowFilter"/> instance which matches only cells from
 /// columns whose qualifiers satisfy the given RE2 regex.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that, since column qualifiers can contain arbitrary bytes, the `\C`
 /// escape sequence must be used if a true wildcard is desired. The `.`
 /// character will not match the new line character `\n`, which may be
 /// present in a binary qualifier.
 /// </para>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>,
 /// so <paramref name="regex"/> can be specified using a string as well and its UTF-8
 /// representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="regex">
 /// The RE2 regex used to match column qualifiers.
 /// </param>
 /// <returns>The created row filter.</returns>
 public static RowFilter ColumnQualifierRegex(BigtableByteString regex) =>
 new RowFilter
 {
     ColumnQualifierRegexFilter = regex.Value
 };
 /// <summary>
 /// Returns the contents of the requested row, optionally applying the specified Reader filter.
 /// </summary>
 /// <remarks>
 /// <para>
 /// This method simply delegates to <see cref="ReadRowAsync(TableName, BigtableByteString, RowFilter, CallSettings)"/>.
 /// </para>
 /// </remarks>
 /// <param name="tableName">
 /// The unique name of the table from which to read. Must not be null.
 /// </param>
 /// <param name="rowKey">
 /// The key of the row to read. Must not be empty.
 /// </param>
 /// <param name="filter">
 /// The filter to apply to the contents of the specified row. If null,
 /// reads the entirety of the row.
 /// </param>
 /// <param name="callSettings">
 /// If not null, applies overrides to this RPC call.
 /// </param>
 /// <returns>
 /// The row from the server or null if it does not exist.
 /// </returns>
 public virtual Row ReadRow(
     TableName tableName,
     BigtableByteString rowKey,
     RowFilter filter          = null,
     CallSettings callSettings = null) =>
 Task.Run(() => ReadRowAsync(tableName, rowKey, filter, callSettings)).ResultWithUnwrappedExceptions();
 /// <summary>
 /// Creates a <see cref="RowSet"/> instance from a single row key.
 /// </summary>
 /// <param name="rowKey">
 /// The key of row included in the set.
 /// </param>
 /// <returns>The created set.</returns>
 public static RowSet FromRowKey(BigtableByteString rowKey) =>
 new RowSet
 {
     RowKeys = { rowKey.Value }
 };
 /// <summary>
 /// Asynchronously modifies a row atomically on the server. The method reads the latest existing version
 /// and value from the specified columns and writes a new entry based on
 /// pre-defined read/modify/write rules. The new value for the version is the
 /// greater of the previous value's version or the current server version. The method
 /// returns the new contents of all modified cells.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that the server version is based on the current timestamp since the Unix epoch, so for
 /// columns which are updated using ReadModifyWriteRow, other reads and writes of those columns
 /// should use <see cref="BigtableVersion"/> values constructed from DateTime values, as opposed
 /// to using a custom versioning scheme with 64-bit values.
 /// </para>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="rowKey"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// <para>
 /// This method simply delegates to <see cref="ReadModifyWriteRowAsync(ReadModifyWriteRowRequest, CallSettings)"/>.
 /// </para>
 /// </remarks>
 /// <param name="tableName">
 /// The unique name of the table to which the read/modify/write rules should be
 /// applied. Must not be null.
 /// </param>
 /// <param name="rowKey">
 /// The key of the row to which the read/modify/write rules should be applied.
 /// Must not be empty.
 /// </param>
 /// <param name="rules">
 /// Rules specifying how the specified row's contents are to be transformed
 /// into writes. Entries are applied in order, meaning that earlier rules will
 /// affect the results of later ones. Must not be null, or contain null
 /// elements.
 /// </param>
 /// <returns>
 /// The response from modifying the row.
 /// </returns>
 public virtual Task <ReadModifyWriteRowResponse> ReadModifyWriteRowAsync(
     TableName tableName,
     BigtableByteString rowKey,
     params ReadModifyWriteRule[] rules) =>
 ReadModifyWriteRowAsync(
     CreateReadModifyWriteRowRequest(tableName, rowKey, rules));
 /// <summary>
 /// Creates a new <see cref="RowFilter"/> instance which matches only cells
 /// from columns whose qualifiers match the exact byte string specified.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="value"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="value">
 /// The exact value used to match column qualifiers.
 /// </param>
 /// <returns>The created row filter.</returns>
 public static RowFilter ColumnQualifierExact(BigtableByteString value) =>
 new RowFilter
 {
     ColumnQualifierRegexFilter = Utilities.RegexEscape(value.Value)
 };
 /// <summary>
 /// Asynchronously mutates a row atomically. Cells already present in the row are left
 /// unchanged unless explicitly changed by <paramref name="mutations"/>.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="rowKey"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// <para>
 /// This method simply delegates to <see cref="MutateRowAsync(MutateRowRequest, CallSettings)"/>.
 /// </para>
 /// </remarks>
 /// <param name="tableName">
 /// The unique name of the table to which the mutation should be applied. Must not be null.
 /// </param>
 /// <param name="rowKey">
 /// The key of the row to which the mutation should be applied. Must not be empty.
 /// </param>
 /// <param name="mutations">
 /// Changes to be atomically applied to the specified row. Entries are applied
 /// in order, meaning that earlier mutations can be masked by later ones.
 /// Must contain at least one entry and at most 100000. Must not be null, or contain null
 /// elements.
 /// </param>
 /// <returns>
 /// The response from mutating the row.
 /// </returns>
 public virtual Task <MutateRowResponse> MutateRowAsync(
     TableName tableName,
     BigtableByteString rowKey,
     params Mutation[] mutations) =>
 MutateRowAsync(
     CreateMutateRowRequest(tableName, rowKey, mutations));
 /// <summary>
 /// Creates a new <see cref="RowFilter"/> instance which matches only cells
 /// with values that match the exact byte string specified.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Note that string is implicitly convertible to <see cref="BigtableByteString"/>, so <paramref name="value"/> can
 /// be specified using a string as well and its UTF-8 representations will be used.
 /// </para>
 /// </remarks>
 /// <param name="value">
 /// The exact value used to match cell values.
 /// </param>
 /// <returns>The created row filter.</returns>
 public static RowFilter ValueExact(BigtableByteString value) =>
 new RowFilter
 {
     ValueRegexFilter = Utilities.RegexEscape(value.Value)
 };