From c9c3a06bbe74fb3fb33a2ca12aab34e2a17270a4 Mon Sep 17 00:00:00 2001
From: KK <1985088337@qq.com>
Date: Fri, 16 Oct 2020 18:30:53 +0800
Subject: [PATCH 1/2] =?UTF-8?q?1.=20=E6=B7=BB=E5=8A=A0Standard=E5=BA=93(al?=
=?UTF-8?q?iyun-tablestore-netstandard-sdk.csproj),=E4=BB=A5=E4=BE=BF?=
=?UTF-8?q?=E5=90=8C=E6=97=B6=E6=94=AF=E6=8C=81=EF=BC=88.Net=20Core=20?=
=?UTF-8?q?=E5=92=8C=20.Net=20Framework=EF=BC=89=202.=20=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E6=B5=8B=E8=AF=95=E7=A4=BA=E4=BE=8B=EF=BC=88aliyun-tablestore-?=
=?UTF-8?q?netcore-sdk-sample.csproj=EF=BC=89=EF=BC=8C=E4=BB=8E=E5=8E=9F?=
=?UTF-8?q?=E5=A7=8B=E7=A4=BA=E4=BE=8B=E4=B8=AD=E6=8B=B7=E8=B4=9D=EF=BC=8C?=
=?UTF-8?q?=E5=B9=B6=E5=AE=9E=E9=99=85=E8=BF=90=E8=A1=8C=E6=B5=8B=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
aliyun-tablestore-csharp-sdk.sln | 16 +-
netcore-sample/Config.cs | 31 +
netcore-sample/Program.cs | 56 +
.../Samples/AtomicIncrementSample.cs | 172 +
netcore-sample/Samples/AutoIncrementSample.cs | 90 +
netcore-sample/Samples/ClientInitialize.cs | 31 +
.../Samples/ConditionUpdateSample.cs | 288 +
netcore-sample/Samples/CreateTableSample.cs | 70 +
netcore-sample/Samples/GlobalIndexSample.cs | 233 +
.../Samples/MultiRowReadWriteSample.cs | 397 +
.../Samples/SearchIndexGeoSample.cs | 321 +
.../Samples/SearchIndexPageSample.cs | 212 +
netcore-sample/Samples/SearchIndexSample.cs | 584 +
.../Samples/SingleRowReadWriteSample.cs | 239 +
...liyun-tablestore-netcore-sdk-sample.csproj | 17 +
.../Aliyun/OTS/DataModel/AttributeColumns.cs | 99 +
.../Aliyun/OTS/DataModel/BloomFilterType.cs | 9 +
.../Aliyun/OTS/DataModel/CapacityUnit.cs | 48 +
.../Aliyun/OTS/DataModel/Column.cs | 69 +
.../Aliyun/OTS/DataModel/ColumnValue.cs | 297 +
.../Aliyun/OTS/DataModel/ColumnValueType.cs | 33 +
.../Aliyun/OTS/DataModel/CompareOperator.cs | 7 +
.../Aliyun/OTS/DataModel/Condition.cs | 36 +
.../ConditionalUpdate/ColumnCondition.cs | 7 +
.../ConditionalUpdate/ColumnConditionType.cs | 8 +
.../ConditionalUpdate/CompositeCondition.cs | 54 +
.../ConditionalUpdate/IColumnCondition.cs | 12 +
.../ConditionalUpdate/RelationalCondition.cs | 46 +
.../OTS/DataModel/DefinedColumnSchema.cs | 20 +
.../Aliyun/OTS/DataModel/DefinedColumnType.cs | 15 +
.../Filter/ColumnPaginationFilter.cs | 35 +
.../Filter/CompositeColumnValueFilter.cs | 128 +
.../Aliyun/OTS/DataModel/Filter/FilterType.cs | 10 +
.../Aliyun/OTS/DataModel/Filter/IFilter.cs | 12 +
.../Filter/SingleColumnValueFilter.cs | 93 +
.../Aliyun/OTS/DataModel/IMeasurable.cs | 11 +
netstandard-sdk/Aliyun/OTS/DataModel/IRow.cs | 8 +
.../Aliyun/OTS/DataModel/IndexMeta.cs | 25 +
.../Aliyun/OTS/DataModel/IndexType.cs | 13 +
.../Aliyun/OTS/DataModel/IndexUpdateMode.cs | 13 +
.../Aliyun/OTS/DataModel/LogicOperator.cs | 7 +
.../OTS/DataModel/MultiRowQueryCriteria.cs | 128 +
.../OTS/DataModel/NameTimestampComparator.cs | 23 +
.../Aliyun/OTS/DataModel/PartitionRange.cs | 24 +
.../Aliyun/OTS/DataModel/PrimaryKey.cs | 112 +
.../Aliyun/OTS/DataModel/PrimaryKeyColumn.cs | 109 +
.../Aliyun/OTS/DataModel/PrimaryKeyOption.cs | 8 +
.../Aliyun/OTS/DataModel/PrimaryKeySchema.cs | 56 +
.../OTS/DataModel/RangeRowQueryCriteria.cs | 59 +
.../DataModel/ReservedThroughputDetails.cs | 61 +
.../Aliyun/OTS/DataModel/ReturnType.cs | 24 +
netstandard-sdk/Aliyun/OTS/DataModel/Row.cs | 221 +
.../Aliyun/OTS/DataModel/RowChange.cs | 83 +
.../Aliyun/OTS/DataModel/RowChangeType.cs | 25 +
.../Aliyun/OTS/DataModel/RowChanges.cs | 125 +
.../Aliyun/OTS/DataModel/RowDeleteChange.cs | 28 +
.../OTS/DataModel/RowExistenceExpectation.cs | 23 +
.../Aliyun/OTS/DataModel/RowPutChange.cs | 249 +
.../Aliyun/OTS/DataModel/RowQueryCriteria.cs | 122 +
.../Aliyun/OTS/DataModel/RowUpdateChange.cs | 191 +
.../Aliyun/OTS/DataModel/Search/Collapse.cs | 13 +
.../OTS/DataModel/Search/ColumnsToGet.cs | 10 +
.../OTS/DataModel/Search/FieldSchema.cs | 64 +
.../Aliyun/OTS/DataModel/Search/FieldType.cs | 19 +
.../Aliyun/OTS/DataModel/Search/GeoPoint.cs | 17 +
.../OTS/DataModel/Search/IndexOptions.cs | 16 +
.../OTS/DataModel/Search/IndexSchema.cs | 19 +
.../OTS/DataModel/Search/IndexSetting.cs | 10 +
.../OTS/DataModel/Search/Query/BoolQuery.cs | 46 +
.../DataModel/Search/Query/ConstScoreQuery.cs | 24 +
.../Search/Query/FieldValueFactor.cs | 16 +
.../Search/Query/FunctionScoreQuery.cs | 31 +
.../Search/Query/GeoBoundingBoxQuery.cs | 35 +
.../Search/Query/GeoDistanceQuery.cs | 36 +
.../DataModel/Search/Query/GeoPolygonQuery.cs | 33 +
.../OTS/DataModel/Search/Query/IQuery.cs | 16 +
.../DataModel/Search/Query/MatchAllQuery.cs | 21 +
.../Search/Query/MatchPhraseQuery.cs | 30 +
.../OTS/DataModel/Search/Query/MatchQuery.cs | 46 +
.../OTS/DataModel/Search/Query/NestedQuery.cs | 36 +
.../OTS/DataModel/Search/Query/PrefixQuery.cs | 32 +
.../DataModel/Search/Query/QueryOperator.cs | 8 +
.../OTS/DataModel/Search/Query/QueryType.cs | 25 +
.../OTS/DataModel/Search/Query/RangeQuery.cs | 49 +
.../OTS/DataModel/Search/Query/ScoreMode.cs | 16 +
.../OTS/DataModel/Search/Query/TermQuery.cs | 30 +
.../OTS/DataModel/Search/Query/TermsQuery.cs | 23 +
.../DataModel/Search/Query/WildcardQuery.cs | 31 +
.../OTS/DataModel/Search/SearchIndexInfo.cs | 8 +
.../OTS/DataModel/Search/SearchQuery.cs | 50 +
.../OTS/DataModel/Search/Sort/FieldSort.cs | 24 +
.../DataModel/Search/Sort/GeoDistanceSort.cs | 39 +
.../DataModel/Search/Sort/GeoDistanceType.cs | 18 +
.../OTS/DataModel/Search/Sort/ISorter.cs | 6 +
.../OTS/DataModel/Search/Sort/NestedFilter.cs | 19 +
.../DataModel/Search/Sort/PrimaryKeySort.cs | 14 +
.../OTS/DataModel/Search/Sort/ScoreSort.cs | 19 +
.../Aliyun/OTS/DataModel/Search/Sort/Sort.cs | 14 +
.../OTS/DataModel/Search/Sort/SortMode.cs | 15 +
.../OTS/DataModel/Search/Sort/SortOrder.cs | 11 +
.../Aliyun/OTS/DataModel/Search/SyncStat.cs | 15 +
.../OTS/DataModel/SingleRowQueryCriteria.cs | 44 +
.../Aliyun/OTS/DataModel/StreamDetails.cs | 32 +
.../OTS/DataModel/StreamSpecification.cs | 15 +
.../Aliyun/OTS/DataModel/TableMeta.cs | 49 +
.../Aliyun/OTS/DataModel/TableOptions.cs | 28 +
.../Aliyun/OTS/DataModel/TimeRange.cs | 10 +
.../Aliyun/OTS/DataModel/UpdateOfAttribute.cs | 47 +
netstandard-sdk/Aliyun/OTS/Handler/Context.cs | 50 +
.../Aliyun/OTS/Handler/ErrorHandler.cs | 89 +
.../Aliyun/OTS/Handler/HttpHandler.cs | 74 +
.../Aliyun/OTS/Handler/HttpHeaderHandler.cs | 231 +
.../Aliyun/OTS/Handler/OTSHandler.cs | 40 +
.../Aliyun/OTS/Handler/PipelineHandler.cs | 32 +
.../OTS/Handler/ProtocolBufferDecoder.cs | 772 +
.../OTS/Handler/ProtocolBufferEncoder.cs | 1221 +
.../Aliyun/OTS/Handler/RetryHandler.cs | 99 +
netstandard-sdk/Aliyun/OTS/OTSClient.cs | 832 +
netstandard-sdk/Aliyun/OTS/OTSClientConfig.cs | 144 +
.../Aliyun/OTS/OTSClientException.cs | 43 +
.../Aliyun/OTS/OTSClientTestHelper.cs | 67 +
.../Aliyun/OTS/OTSDefaultLogHandler.cs | 37 +
netstandard-sdk/Aliyun/OTS/OTSException.cs | 28 +
.../Aliyun/OTS/OTSServerException.cs | 101 +
.../Aliyun/OTS/ProtoBuffer/IResultParser.cs | 8 +
.../OTS/ProtoBuffer/PlainBufferBuilder.cs | 488 +
.../Aliyun/OTS/ProtoBuffer/PlainBufferCell.cs | 218 +
.../PlainBufferCodedInputStream.cs | 352 +
.../PlainBufferCodedOutputStream.cs | 287 +
.../OTS/ProtoBuffer/PlainBufferConsts.cs | 109 +
.../OTS/ProtoBuffer/PlainBufferConversion.cs | 95 +
.../Aliyun/OTS/ProtoBuffer/PlainBufferCrc8.cs | 113 +
.../OTS/ProtoBuffer/PlainBufferExtension.cs | 40 +
.../OTS/ProtoBuffer/PlainBufferInputStream.cs | 138 +
.../ProtoBuffer/PlainBufferOutputStream.cs | 110 +
.../Aliyun/OTS/ProtoBuffer/PlainBufferRow.cs | 121 +
.../ProtoBuffer/PlainBufferSequenceInfo.cs | 53 +
.../OTS/ProtoBuffer/ProtocolBufferParser.cs | 11 +
.../OTS/ProtoBuffer/SearchQueryBuilder.cs | 268 +
.../OTS/ProtoBuffer/SearchSortBuilder.cs | 149 +
.../OTS/ProtoBuffer/SearchVariantType.cs | 116 +
.../Aliyun/OTS/ProtoBuffer/TableStore.cs | 29215 ++++++++++++++++
.../OTS/ProtoBuffer/TableStoreFilter.cs | 1582 +
.../OTS/ProtoBuffer/TablestoreSearch.cs | 15965 +++++++++
.../Aliyun/OTS/ProtoBuffer/table_store.proto | 637 +
.../OTS/ProtoBuffer/table_store_filter.proto | 46 +
.../OTS/ProtoBuffer/tablestore_search.proto | 325 +
.../Aliyun/OTS/Request/BatchGetRowRequest.cs | 132 +
.../OTS/Request/BatchWriteRowRequest.cs | 43 +
.../OTS/Request/CreateGlobalIndexRequest.cs | 19 +
.../OTS/Request/CreateSearchIndexRequest.cs | 17 +
.../Aliyun/OTS/Request/CreateTableRequest.cs | 61 +
.../OTS/Request/DeleteGlobalIndexRequest.cs | 15 +
.../Aliyun/OTS/Request/DeleteRowRequest.cs | 59 +
.../OTS/Request/DeleteSearchIndexRequest.cs | 13 +
.../Aliyun/OTS/Request/DeleteTableRequest.cs | 29 +
.../OTS/Request/DescribeSearchIndexRequest.cs | 14 +
.../OTS/Request/DescribeTableRequest.cs | 29 +
.../Aliyun/OTS/Request/GetIteratorRequest.cs | 61 +
.../Aliyun/OTS/Request/GetRangeRequest.cs | 188 +
.../Aliyun/OTS/Request/GetRowRequest.cs | 134 +
.../OTS/Request/ListSearchIndexRequest.cs | 15 +
.../Aliyun/OTS/Request/ListTableRequest.cs | 21 +
.../Aliyun/OTS/Request/OTSRequest.cs | 18 +
.../Aliyun/OTS/Request/PutRowRequest.cs | 60 +
.../Aliyun/OTS/Request/SearchRequest.cs | 41 +
.../Aliyun/OTS/Request/UpdateRowRequest.cs | 67 +
.../Aliyun/OTS/Request/UpdateTableRequest.cs | 52 +
.../Response/BatchGetRowErrorResponseItem.cs | 21 +
.../OTS/Response/BatchGetRowResponse.cs | 54 +
.../OTS/Response/BatchGetRowResponseItem.cs | 104 +
.../BatchGetRowSuccessResponseItem.cs | 25 +
.../BatchWriteRowErrorResponseItem.cs | 22 +
.../OTS/Response/BatchWriteRowResponse.cs | 62 +
.../OTS/Response/BatchWriteRowResponseItem.cs | 91 +
.../BatchWriteRowSuccessResponseItem.cs | 24 +
.../OTS/Response/CreateGlobalIndexResponse.cs | 6 +
.../OTS/Response/CreateSearchIndexResponse.cs | 7 +
.../OTS/Response/CreateTableResponse.cs | 21 +
.../OTS/Response/DeleteGlobalIndexResponse.cs | 7 +
.../Aliyun/OTS/Response/DeleteRowResponse.cs | 46 +
.../OTS/Response/DeleteSearchIndexResponse.cs | 6 +
.../OTS/Response/DeleteTableResponse.cs | 21 +
.../Response/DescribeSearchIndexResponse.cs | 11 +
.../OTS/Response/DescribeTableResponse.cs | 48 +
.../Aliyun/OTS/Response/GetRangeResponse.cs | 45 +
.../Aliyun/OTS/Response/GetRowResponse.cs | 85 +
.../OTS/Response/ListSearchIndexResponse.cs | 15 +
.../Aliyun/OTS/Response/ListTableResponse.cs | 27 +
.../Aliyun/OTS/Response/OTSResponse.cs | 18 +
.../Aliyun/OTS/Response/PutRowResponse.cs | 44 +
.../Aliyun/OTS/Response/SearchResponse.cs | 27 +
.../Aliyun/OTS/Response/UpdateRowResponse.cs | 40 +
.../OTS/Response/UpdateTableResponse.cs | 34 +
.../OTS/Retry/PredefinedRetryPolicies.cs | 116 +
.../Aliyun/OTS/Retry/RetryPolicy.cs | 26 +
netstandard-sdk/Aliyun/OTS/Retry/RetryUtil.cs | 97 +
netstandard-sdk/Aliyun/OTS/Util/OtsUtils.cs | 76 +
.../aliyun-tablestore-netstandard-sdk.csproj | 12 +
199 files changed, 63402 insertions(+), 2 deletions(-)
create mode 100644 netcore-sample/Config.cs
create mode 100644 netcore-sample/Program.cs
create mode 100644 netcore-sample/Samples/AtomicIncrementSample.cs
create mode 100644 netcore-sample/Samples/AutoIncrementSample.cs
create mode 100644 netcore-sample/Samples/ClientInitialize.cs
create mode 100644 netcore-sample/Samples/ConditionUpdateSample.cs
create mode 100644 netcore-sample/Samples/CreateTableSample.cs
create mode 100644 netcore-sample/Samples/GlobalIndexSample.cs
create mode 100644 netcore-sample/Samples/MultiRowReadWriteSample.cs
create mode 100644 netcore-sample/Samples/SearchIndexGeoSample.cs
create mode 100644 netcore-sample/Samples/SearchIndexPageSample.cs
create mode 100644 netcore-sample/Samples/SearchIndexSample.cs
create mode 100644 netcore-sample/Samples/SingleRowReadWriteSample.cs
create mode 100644 netcore-sample/aliyun-tablestore-netcore-sdk-sample.csproj
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/AttributeColumns.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/BloomFilterType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/CapacityUnit.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Column.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ColumnValue.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ColumnValueType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/CompareOperator.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Condition.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnCondition.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnConditionType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/CompositeCondition.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/IColumnCondition.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/RelationalCondition.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnSchema.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Filter/ColumnPaginationFilter.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Filter/CompositeColumnValueFilter.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Filter/FilterType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Filter/IFilter.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Filter/SingleColumnValueFilter.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/IMeasurable.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/IRow.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/IndexMeta.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/IndexType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/IndexUpdateMode.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/LogicOperator.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/MultiRowQueryCriteria.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/NameTimestampComparator.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/PartitionRange.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKey.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyColumn.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyOption.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeySchema.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RangeRowQueryCriteria.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ReservedThroughputDetails.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/ReturnType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Row.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowChange.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowChangeType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowChanges.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowDeleteChange.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowExistenceExpectation.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowPutChange.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowQueryCriteria.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/RowUpdateChange.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Collapse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/ColumnsToGet.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldSchema.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/GeoPoint.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexOptions.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSchema.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSetting.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/BoolQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ConstScoreQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FieldValueFactor.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FunctionScoreQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoBoundingBoxQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoDistanceQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoPolygonQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/IQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchAllQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchPhraseQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/NestedQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/PrefixQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryOperator.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/RangeQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ScoreMode.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermsQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/WildcardQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchIndexInfo.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchQuery.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/FieldSort.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceSort.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ISorter.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/NestedFilter.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/PrimaryKeySort.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ScoreSort.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/Sort.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortMode.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortOrder.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/Search/SyncStat.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/SingleRowQueryCriteria.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/StreamDetails.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/StreamSpecification.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/TableMeta.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/TableOptions.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/TimeRange.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/DataModel/UpdateOfAttribute.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/Context.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/ErrorHandler.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/HttpHandler.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/HttpHeaderHandler.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/OTSHandler.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/PipelineHandler.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferDecoder.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferEncoder.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Handler/RetryHandler.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/OTSClient.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/OTSClientConfig.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/OTSClientException.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/OTSClientTestHelper.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/OTSDefaultLogHandler.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/OTSException.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/OTSServerException.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/IResultParser.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferBuilder.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCell.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedInputStream.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedOutputStream.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConsts.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConversion.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCrc8.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferExtension.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferInputStream.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferOutputStream.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferRow.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferSequenceInfo.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/ProtocolBufferParser.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchQueryBuilder.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchSortBuilder.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchVariantType.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/TableStore.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/TableStoreFilter.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/TablestoreSearch.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/table_store.proto
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/table_store_filter.proto
create mode 100644 netstandard-sdk/Aliyun/OTS/ProtoBuffer/tablestore_search.proto
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/BatchGetRowRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/BatchWriteRowRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/CreateGlobalIndexRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/CreateSearchIndexRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/CreateTableRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/DeleteGlobalIndexRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/DeleteRowRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/DeleteSearchIndexRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/DeleteTableRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/DescribeSearchIndexRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/DescribeTableRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/GetIteratorRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/GetRangeRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/GetRowRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/ListSearchIndexRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/ListTableRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/OTSRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/PutRowRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/SearchRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/UpdateRowRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Request/UpdateTableRequest.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchGetRowErrorResponseItem.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchGetRowResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchGetRowResponseItem.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchGetRowSuccessResponseItem.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchWriteRowErrorResponseItem.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchWriteRowResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchWriteRowResponseItem.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/BatchWriteRowSuccessResponseItem.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/CreateGlobalIndexResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/CreateSearchIndexResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/CreateTableResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/DeleteGlobalIndexResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/DeleteRowResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/DeleteSearchIndexResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/DeleteTableResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/DescribeSearchIndexResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/DescribeTableResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/GetRangeResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/GetRowResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/ListSearchIndexResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/ListTableResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/OTSResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/PutRowResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/SearchResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/UpdateRowResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Response/UpdateTableResponse.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Retry/PredefinedRetryPolicies.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Retry/RetryPolicy.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Retry/RetryUtil.cs
create mode 100644 netstandard-sdk/Aliyun/OTS/Util/OtsUtils.cs
create mode 100644 netstandard-sdk/aliyun-tablestore-netstandard-sdk.csproj
diff --git a/aliyun-tablestore-csharp-sdk.sln b/aliyun-tablestore-csharp-sdk.sln
index 517b5a7..7ad5b93 100644
--- a/aliyun-tablestore-csharp-sdk.sln
+++ b/aliyun-tablestore-csharp-sdk.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.28010.2050
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30611.23
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aliyun-tablestore-sdk", "sdk\aliyun-tablestore-sdk.csproj", "{AB5EFCA2-53A9-42B5-861E-3FD6F865036B}"
EndProject
@@ -9,6 +9,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aliyun-tablestore-sdk-test"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "aliyun-tablestore-sdk-sample", "sample\aliyun-tablestore-sdk-sample.csproj", "{D151C869-BC8F-4465-9460-5103A25D21E9}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "aliyun-tablestore-netstandard-sdk", "netstandard-sdk\aliyun-tablestore-netstandard-sdk.csproj", "{9D75067C-1B14-45BC-94C4-8DB2ED5EEF93}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "aliyun-tablestore-netcore-sdk-sample", "netcore-sample\aliyun-tablestore-netcore-sdk-sample.csproj", "{4E840B62-46EE-49DC-B140-43884CAAF4CF}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +31,14 @@ Global
{D151C869-BC8F-4465-9460-5103A25D21E9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D151C869-BC8F-4465-9460-5103A25D21E9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D151C869-BC8F-4465-9460-5103A25D21E9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9D75067C-1B14-45BC-94C4-8DB2ED5EEF93}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9D75067C-1B14-45BC-94C4-8DB2ED5EEF93}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9D75067C-1B14-45BC-94C4-8DB2ED5EEF93}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9D75067C-1B14-45BC-94C4-8DB2ED5EEF93}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4E840B62-46EE-49DC-B140-43884CAAF4CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4E840B62-46EE-49DC-B140-43884CAAF4CF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4E840B62-46EE-49DC-B140-43884CAAF4CF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4E840B62-46EE-49DC-B140-43884CAAF4CF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/netcore-sample/Config.cs b/netcore-sample/Config.cs
new file mode 100644
index 0000000..09097ae
--- /dev/null
+++ b/netcore-sample/Config.cs
@@ -0,0 +1,31 @@
+namespace Aliyun.OTS.Samples
+{
+ internal static class Config
+ {
+ public static string AccessKeyId = "";
+
+ public static string AccessKeySecret = "";
+
+ public static string Endpoint = "";
+
+ public static string InstanceName = "";
+
+ private static OTSClient OtsClient = null;
+
+ public static OTSClient GetClient()
+ {
+ if (OtsClient != null)
+ {
+ return OtsClient;
+ }
+
+ OTSClientConfig config = new OTSClientConfig(Endpoint, AccessKeyId, AccessKeySecret, InstanceName)
+ {
+ OTSDebugLogHandler = null,
+ OTSErrorLogHandler = null
+ };
+ OtsClient = new OTSClient(config);
+ return OtsClient;
+ }
+ }
+}
diff --git a/netcore-sample/Program.cs b/netcore-sample/Program.cs
new file mode 100644
index 0000000..e9eff33
--- /dev/null
+++ b/netcore-sample/Program.cs
@@ -0,0 +1,56 @@
+using System;
+namespace Aliyun.OTS.Samples
+{
+ class Program
+ {
+ static void Main(string[] args)
+ {
+ Console.WriteLine("Aliyun Table Store SDK for .NET Samples!");
+
+ try
+ {
+ ClientInitialize.InitializeClient();
+
+ CreateTableSample.TableOperations();
+
+ SingleRowReadWriteSample.PutRow();
+ SingleRowReadWriteSample.PutRowAsync();
+
+ SingleRowReadWriteSample.UpdateRow();
+
+ SingleRowReadWriteSample.GetRow();
+ SingleRowReadWriteSample.GetRowWithFilter();
+
+ MultiRowReadWriteSample.BatchWriteRow();
+
+ MultiRowReadWriteSample.GetRange();
+ MultiRowReadWriteSample.GetRangeWithFilter();
+ MultiRowReadWriteSample.GetIterator();
+
+ MultiRowReadWriteSample.BatchGetRow();
+ MultiRowReadWriteSample.BatchGetRowWithFilter();
+
+ ConditionUpdateSample.ConditionPutRow();
+ ConditionUpdateSample.ConditionUpdateRow();
+ ConditionUpdateSample.ConditionDeleteRow();
+ ConditionUpdateSample.ConditionBatchWriteRow();
+ }
+ catch (OTSClientException ex)
+ {
+ Console.WriteLine("Failed with client exception:{0}", ex.Message);
+ }
+ catch (OTSServerException ex)
+ {
+ Console.WriteLine("Failed with server exception:{0}, {1}", ex.Message, ex.RequestID);
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Failed with error info: {0}", ex.Message);
+ }
+
+ Console.WriteLine("Press any key to continue . . . ");
+
+ Console.ReadKey(true);
+ }
+ }
+}
diff --git a/netcore-sample/Samples/AtomicIncrementSample.cs b/netcore-sample/Samples/AtomicIncrementSample.cs
new file mode 100644
index 0000000..f3b19fc
--- /dev/null
+++ b/netcore-sample/Samples/AtomicIncrementSample.cs
@@ -0,0 +1,172 @@
+using System;
+using System.Collections.Generic;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+
+namespace Aliyun.OTS.Samples.Samples
+{
+ ///
+ /// 原子自增示例
+ /// 可以指定某一列为原子自增列,每次按照指定的数值进行累加。
+ ///
+ public class AtomicIncrementSample
+ {
+ private static readonly string TableName = "AtomicIncrementSample";
+
+ private static readonly string Pk1 = "Pk1";
+ private static readonly string Pk2 = "Pk2";
+ private static readonly string IncrementCol = "IncrementCol";
+
+
+ //static void Main(string[] args)
+ //{
+ // Console.WriteLine("AtomicIncrementSample");
+
+ // //准备表
+ // PrepareTable();
+
+ // //新增一行,设置IncrementCol这个属性列的初始值为0
+ // PutRow();
+
+ // //对IncrementCol执行原子自增,10次,每次加1
+ // for (int i = 0; i < 10; i++)
+ // {
+ // Increment(1);
+ // }
+
+ // //获取自增后的列
+ // GetRow();
+
+ // Console.ReadLine();
+
+ //}
+
+
+ private static void PrepareTable()
+ {
+ // 创建表
+ OTSClient otsClient = Config.GetClient();
+
+ IList tables = otsClient.ListTable(new ListTableRequest()).TableNames;
+ if (tables.Contains(TableName))
+ {
+ return;
+ }
+
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { Pk1, ColumnValueType.Integer },
+ { Pk2, ColumnValueType.String }
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ }
+
+ public static void PutRow()
+ {
+ Console.WriteLine("Start put row...");
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { Pk1, new ColumnValue(0) },
+ { Pk2, new ColumnValue("abc") }
+ };
+
+ // 定义要写入该行的属性列
+ AttributeColumns attribute = new AttributeColumns
+ {
+ { IncrementCol, new ColumnValue(0) }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.PutRow(request);
+ Console.WriteLine("Put row succeed.");
+ }
+
+
+ ///
+ /// 更新行的时候,指定某一列为原子自增列,并对这一列进行原子自增
+ ///
+ public static void Increment(int incrementValue)
+ {
+ Console.WriteLine("Start set increment column...");
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { Pk1, new ColumnValue(0) },
+ { Pk2, new ColumnValue("abc") }
+ };
+ RowUpdateChange rowUpdateChange = new RowUpdateChange(TableName, primaryKey);
+ rowUpdateChange.ReturnType = ReturnType.RT_AFTER_MODIFY;
+ rowUpdateChange.ReturnColumnNames = new List() { IncrementCol};
+ //设置一个原子自增列,这一列从0开始自增,每次增增加1。
+ rowUpdateChange.Increment(new Column(IncrementCol, new ColumnValue(incrementValue)));
+
+ UpdateRowRequest updateRowRequest = new UpdateRowRequest(rowUpdateChange);
+
+ var response = otsClient.UpdateRow(updateRowRequest);
+ Console.WriteLine("set Increment column succeed,Increment result:" + response.Row.GetColumns()[0].Value);
+ }
+
+
+ public static void GetRow()
+ {
+ Console.WriteLine("Start get row...");
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { Pk1, new ColumnValue(0) },
+ { Pk2, new ColumnValue("abc") }
+ };
+
+ GetRowRequest request = new GetRowRequest(TableName, primaryKey); // 未指定读哪列,默认读整行
+ GetRowResponse response = otsClient.GetRow(request);
+ PrimaryKey primaryKeyRead = response.PrimaryKey;
+ AttributeColumns attributesRead = response.Attribute;
+
+ Console.WriteLine("Primary key read: ");
+ foreach (KeyValuePair entry in primaryKeyRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Attributes read: ");
+ foreach (KeyValuePair entry in attributesRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Get row succeed.");
+ }
+
+
+
+ private static string PrintColumnValue(ColumnValue value)
+ {
+ switch (value.Type)
+ {
+ case ColumnValueType.String: return value.StringValue;
+ case ColumnValueType.Integer: return value.IntegerValue.ToString();
+ case ColumnValueType.Boolean: return value.BooleanValue.ToString();
+ case ColumnValueType.Double: return value.DoubleValue.ToString();
+ case ColumnValueType.Binary: return value.BinaryValue.ToString();
+ }
+
+ throw new Exception("Unknow type.");
+ }
+
+
+ }
+}
diff --git a/netcore-sample/Samples/AutoIncrementSample.cs b/netcore-sample/Samples/AutoIncrementSample.cs
new file mode 100644
index 0000000..d372ca5
--- /dev/null
+++ b/netcore-sample/Samples/AutoIncrementSample.cs
@@ -0,0 +1,90 @@
+using System;
+using System.Collections.Generic;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+
+namespace Aliyun.OTS.Samples.Samples
+{
+ ///
+ /// 主键列自增示例
+ ///
+ public class AutoIncrementSample
+ {
+ private static readonly string TableName = "AutoIncrementSample";
+
+ private static readonly string Pk1 = "Pk1";
+ private static readonly string Pk2 = "Pk2_AutoIncrement";
+
+
+ //static void Main(string[] args)
+ //{
+ // Console.WriteLine("AutoIncrementSample");
+
+ // //创建一个带自增列的表
+ // CreateTableWithAutoIncrementPk();
+
+ // //写入10行,自增列Pk2将
+ // for (int i = 0; i < 10; i++)
+ // {
+ // PutRow(i.ToString());
+ // }
+
+ // Console.ReadLine();
+
+ //}
+
+ ///
+ /// 创建一个带自增列的表
+ ///
+ private static void CreateTableWithAutoIncrementPk()
+ {
+
+ OTSClient otsClient = Config.GetClient();
+
+ IList tables = otsClient.ListTable(new ListTableRequest()).TableNames;
+ if (tables.Contains(TableName))
+ {
+ return;
+ }
+
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { Pk1, ColumnValueType.String },
+ //指定Pk2为自增列主键
+ { Pk2, ColumnValueType.Integer, PrimaryKeyOption.AUTO_INCREMENT}
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ }
+
+ public static void PutRow(string pk1Value)
+ {
+ Console.WriteLine("Start put row...");
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { Pk1, new ColumnValue(pk1Value) },
+ { Pk2, ColumnValue.AUTO_INCREMENT }
+ };
+
+ // 定义要写入该行的属性列
+ AttributeColumns attribute = new AttributeColumns
+ {
+ { "Col1", new ColumnValue(0) }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+ request.RowPutChange.ReturnType = ReturnType.RT_PK;
+
+ var response = otsClient.PutRow(request);
+ Console.WriteLine("Put row succeed,autoIncrement Pk value:"+ response.Row.GetPrimaryKey()[Pk2].IntegerValue);
+ }
+
+ }
+}
diff --git a/netcore-sample/Samples/ClientInitialize.cs b/netcore-sample/Samples/ClientInitialize.cs
new file mode 100644
index 0000000..c7a88d3
--- /dev/null
+++ b/netcore-sample/Samples/ClientInitialize.cs
@@ -0,0 +1,31 @@
+using System;
+using Aliyun.OTS.Request;
+
+namespace Aliyun.OTS.Samples
+{
+ public static class ClientInitialize
+ {
+
+ public static void ErrorLog(string message)
+ {
+ Console.WriteLine(message);
+ }
+
+ public static void InitializeClient()
+ {
+ OTSClientConfig config = new OTSClientConfig(Config.Endpoint, Config.AccessKeyId, Config.AccessKeySecret, Config.InstanceName);
+ config.AccessKeyID = Config.AccessKeyId; // 访问OTS服务所需的云账号的accessid
+ config.AccessKeySecret = Config.AccessKeySecret; // 访问OTS服务所需的云账号的accesskey
+ config.InstanceName = Config.InstanceName; // OTS的实例名
+ config.EndPoint = Config.Endpoint; // OTS的服务访问地址
+ config.ConnectionLimit = 300; // Client内部的连接池的连接数上限
+ config.OTSDebugLogHandler = null; // 将DebugLogHandler设置为null,可关闭client内部的debug log的输出,否则默认会输出到标准输出
+ config.OTSErrorLogHandler = ErrorLog; // 也可自定义LogHandler,将日志输出进行定制
+
+ OTSClient client = new OTSClient(config); // 初始化ots client
+
+ ListTableRequest request = new ListTableRequest();
+ client.ListTable(request);
+ }
+ }
+}
diff --git a/netcore-sample/Samples/ConditionUpdateSample.cs b/netcore-sample/Samples/ConditionUpdateSample.cs
new file mode 100644
index 0000000..ad4d94a
--- /dev/null
+++ b/netcore-sample/Samples/ConditionUpdateSample.cs
@@ -0,0 +1,288 @@
+using System;
+using System.Collections.Generic;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using Aliyun.OTS.DataModel.ConditionalUpdate;
+
+namespace Aliyun.OTS.Samples
+{
+ public static class ConditionUpdateSample
+ {
+
+ private static string tableName = "condition_update_sample";
+
+ private static void PrepareTable()
+ {
+ // 创建表
+ OTSClient otsClient = Config.GetClient();
+
+ IList tables = otsClient.ListTable(new ListTableRequest()).TableNames;
+ if (tables.Contains(tableName)) {
+ return;
+ }
+
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema();
+ primaryKeySchema.Add("pk0", ColumnValueType.Integer);
+ primaryKeySchema.Add("pk1", ColumnValueType.String);
+ TableMeta tableMeta = new TableMeta(tableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+ }
+
+ public static void ConditionPutRow()
+ {
+ Console.WriteLine("Start put row...");
+
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey();
+ primaryKey.Add("pk0", new ColumnValue(0));
+ primaryKey.Add("pk1", new ColumnValue("abc"));
+
+ // 定义要写入改行的属性列
+ AttributeColumns attribute = new AttributeColumns();
+ attribute.Add("col0", new ColumnValue(0));
+ attribute.Add("col1", new ColumnValue("a"));
+ attribute.Add("col2", new ColumnValue(true));
+
+ PutRowRequest request = new PutRowRequest(tableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ // 不带condition时put row,预期成功
+ try
+ {
+ otsClient.PutRow(request);
+
+ Console.WriteLine("Put row succeeded.");
+ } catch (Exception ex)
+ {
+ Console.WriteLine("Put row failed. error:{0}", ex.Message);
+ }
+
+ // 当col0列的值不等于5的时候,允许再次put row,覆盖掉原值,预期成功
+ try
+ {
+ request.Condition.ColumnCondition = new RelationalCondition("col0",
+ CompareOperator.NOT_EQUAL,
+ new ColumnValue(5));
+ otsClient.PutRow(request);
+
+ Console.WriteLine("Put row succeeded.");
+ } catch (Exception ex)
+ {
+ Console.WriteLine("Put row failed. error:{0}", ex.Message);
+ }
+
+ // 当col0列的值等于5的时候,允许再次put row,覆盖掉原值,预期失败
+ try
+ {
+ // 新增条件:col0列的值等于5
+ request.Condition.ColumnCondition = new RelationalCondition("col0",
+ CompareOperator.EQUAL,
+ new ColumnValue(5));
+ otsClient.PutRow(request);
+
+ Console.WriteLine("Put row succeeded.");
+ }
+ catch (OTSServerException)
+ {
+ // 由于条件不满足,抛出OTSServerException
+ Console.WriteLine("Put row failed because condition check failed. but expected");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Put row failed. error:{0}", ex.Message);
+ }
+ }
+
+ public static void ConditionUpdateRow()
+ {
+ Console.WriteLine("Start update row...");
+
+ PrepareTable();
+ var otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ var primaryKey = new PrimaryKey();
+ primaryKey.Add("pk0", new ColumnValue(1));
+ primaryKey.Add("pk1", new ColumnValue("abc"));
+
+ // 定义要写入改行的属性列
+ var attribute = new AttributeColumns();
+ attribute.Add("col0", new ColumnValue(1));
+ attribute.Add("col1", new ColumnValue("a"));
+ attribute.Add("col2", new ColumnValue(true));
+
+ var request = new PutRowRequest(tableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ // 新创建一行数据
+ try
+ {
+ otsClient.PutRow(request);
+
+ Console.WriteLine("Put row succeeded.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Put row failed. error:{0}", ex.Message);
+ }
+
+
+ // 当col0不等于5,且col1等于'a'时,允许修改,否则不允许修改
+ try
+ {
+ // 构造condition
+ var cond1 = new RelationalCondition("col0",
+ CompareOperator.NOT_EQUAL,
+ new ColumnValue(5));
+ var cond2 = new RelationalCondition("col1", CompareOperator.EQUAL,
+ new ColumnValue("a"));
+ var columenCondition = new CompositeCondition(LogicOperator.AND);
+ columenCondition.AddCondition(cond1);
+ columenCondition.AddCondition(cond2);
+
+ var condition = new Condition(RowExistenceExpectation.IGNORE);
+ condition.ColumnCondition = columenCondition;
+
+ // 构造更新请求
+ var updateOfAttribute = new UpdateOfAttribute();
+ updateOfAttribute.AddAttributeColumnToPut("col2", new ColumnValue(false));
+ var updateRowRequest = new UpdateRowRequest(tableName, condition, primaryKey, updateOfAttribute);
+
+ // 更新数据
+ otsClient.UpdateRow(updateRowRequest);
+
+ // 更新成功
+ Console.WriteLine("Update row succeeded.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Update row failed. error:{0}", ex.Message);
+ }
+ }
+
+ public static void ConditionDeleteRow()
+ {
+ Console.WriteLine("Start delete row...");
+
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey();
+ primaryKey.Add("pk0", new ColumnValue(2));
+ primaryKey.Add("pk1", new ColumnValue("abc"));
+
+ // 定义要写入改行的属性列
+ AttributeColumns attribute = new AttributeColumns();
+ attribute.Add("col0", new ColumnValue(2));
+ attribute.Add("col1", new ColumnValue("a"));
+ attribute.Add("col2", new ColumnValue(true));
+
+ PutRowRequest putRequest = new PutRowRequest(tableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ // 新创建一行数据
+ try
+ {
+ otsClient.PutRow(putRequest);
+
+ Console.WriteLine("Put row succeeded.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Put row failed. error:{0}", ex.Message);
+ }
+
+ // 当col2列的值等于true的时候,允许删除
+ try
+ {
+ // 构造条件语句:col2列的值等于true
+ var condition = new Condition(RowExistenceExpectation.EXPECT_EXIST);
+ condition.ColumnCondition = new RelationalCondition("col2",
+ CompareOperator.EQUAL,
+ new ColumnValue(true));
+
+ // 构造删除请求
+ var deleteRequest = new DeleteRowRequest(tableName, condition, primaryKey);
+
+ // 删除满足条件的特定行
+ otsClient.DeleteRow(deleteRequest);
+
+ Console.WriteLine("Delete row succeeded.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Delete row failed. error:{0}", ex.Message);
+ }
+
+ Console.WriteLine("Delete row succeeded.");
+ }
+
+ public static void ConditionBatchWriteRow()
+ {
+ Console.WriteLine("Start batch write row...");
+
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey();
+ primaryKey.Add("pk0", new ColumnValue(3));
+ primaryKey.Add("pk1", new ColumnValue("abc"));
+
+ // 定义要写入改行的属性列
+ AttributeColumns attribute = new AttributeColumns();
+ attribute.Add("col0", new ColumnValue(0));
+ attribute.Add("col1", new ColumnValue("a"));
+ attribute.Add("col2", new ColumnValue(true));
+
+ PutRowRequest request = new PutRowRequest(tableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ // 新创建一行数据
+ try
+ {
+ otsClient.PutRow(request);
+
+ Console.WriteLine("Put row succeeded.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Put row failed. error:{0}", ex.Message);
+ }
+
+ // 当col0列的值不等于5的时候,允许再次put row,覆盖掉原值,预期成功
+ try
+ {
+ // 构造条件语句:col0列的值不等于5
+ var condition = new Condition(RowExistenceExpectation.IGNORE);
+ condition.ColumnCondition = new RelationalCondition("col0",
+ CompareOperator.NOT_EQUAL,
+ new ColumnValue(5));
+
+ // 构造col2列的值
+ var attr1 = new AttributeColumns();
+ attr1.Add("col2", new ColumnValue(false));
+
+ // 构造批量写请求
+ var rowChange = new RowChanges(tableName);
+ rowChange.AddPut(condition, primaryKey, attr1);
+
+ var batchWriteRequest = new BatchWriteRowRequest();
+ batchWriteRequest.Add(tableName, rowChange);
+
+ // 批量写数据
+ otsClient.BatchWriteRow(batchWriteRequest);
+
+ Console.WriteLine("Batch write row succeeded.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Batch write row failed. error:{0}", ex.Message);
+ }
+ }
+ }
+}
diff --git a/netcore-sample/Samples/CreateTableSample.cs b/netcore-sample/Samples/CreateTableSample.cs
new file mode 100644
index 0000000..24e116e
--- /dev/null
+++ b/netcore-sample/Samples/CreateTableSample.cs
@@ -0,0 +1,70 @@
+using System;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using System.Threading;
+
+namespace Aliyun.OTS.Samples
+{
+ public static class CreateTableSample
+ {
+
+ private static readonly string TableName = "createTableSample";
+
+ public static void TableOperations()
+ {
+ // 创建表
+ OTSClient otsClient = Config.GetClient();
+
+ {
+ Console.WriteLine("Start create table...");
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { "pk0", ColumnValueType.Integer },
+ { "pk1", ColumnValueType.String }
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ Console.WriteLine("Table is created: " + TableName);
+ }
+
+ //// 更新表
+ //{
+ // Thread.Sleep(60 * 1000); // 每次更新表需要至少间隔1分钟
+ // Console.WriteLine("Start update table...");
+ // CapacityUnit reservedThroughput = new CapacityUnit(0, 0); // 将预留CU调整为0,0
+ // UpdateTableRequest request = new UpdateTableRequest(TableName, reservedThroughput);
+ // UpdateTableResponse response = otsClient.UpdateTable(request);
+ // Console.WriteLine("LastIncreaseTime: " + response.ReservedThroughputDetails.LastIncreaseTime);
+ // Console.WriteLine("LastDecreaseTime: " + response.ReservedThroughputDetails.LastDecreaseTime);
+ // Console.WriteLine("NumberOfDecreaseToday: " + response.ReservedThroughputDetails.LastIncreaseTime);
+ // Console.WriteLine("ReadCapacity: " + response.ReservedThroughputDetails.CapacityUnit.Read);
+ // Console.WriteLine("WriteCapacity: " + response.ReservedThroughputDetails.CapacityUnit.Write);
+ //}
+
+ // 描述表
+ {
+ Console.WriteLine("Start describe table...");
+ DescribeTableRequest request = new DescribeTableRequest(TableName);
+ DescribeTableResponse response = otsClient.DescribeTable(request);
+ Console.WriteLine("LastIncreaseTime: " + response.ReservedThroughputDetails.LastIncreaseTime);
+ Console.WriteLine("LastDecreaseTime: " + response.ReservedThroughputDetails.LastDecreaseTime);
+ Console.WriteLine("NumberOfDecreaseToday: " + response.ReservedThroughputDetails.LastIncreaseTime);
+ Console.WriteLine("ReadCapacity: " + response.ReservedThroughputDetails.CapacityUnit.Read);
+ Console.WriteLine("WriteCapacity: " + response.ReservedThroughputDetails.CapacityUnit.Write);
+ }
+
+ //// 删除表
+ //{
+ // Console.WriteLine("Start delete table...");
+ // DeleteTableRequest request = new DeleteTableRequest(TableName);
+ // otsClient.DeleteTable(request);
+ // Console.WriteLine("Table is deleted.");
+ //}
+ }
+ }
+}
diff --git a/netcore-sample/Samples/GlobalIndexSample.cs b/netcore-sample/Samples/GlobalIndexSample.cs
new file mode 100644
index 0000000..a7b9e25
--- /dev/null
+++ b/netcore-sample/Samples/GlobalIndexSample.cs
@@ -0,0 +1,233 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+
+namespace Aliyun.OTS.Samples.Samples
+{
+ public class GlobalIndexSample
+ {
+ private static readonly string TableName = "tableWithGlobalIndexSample";
+ private static readonly string IndexName = "tableWithGlobalIndexSampleIndex";
+ private static readonly string IndexName2 = "tableWithGlobalIndexSampleIndex2";
+
+ private static readonly string Pk1 = "Pk1";
+ private static readonly string Pk2 = "Pk2";
+ private static readonly string Col1 = "Col1";
+ private static readonly string Col2 = "Col2";
+
+
+ //static void Main(string[] args)
+ //{
+ // Console.WriteLine("GlobalIndexSample");
+
+ // CreateTableWithGlobalIndex();
+
+ // CreateGlobalIndex();
+
+ // PutRow();
+
+ // GetRangeFromIndexTable();
+
+ // DeleteGlobalIndex();
+
+ // DeleteTable();
+
+ // Console.ReadLine();
+
+ //}
+
+ ///
+ /// 创建一个带二级索引的表
+ ///
+ public static void CreateTableWithGlobalIndex()
+ {
+ //建主表,两列Pk:Pk1、Pk2。 预定义列:Col1、Col2。
+ //建索引表,索引表中Col1放Pk0
+ OTSClient otsClient = Config.GetClient();
+
+ Console.WriteLine("Start create table with globalIndex...");
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { Pk1, ColumnValueType.String },
+ { Pk2, ColumnValueType.String }
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+ tableMeta.DefinedColumnSchema = new DefinedColumnSchema {
+ { Col1, DefinedColumnType.STRING},
+ { Col2,DefinedColumnType.STRING}
+ };
+
+ IndexMeta indexMeta = new IndexMeta(IndexName);
+ indexMeta.PrimaryKey = new List() { Col1 };
+ indexMeta.DefinedColumns = new List() { Col2 };
+ //indexMeta.IndexType = IndexType.IT_GLOBAL_INDEX;
+ //indexMeta.IndexUpdateModel = IndexUpdateMode.IUM_ASYNC_INDEX;
+
+ List indexMetas = new List() { };
+ indexMetas.Add(indexMeta);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput, indexMetas);
+ otsClient.CreateTable(request);
+
+ Console.WriteLine("Table is created: " + TableName);
+
+ }
+
+ ///
+ /// 单独在表上再创建一个索引表2
+ ///
+ public static void CreateGlobalIndex()
+ {
+ OTSClient otsClient = Config.GetClient();
+
+ Console.WriteLine("Start create globalIndex...");
+
+ IndexMeta indexMeta = new IndexMeta(IndexName2);
+ indexMeta.PrimaryKey = new List() { Col2 };
+ indexMeta.DefinedColumns = new List() { Pk1 };
+
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateGlobalIndexRequest request = new CreateGlobalIndexRequest(TableName, indexMeta);
+ otsClient.CreateGlobalIndex(request);
+
+ Console.WriteLine("Global Index is created,tableName: " + TableName + ",IndexName:" + IndexName2);
+
+ }
+
+ ///
+ /// 向主表中写入数据(自动同步到索引表)
+ ///
+ public static void PutRow()
+ {
+ Console.WriteLine("Start put row...");
+ OTSClient otsClient = Config.GetClient();
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { Pk1, new ColumnValue("abc") },
+ { Pk2, new ColumnValue("edf") }
+ };
+
+ // 定义要写入改行的属性列
+ AttributeColumns attribute = new AttributeColumns
+ {
+ { Col1, new ColumnValue("Col1Value") },
+ { Col2, new ColumnValue("Col2Value") }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.PutRow(request);
+ Console.WriteLine("Put row succeed.");
+ }
+
+ ///
+ /// 从索引表中读取数据
+ ///
+ public static void GetRangeFromIndexTable()
+ {
+ Console.WriteLine("Start getRange from index...");
+ OTSClient otsClient = Config.GetClient();
+ // 指定第一主键Col1的值,进行扫描
+ PrimaryKey inclusiveStartPrimaryKey = new PrimaryKey
+ {
+ { Col1, new ColumnValue("Col1Value") },
+ { Pk1, ColumnValue.INF_MIN },
+ { Pk2, ColumnValue.INF_MIN }
+ };
+
+ PrimaryKey exclusiveEndPrimaryKey = new PrimaryKey
+ {
+ { Col1, new ColumnValue("Col1Value") },
+ { Pk1, ColumnValue.INF_MAX },
+ { Pk2, ColumnValue.INF_MAX }
+ };
+
+ GetRangeRequest request = new GetRangeRequest(IndexName, GetRangeDirection.Forward, inclusiveStartPrimaryKey, exclusiveEndPrimaryKey);
+
+ GetRangeResponse response = otsClient.GetRange(request);
+ IList rows = response.RowDataList;
+ PrimaryKey nextStartPrimaryKey = response.NextPrimaryKey;
+ while (nextStartPrimaryKey != null)
+ {
+ request = new GetRangeRequest(TableName, GetRangeDirection.Forward, nextStartPrimaryKey, exclusiveEndPrimaryKey);
+ response = otsClient.GetRange(request);
+ nextStartPrimaryKey = response.NextPrimaryKey;
+ foreach (var row in response.RowDataList)
+ {
+ rows.Add(row);
+ }
+ }
+
+ foreach (var row in rows)
+ {
+ PrintRow(row);
+ }
+
+ Console.WriteLine("TotalRowsRead: " + rows.Count);
+ }
+
+
+ ///
+ /// 删除索引表1、2
+ ///
+ public static void DeleteGlobalIndex()
+ {
+ OTSClient otsClient = Config.GetClient();
+
+ Console.WriteLine("Start delete globalIndex...");
+
+ DeleteGlobalIndexRequest request = new DeleteGlobalIndexRequest(TableName, IndexName);
+ otsClient.DeleteGlobalIndex(request);
+
+ DeleteGlobalIndexRequest request2 = new DeleteGlobalIndexRequest(TableName, IndexName2);
+ otsClient.DeleteGlobalIndex(request2);
+
+ Console.WriteLine("Global Index is deleted,tableName: " + TableName + ",IndexName:" + IndexName + "," + IndexName2);
+
+ }
+
+ public static void DeleteTable()
+ {
+ OTSClient otsClient = Config.GetClient();
+ Console.WriteLine("Start delete table...");
+ DeleteTableRequest request = new DeleteTableRequest(TableName);
+ otsClient.DeleteTable(request);
+ Console.WriteLine("Table is deleted.");
+ }
+
+ private static string PrintColumnValue(ColumnValue value)
+ {
+ switch (value.Type)
+ {
+ case ColumnValueType.String: return value.StringValue;
+ case ColumnValueType.Integer: return value.IntegerValue.ToString();
+ case ColumnValueType.Boolean: return value.BooleanValue.ToString();
+ case ColumnValueType.Double: return value.DoubleValue.ToString();
+ case ColumnValueType.Binary: return value.BinaryValue.ToString();
+ }
+
+ throw new Exception("Unknow type.");
+ }
+
+ private static void PrintRow(Row row)
+ {
+ Console.WriteLine("-----------------");
+
+ foreach (KeyValuePair entry in row.GetPrimaryKey())
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ foreach (Column entry in row.GetColumns())
+ {
+ Console.WriteLine(entry.Name + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("-----------------");
+ }
+ }
+}
diff --git a/netcore-sample/Samples/MultiRowReadWriteSample.cs b/netcore-sample/Samples/MultiRowReadWriteSample.cs
new file mode 100644
index 0000000..88102a5
--- /dev/null
+++ b/netcore-sample/Samples/MultiRowReadWriteSample.cs
@@ -0,0 +1,397 @@
+using System;
+using System.Collections.Generic;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using Aliyun.OTS.DataModel.ConditionalUpdate;
+
+namespace Aliyun.OTS.Samples
+{
+ public static class MultiRowReadWriteSample
+ {
+
+ private const string TableName = "multiRowReadWriteSample";
+
+ private static void PrepareTable()
+ {
+ // 创建表
+ OTSClient otsClient = Config.GetClient();
+
+ IList tables = otsClient.ListTable(new ListTableRequest()).TableNames;
+ if (tables.Contains(TableName)) {
+ return;
+ }
+
+
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { "pk0", ColumnValueType.Integer },
+ { "pk1", ColumnValueType.String }
+ };
+
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ }
+
+ private static void PrepareData()
+ {
+ OTSClient otsClient = Config.GetClient();
+
+ // 插入100条数据
+ for (int i = 0; i < 100; i++)
+ {
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(i) },
+ { "pk1", new ColumnValue("abc") }
+ };
+
+ // 定义要写入改行的属性列
+ AttributeColumns attribute = new AttributeColumns
+ {
+ { "col0", new ColumnValue(0) },
+ { "col1", new ColumnValue("a") },
+ { "col2", new ColumnValue(i % 3 != 0) }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.PutRow(request);
+ }
+ }
+
+ public static void GetRange()
+ {
+ Console.WriteLine("Start get range...");
+
+ PrepareTable();
+ PrepareData();
+
+ OTSClient otsClient = Config.GetClient();
+ // 读取 (0, INF_MIN)到(100, INF_MAX)这个范围内的所有行
+ PrimaryKey inclusiveStartPrimaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(0) },
+ { "pk1", ColumnValue.INF_MIN }
+ };
+
+ PrimaryKey exclusiveEndPrimaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(100) },
+ { "pk1", ColumnValue.INF_MAX }
+ };
+
+ GetRangeRequest request = new GetRangeRequest(TableName, GetRangeDirection.Forward, inclusiveStartPrimaryKey, exclusiveEndPrimaryKey);
+
+ GetRangeResponse response = otsClient.GetRange(request);
+ IList rows = response.RowDataList;
+ PrimaryKey nextStartPrimaryKey = response.NextPrimaryKey;
+ while (nextStartPrimaryKey != null)
+ {
+ request = new GetRangeRequest(TableName, GetRangeDirection.Forward, nextStartPrimaryKey, exclusiveEndPrimaryKey);
+ response = otsClient.GetRange(request);
+ nextStartPrimaryKey = response.NextPrimaryKey;
+ foreach (var row in response.RowDataList)
+ {
+ rows.Add(row);
+ }
+ }
+
+ foreach (var row in rows)
+ {
+ PrintRow(row);
+ }
+
+ Console.WriteLine("TotalRowsRead: " + rows.Count);
+ }
+
+ public static void GetRangeWithFilter()
+ {
+ Console.WriteLine("Start get range with filter ...");
+ PrepareTable();
+ PrepareData();
+
+ OTSClient otsClient = Config.GetClient();
+ // 读取 (0, INF_MIN)到(100, INF_MAX)这个范围内的所有行,且col2等于false的行
+ PrimaryKey inclusiveStartPrimaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(0) },
+ { "pk1", ColumnValue.INF_MIN }
+ };
+
+ PrimaryKey exclusiveEndPrimaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(100) },
+ { "pk1", ColumnValue.INF_MAX }
+ };
+
+ // 构造列过滤条件
+ var condition = new RelationalCondition("col2",
+ CompareOperator.EQUAL,
+ new ColumnValue(false));
+
+ var queryCriteria = new RangeRowQueryCriteria(TableName)
+ {
+ Direction = GetRangeDirection.Forward,
+ InclusiveStartPrimaryKey = inclusiveStartPrimaryKey,
+ ExclusiveEndPrimaryKey = exclusiveEndPrimaryKey,
+ Filter = condition.ToFilter()
+ };
+
+ GetRangeResponse response = otsClient.GetRange(new GetRangeRequest(queryCriteria));
+ IList rows = response.RowDataList;
+ PrimaryKey nextStartPrimaryKey = response.NextPrimaryKey;
+ while (nextStartPrimaryKey != null)
+ {
+ queryCriteria = new RangeRowQueryCriteria(TableName)
+ {
+ Direction = GetRangeDirection.Forward,
+ InclusiveStartPrimaryKey = nextStartPrimaryKey,
+ ExclusiveEndPrimaryKey = exclusiveEndPrimaryKey,
+ Filter = condition.ToFilter()
+ };
+
+ response = otsClient.GetRange(new GetRangeRequest(queryCriteria));
+ nextStartPrimaryKey = response.NextPrimaryKey;
+ foreach (var row in response.RowDataList)
+ {
+ rows.Add(row);
+ }
+ }
+
+ foreach (var row in rows)
+ {
+ PrintRow(row);
+ }
+
+ Console.WriteLine("TotalRowsRead with filter: " + rows.Count);
+ }
+
+ public static void GetIterator()
+ {
+ Console.WriteLine("Start get iterator...");
+
+ PrepareTable();
+ PrepareData();
+
+ OTSClient otsClient = Config.GetClient();
+ // 读取 (0, "a")到(1000, "xyz")这个范围内的所有行
+ PrimaryKey inclusiveStartPrimaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(0) },
+ { "pk1", new ColumnValue("a") }
+ };
+
+ PrimaryKey exclusiveEndPrimaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(1000) },
+ { "pk1", new ColumnValue("xyz") }
+ };
+
+ var cu = new CapacityUnit(0, 0);
+ var request = new GetIteratorRequest(TableName, GetRangeDirection.Forward, inclusiveStartPrimaryKey,
+ exclusiveEndPrimaryKey, cu);
+
+ var iterator = otsClient.GetRangeIterator(request);
+ foreach (var row in iterator)
+ {
+ PrintRow(row);
+ }
+
+ Console.WriteLine("Consumed CapacityUnit Counter:{0}", cu.Read);
+ }
+
+ public static void BatchGetRow()
+ {
+ Console.WriteLine("Start batch get row...");
+ PrepareTable();
+ PrepareData();
+ OTSClient otsClient = Config.GetClient();
+
+ // 批量一次读10行
+ BatchGetRowRequest request = new BatchGetRowRequest();
+ List primaryKeys = new List();
+ for (int i = 0; i < 10; i++)
+ {
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(i) },
+ { "pk1", new ColumnValue("abc") }
+ };
+ primaryKeys.Add(primaryKey);
+ }
+
+ request.Add(TableName, primaryKeys);
+
+ BatchGetRowResponse response = otsClient.BatchGetRow(request);
+ var tableRows = response.RowDataGroupByTable;
+ var rows = tableRows[TableName];
+
+ foreach(var row in rows)
+ {
+ // 注意:batch操作可能部分成功部分失败,需要为每行检查状态
+ if (row.IsOK)
+ {
+ Console.WriteLine("-----------------");
+ foreach (KeyValuePair entry in row.PrimaryKey)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+ foreach (KeyValuePair entry in row.Attribute)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+ Console.WriteLine("-----------------");
+ } else
+ {
+ Console.WriteLine("Read row failed: " + row.ErrorMessage);
+ }
+ }
+
+ Console.WriteLine("RowsCount: " + rows.Count);
+ }
+
+ public static void BatchGetRowWithFilter()
+ {
+ Console.WriteLine("Start batch get row with filter ...");
+ PrepareTable();
+ PrepareData();
+ OTSClient otsClient = Config.GetClient();
+
+ // 批量一次读10行
+ BatchGetRowRequest request = new BatchGetRowRequest();
+ List primaryKeys = new List();
+ for (int i = 0; i < 10; i++)
+ {
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(i) },
+ { "pk1", new ColumnValue("abc") }
+ };
+ primaryKeys.Add(primaryKey);
+ }
+
+ var condition = new RelationalCondition("col2",
+ CompareOperator.EQUAL,
+ new ColumnValue(false));
+
+ request.Add(TableName, primaryKeys, null, condition);
+
+ BatchGetRowResponse response = otsClient.BatchGetRow(request);
+ var tableRows = response.RowDataGroupByTable;
+ var rows = tableRows[TableName];
+
+ foreach (var row in rows)
+ {
+ // 注意:batch操作可能部分成功部分失败,需要为每行检查状态
+ if (row.IsOK)
+ {
+ Console.WriteLine("-----------------");
+ foreach (KeyValuePair entry in row.PrimaryKey)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+ foreach (KeyValuePair entry in row.Attribute)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+ Console.WriteLine("-----------------");
+ }
+ else
+ {
+ Console.WriteLine("Read row with filter failed: " + row.ErrorMessage);
+ }
+ }
+
+ Console.WriteLine("RowsCount with filter");
+ }
+
+ public static void BatchWriteRow()
+ {
+ Console.WriteLine("Start batch write row...");
+ PrepareTable();
+ PrepareData();
+ OTSClient otsClient = Config.GetClient();
+
+ // 一次批量导入100行数据
+ var request = new BatchWriteRowRequest();
+ var rowChanges = new RowChanges(TableName);
+ for (int i = 0; i < 100; i++)
+ {
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(i) },
+ { "pk1", new ColumnValue("abc") }
+ };
+
+ // 定义要写入改行的属性列
+ UpdateOfAttribute attribute = new UpdateOfAttribute();
+ attribute.AddAttributeColumnToPut("col0", new ColumnValue(0));
+ attribute.AddAttributeColumnToPut("col1", new ColumnValue("a"));
+ attribute.AddAttributeColumnToPut("col2", new ColumnValue(true));
+
+ rowChanges.AddUpdate(new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+ }
+
+ request.Add(TableName, rowChanges);
+
+ var response = otsClient.BatchWriteRow(request);
+ var tableRows = response.TableRespones;
+ var rows = tableRows[TableName];
+
+ int succeedRows = 0;
+ int failedRows = 0;
+ foreach (var row in rows.Responses)
+ {
+ // 注意:batch操作可能部分成功部分失败,需要为每行检查状态
+ if (row.IsOK)
+ {
+ succeedRows++;
+ }
+ else
+ {
+ Console.WriteLine("Read row failed: " + row.ErrorMessage);
+ failedRows++;
+ }
+ }
+
+ Console.WriteLine("SucceedRows: " + succeedRows);
+ Console.WriteLine("FailedRows: " + failedRows);
+ }
+
+ private static string PrintColumnValue(ColumnValue value)
+ {
+ switch (value.Type)
+ {
+ case ColumnValueType.String: return value.StringValue;
+ case ColumnValueType.Integer: return value.IntegerValue.ToString();
+ case ColumnValueType.Boolean: return value.BooleanValue.ToString();
+ case ColumnValueType.Double: return value.DoubleValue.ToString();
+ case ColumnValueType.Binary: return value.BinaryValue.ToString();
+ }
+
+ throw new Exception("Unknow type.");
+ }
+
+
+ private static void PrintRow(Row row)
+ {
+ Console.WriteLine("-----------------");
+
+ foreach (KeyValuePair entry in row.GetPrimaryKey())
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ foreach (Column entry in row.GetColumns())
+ {
+ Console.WriteLine(entry.Name + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("-----------------");
+ }
+ }
+}
diff --git a/netcore-sample/Samples/SearchIndexGeoSample.cs b/netcore-sample/Samples/SearchIndexGeoSample.cs
new file mode 100644
index 0000000..e5046c4
--- /dev/null
+++ b/netcore-sample/Samples/SearchIndexGeoSample.cs
@@ -0,0 +1,321 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.DataModel.Search;
+using Aliyun.OTS.DataModel.Search.Query;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using Newtonsoft.Json;
+
+namespace Aliyun.OTS.Samples.Samples
+{
+ public class SearchIndexGeoSample
+ {
+ private static readonly string TableName = "SearchIndexGeoSampleTable";
+ private static readonly string IndexName = "SearchIndexGeoSampleTableIndex";
+ private static readonly string Pk0 = "pk0";
+ private static readonly string Pk1 = "pk1";
+ private static readonly string Geo_type_col = "geo_type_col";
+
+ //static void Main(string[] args)
+ //{
+ // OTSClient otsClient = Config.GetClient();
+ // //DeleteSearchIndex(otsClient);
+ // //DeleteTable(otsClient);
+ // //CreateTable(otsClient);
+ // //CreateSearchIndex(otsClient);
+
+ // ////Wait searchIndex load success
+ // //Console.WriteLine("wait searchIndex load success");
+ // //Thread.Sleep(3 * 1000);
+
+ // //ListSearchIndex(otsClient);
+ // //DescribeSearchIndex(otsClient);
+ // //PutRow(otsClient);
+
+ // //Wait searchIndex load success
+ // WaiteAllDataSyncSuccess(otsClient, 10);
+
+ // //GeoBoundingBoxQuery
+ // GeoBoundingBoxQuery(otsClient);
+
+ // //GeoDistanceQuery
+ // GeoDistanceQuery(otsClient);
+
+ // //GeoPolygonQuery
+ // GeoPolygonQuery(otsClient);
+
+ // Console.ReadLine();
+ //}
+
+ public static void CreateTable(OTSClient otsClient)
+ {
+ // 创建表
+ Console.WriteLine("\n Start create table...");
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { Pk0, ColumnValueType.Integer },
+ { Pk1, ColumnValueType.String }
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ Console.WriteLine("Table is created: " + TableName);
+ }
+
+ public static void DeleteTable(OTSClient otsClient)
+ {
+ DeleteTableRequest request = new DeleteTableRequest(TableName);
+ otsClient.DeleteTable(request);
+ }
+
+ public static void ListSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start list searchindex...");
+
+ ListSearchIndexRequest request = new ListSearchIndexRequest(TableName);
+ ListSearchIndexResponse response = otsClient.ListSearchIndex(request);
+ foreach (var index in response.IndexInfos)
+ {
+ Console.WriteLine("indexname:" + index.IndexName);
+ Console.WriteLine("tablename:" + index.TableName);
+ }
+ }
+
+ public static void CreateSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Create searchindex...");
+
+ CreateSearchIndexRequest request = new CreateSearchIndexRequest(TableName,IndexName);
+ List FieldSchemas = new List() {
+ new FieldSchema(Geo_type_col,FieldType.GEO_POINT){ index=true,EnableSortAndAgg=true},
+ };
+ request.IndexSchame = new IndexSchema()
+ {
+ FieldSchemas = FieldSchemas
+ };
+
+ CreateSearchIndexResponse response = otsClient.CreateSearchIndex(request);
+
+ Console.WriteLine("Searchindex is created: " + IndexName);
+ }
+
+ public static void DescribeSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Describe searchindex...");
+
+ DescribeSearchIndexRequest request = new DescribeSearchIndexRequest(TableName, IndexName);
+ DescribeSearchIndexResponse response = otsClient.DescribeSearchIndex(request);
+ string serializedObjectString = JsonConvert.SerializeObject(response);
+ Console.WriteLine(serializedObjectString);
+
+ }
+
+ public static void DeleteSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Delete searchindex...");
+
+ DeleteSearchIndexRequest request = new DeleteSearchIndexRequest(TableName, IndexName);
+ DeleteSearchIndexResponse response = otsClient.DeleteSearchIndex(request);
+
+ Console.WriteLine("Searchindex is deleted:" + IndexName);
+
+ }
+
+ public static void PutRow(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start put row...");
+ List colList = new List() {
+ "0,0",
+ "7,3",
+ "2,8",
+ "5,9",
+ "10,10",
+ "20,20",
+ "14,18",
+ "12,16",
+ "15,4",
+ "8,13"
+ };
+ for (int i = 0; i < 10; i++)
+ {
+ PrimaryKey primaryKey = new PrimaryKey{
+ { Pk0, new ColumnValue(i) },
+ { Pk1, new ColumnValue("pk1value") }
+ };
+ AttributeColumns attribute = new AttributeColumns{
+ { Geo_type_col, new ColumnValue(colList[i]) }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.PutRow(request);
+ }
+ Console.WriteLine("Put row succeed.");
+ }
+
+ public static void WaiteAllDataSyncSuccess(OTSClient otsClient, int expectTotalCount)
+ {
+ Console.WriteLine("wait all rows sync success");
+ int timeoutSeconds = 3 * 60;
+ var beginTime = DateTime.Now;
+ while (true)
+ {
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new MatchAllQuery();
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+
+ var response = otsClient.Search(request);
+ if (response.TotalCount == expectTotalCount)
+ {
+ break;
+ }
+ else if ((DateTime.Now - beginTime).Seconds > timeoutSeconds)
+ {
+ throw new Exception("searchIndex sync data timeout");
+ }
+ Thread.Sleep(1000);
+ }
+ }
+
+ private static string PrintColumnValue(ColumnValue value)
+ {
+ switch (value.Type)
+ {
+ case ColumnValueType.String: return value.StringValue;
+ case ColumnValueType.Integer: return value.IntegerValue.ToString();
+ case ColumnValueType.Boolean: return value.BooleanValue.ToString();
+ case ColumnValueType.Double: return value.DoubleValue.ToString();
+ case ColumnValueType.Binary: return value.BinaryValue.ToString();
+ }
+
+ throw new Exception("Unknow type.");
+ }
+
+ private static void PrintRow(Row row)
+ {
+ PrimaryKey primaryKeyRead = row.PrimaryKey;
+ AttributeColumns attributesRead = row.AttributeColumns;
+
+ Console.WriteLine("Primary key: ");
+ foreach (KeyValuePair entry in primaryKeyRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Attributes: ");
+ foreach (KeyValuePair entry in attributesRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+ }
+
+ ///
+ /// 查询所有行,返回行数
+ ///
+ ///
+ public static void MatchAllQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start matchAll query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new MatchAllQuery();
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("IsAllSuccess:" + response.IsAllSuccess);
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ }
+
+ ///
+ /// geo_type_col是GeoPoint类型,查询表中geo_type_col这一列的值在左上角为"10,0", 右下角为"0,10"的矩形范围内的数据
+ ///
+ ///
+ public static void GeoBoundingBoxQuery(OTSClient client)
+ {
+ Console.WriteLine("\n Start GeoBoundingBox query...");
+
+ SearchQuery searchQuery = new SearchQuery();
+ GeoBoundingBoxQuery geoBoundingBoxQuery = new GeoBoundingBoxQuery(); // 设置查询类型为GeoBoundingBoxQuery
+ geoBoundingBoxQuery.FieldName = Geo_type_col; // 设置比较哪个字段的值
+ geoBoundingBoxQuery.TopLeft = "10,0"; // 设置矩形左上角
+ geoBoundingBoxQuery.BottomRight = "0,10"; // 设置矩形右下角
+ searchQuery.Query = geoBoundingBoxQuery;
+
+ SearchRequest searchRequest = new SearchRequest(TableName, IndexName, searchQuery);
+
+ var columnsToGet = new ColumnsToGet();
+ columnsToGet.Columns = new List { Geo_type_col }; //设置返回Col_GeoPoint这一列
+ searchRequest.ColumnsToGet = columnsToGet;
+
+ SearchResponse response = client.Search(searchRequest);
+ Console.WriteLine(response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+ ///
+ /// 查询表中geo_type_col这一列的值距离中心点不超过一定距离的数据。
+ ///
+ ///
+ public static void GeoDistanceQuery(OTSClient client)
+ {
+ Console.WriteLine("\n Start GeoDistance query...");
+
+ SearchQuery searchQuery = new SearchQuery();
+ GeoDistanceQuery geoDistanceQuery = new GeoDistanceQuery(); // 设置查询类型为GeoDistanceQuery
+ geoDistanceQuery.FieldName = Geo_type_col;
+ geoDistanceQuery.CenterPoint = "10,11"; // 设置中心点
+ geoDistanceQuery.DistanceInMeter = 10000; // 设置到中心点的距离条件,不超过50米
+ searchQuery.Query = geoDistanceQuery;
+
+ SearchRequest searchRequest = new SearchRequest(TableName, IndexName, searchQuery);
+
+ ColumnsToGet columnsToGet = new ColumnsToGet();
+ columnsToGet.Columns = new List() { Geo_type_col }; //设置返回Col_GeoPoint这一列
+ searchRequest.ColumnsToGet = columnsToGet;
+
+ SearchResponse response = client.Search(searchRequest);
+ Console.WriteLine(response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+
+ ///
+ /// 查询表中geo_type_col这一列的值在一个给定多边形范围内的数据。
+ ///
+ ///
+ public static void GeoPolygonQuery(OTSClient client)
+ {
+ Console.WriteLine("\n Start GeoPolygon query...");
+
+ SearchQuery searchQuery = new SearchQuery();
+ GeoPolygonQuery geoPolygonQuery = new GeoPolygonQuery(); // 设置查询类型为GeoPolygonQuery
+ geoPolygonQuery.FieldName = Geo_type_col;
+ geoPolygonQuery.Points = new List() { "0,0", "10,0", "10,10" }; // 设置多边形的顶点
+ searchQuery.Query = geoPolygonQuery;
+
+ SearchRequest searchRequest = new SearchRequest(TableName, IndexName, searchQuery);
+
+ ColumnsToGet columnsToGet = new ColumnsToGet();
+ columnsToGet.Columns = new List() { Geo_type_col }; //设置返回Col_GeoPoint这一列
+ searchRequest.ColumnsToGet = columnsToGet;
+
+ SearchResponse response = client.Search(searchRequest);
+ Console.WriteLine(response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+ }
+}
diff --git a/netcore-sample/Samples/SearchIndexPageSample.cs b/netcore-sample/Samples/SearchIndexPageSample.cs
new file mode 100644
index 0000000..7860ac2
--- /dev/null
+++ b/netcore-sample/Samples/SearchIndexPageSample.cs
@@ -0,0 +1,212 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.DataModel.Search;
+using Aliyun.OTS.DataModel.Search.Query;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using Newtonsoft.Json;
+
+namespace Aliyun.OTS.Samples.Samples
+{
+ public class SearchIndexPageSample
+ {
+ private static readonly string TableName = "SearchIndexPageSampleTable";
+ private static readonly string IndexName = "SearchIndexPageSampleTableIndex";
+ private static readonly string Pk0 = "pk0";
+ private static readonly string Pk1 = "pk1";
+ private static readonly string Long_type_col = "Long_type_col";
+ private static readonly string Text_type_col = "Text_type_col";
+ private static readonly string Keyword_type_col = "Keyword_type_col";
+
+ //static void Main(string[] args)
+ //{
+ // OTSClient otsClient = Config.GetClient();
+ // //DeleteSearchIndex(otsClient);
+ // //DeleteTable(otsClient);
+ // //CreateTable(otsClient);
+ // //CreateSearchIndex(otsClient);
+
+ // ////Wait searchIndex load success
+ // //Console.WriteLine("wait searchIndex load success");
+ // //Thread.Sleep(3 * 1000);
+
+ // //ListSearchIndex(otsClient);
+ // //DescribeSearchIndex(otsClient);
+ // //PutRow(otsClient);
+
+ // ////Wait searchIndex load success
+ // //WaiteAllDataSyncSuccess(otsClient, 7);
+
+ // ReadMoreRowsWithToken(otsClient);
+
+ // Console.ReadLine();
+ //}
+
+
+ public static void CreateTable(OTSClient otsClient)
+ {
+ // 创建表
+ Console.WriteLine("\n Start create table...");
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { Pk0, ColumnValueType.Integer },
+ { Pk1, ColumnValueType.String }
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ Console.WriteLine("Table is created: " + TableName);
+ }
+
+ public static void DeleteTable(OTSClient otsClient)
+ {
+ DeleteTableRequest request = new DeleteTableRequest(TableName);
+ otsClient.DeleteTable(request);
+ }
+
+ public static void ListSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start list searchindex...");
+
+ ListSearchIndexRequest request = new ListSearchIndexRequest(TableName);
+ ListSearchIndexResponse response = otsClient.ListSearchIndex(request);
+ foreach (var index in response.IndexInfos)
+ {
+ Console.WriteLine("indexname:" + index.IndexName);
+ Console.WriteLine("tablename:" + index.TableName);
+ }
+ }
+
+ public static void CreateSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Create searchindex...");
+
+ CreateSearchIndexRequest request = new CreateSearchIndexRequest(TableName, IndexName);
+ List FieldSchemas = new List() {
+ new FieldSchema(Keyword_type_col,FieldType.KEYWORD){index=true,EnableSortAndAgg=true},
+ new FieldSchema(Long_type_col,FieldType.LONG){ index=true,EnableSortAndAgg=true},
+ new FieldSchema(Text_type_col,FieldType.TEXT){ index=true}
+ };
+ request.IndexSchame = new IndexSchema()
+ {
+ FieldSchemas = FieldSchemas
+ };
+
+ CreateSearchIndexResponse response = otsClient.CreateSearchIndex(request);
+
+ Console.WriteLine("Searchindex is created: " + IndexName);
+ }
+
+ public static void DescribeSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Describe searchindex...");
+
+ DescribeSearchIndexRequest request = new DescribeSearchIndexRequest(TableName, IndexName);
+
+ DescribeSearchIndexResponse response = otsClient.DescribeSearchIndex(request);
+ string serializedObjectString = JsonConvert.SerializeObject(response);
+ Console.WriteLine(serializedObjectString);
+
+ }
+
+ public static void DeleteSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Delete searchindex...");
+
+ DeleteSearchIndexRequest request = new DeleteSearchIndexRequest(TableName, IndexName);
+ DeleteSearchIndexResponse response = otsClient.DeleteSearchIndex(request);
+
+ Console.WriteLine("Searchindex is deleted:" + IndexName);
+
+ }
+
+ public static void PutRow(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start put row...");
+ List colList = new List() {
+ "TableStore SearchIndex Sample",
+ "TableStore",
+ "SearchIndex",
+ "Sample",
+ "SearchIndex Sample",
+ "TableStore Sample",
+ "TableStore SearchIndex"
+ };
+ for (int i = 0; i < 500; i++)
+ {
+ PrimaryKey primaryKey = new PrimaryKey{
+ { Pk0, new ColumnValue(i) },
+ { Pk1, new ColumnValue("pk1value") }
+ };
+ var colId = i % 7;
+ AttributeColumns attribute = new AttributeColumns{
+ { Long_type_col, new ColumnValue(i) },
+ { Text_type_col, new ColumnValue(colList[colId]) },
+ { Keyword_type_col, new ColumnValue(colList[colId]) }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.PutRow(request);
+ }
+ Console.WriteLine("Put row succeed.");
+ }
+
+ public static void WaiteAllDataSyncSuccess(OTSClient otsClient, int expectTotalCount)
+ {
+ Console.WriteLine("wait all rows sync success");
+ int timeoutSeconds = 3 * 60;
+ var beginTime = DateTime.Now;
+ while (true)
+ {
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new MatchAllQuery();
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+
+ var response = otsClient.Search(request);
+ if (response.TotalCount == expectTotalCount)
+ {
+ break;
+ }
+ else if ((DateTime.Now - beginTime).Seconds > timeoutSeconds)
+ {
+ throw new Exception("searchIndex sync data timeout");
+ }
+ Thread.Sleep(1000);
+ }
+ }
+
+
+ ///
+ /// 查询所有行,返回行数
+ ///
+ ///
+ public static SearchResponse ReadMoreRowsWithToken(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start matchAll query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new MatchAllQuery();
+
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+
+ var response = otsClient.Search(request);
+ var rows = response.Rows;
+ while (response.NextToken != null)
+ {
+ request.SearchQuery.Token = response.NextToken;
+ response = otsClient.Search(request);
+ rows.AddRange(response.Rows);
+ }
+
+ return response;
+ }
+
+ }
+}
diff --git a/netcore-sample/Samples/SearchIndexSample.cs b/netcore-sample/Samples/SearchIndexSample.cs
new file mode 100644
index 0000000..22809f3
--- /dev/null
+++ b/netcore-sample/Samples/SearchIndexSample.cs
@@ -0,0 +1,584 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.DataModel.Search;
+using Aliyun.OTS.DataModel.Search.Query;
+using Aliyun.OTS.DataModel.Search.Sort;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using Newtonsoft.Json;
+
+namespace Aliyun.OTS.Samples.Samples
+{
+ public class SearchIndexSample
+ {
+ private static readonly string TableName = "SearchIndexSampleTable";
+ private static readonly string IndexName = "SearchIndexSampleTableIndex2";
+ private static readonly string Pk0 = "pk0";
+ private static readonly string Pk1 = "pk1";
+ private static readonly string Long_type_col = "Long_type_col";
+ private static readonly string Text_type_col = "Text_type_col";
+ private static readonly string Keyword_type_col = "Keyword_type_col";
+
+ //static void Main(string[] args)
+ //{
+ // OTSClient otsClient = Config.GetClient();
+ // //DeleteSearchIndex(otsClient);
+ // //DeleteTable(otsClient);
+
+ // //创建一张TableStore表
+ // CreateTable(otsClient);
+ // //在TableStore表上创建一个索引表
+ // CreateSearchIndex(otsClient);
+
+ // //Wait searchIndex load success
+ // Console.WriteLine("wait searchIndex load success");
+ // Thread.Sleep(3 * 1000);
+
+ // ListSearchIndex(otsClient);
+ // CreateSearchIndexWithIndexSort(otsClient);
+ // DescribeSearchIndex(otsClient);
+ // PutRow(otsClient);
+
+ // //等待索引数据同步成功
+ // WaiteAllDataSyncSuccess(otsClient, 7);
+
+ // //MatchAll Query
+ // MatchAllQuery(otsClient);
+
+ // //MatchQuery
+ // MatchQuery(otsClient);
+
+ // //MatchPhraseQuery
+ // MatchPhraseQuery(otsClient);
+
+ // //RangeQuery
+ // RangeQuery(otsClient);
+
+ // //PrefixQuery
+ // PrefixQuery(otsClient);
+
+ // //TermQuery
+ // TermQuery(otsClient);
+
+ // //WildcardQuery
+ // WildcardQuery(otsClient);
+
+ // //BoolQuery
+ // BoolQuery(otsClient);
+
+ // Console.ReadLine();
+ //}
+
+ public static void CreateTable(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start create table...");
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { Pk0, ColumnValueType.Integer },
+ { Pk1, ColumnValueType.String }
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ Console.WriteLine("Table is created: " + TableName);
+ }
+
+ public static void DeleteTable(OTSClient otsClient)
+ {
+ DeleteTableRequest request = new DeleteTableRequest(TableName);
+ otsClient.DeleteTable(request);
+ }
+
+ ///
+ /// 列出多元索引名称
+ ///
+ ///
+ public static void ListSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start list searchindex...");
+
+ ListSearchIndexRequest request = new ListSearchIndexRequest(TableName);
+ ListSearchIndexResponse response = otsClient.ListSearchIndex(request);
+ foreach (var index in response.IndexInfos)
+ {
+ Console.WriteLine("indexname:" + index.IndexName);
+ Console.WriteLine("tablename:" + index.TableName);
+ }
+ }
+
+ ///
+ /// 创建一个多元索引,包含Keyword_type_col、Long_type_col、Text_type_col三个属性列,类型分别设置为不分词字符串(KEYWORD),整型(LONG),分词字符串(TEXT)
+ ///
+ ///
+ public static void CreateSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Create searchindex...");
+
+ //指定表名和索引名
+ CreateSearchIndexRequest request = new CreateSearchIndexRequest(TableName, IndexName);
+ List FieldSchemas = new List() {
+ new FieldSchema(Keyword_type_col,FieldType.KEYWORD){ //设置字段名和字段类型
+ index =true, //开启索引
+ EnableSortAndAgg =true //开启排序和统计功能
+ },
+ new FieldSchema(Long_type_col,FieldType.LONG){ index=true,EnableSortAndAgg=true},
+ new FieldSchema(Text_type_col,FieldType.TEXT){ index=true}
+ };
+ request.IndexSchame = new IndexSchema()
+ {
+ FieldSchemas = FieldSchemas
+ };
+
+ CreateSearchIndexResponse response = otsClient.CreateSearchIndex(request);
+
+ Console.WriteLine("Searchindex is created: " + IndexName);
+ }
+
+ ///
+ /// 创建一个多元索引,包含Keyword_type_col、Long_type_col、Text_type_col三个属性列,类型分别设置为不分词字符串(KEYWORD),整型(LONG),分词字符串(TEXT)
+ ///
+ ///
+ public static void CreateSearchIndexWithIndexSort(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Create searchindex with indexSort...");
+
+ //指定表名和索引名
+ CreateSearchIndexRequest request = new CreateSearchIndexRequest(TableName, IndexName);
+ List FieldSchemas = new List() {
+ new FieldSchema(Keyword_type_col,FieldType.KEYWORD){ //设置字段名和字段类型
+ index =true, //开启索引
+ EnableSortAndAgg =true //开启排序和统计功能
+ },
+ new FieldSchema(Long_type_col,FieldType.LONG){ index=true,EnableSortAndAgg=true},
+ new FieldSchema(Text_type_col,FieldType.TEXT){ index=true}
+ };
+ request.IndexSchame = new IndexSchema()
+ {
+ FieldSchemas = FieldSchemas,
+ IndexSort = new Sort(new List()
+ {
+ new FieldSort(Long_type_col,SortOrder.ASC)
+ })
+ };
+
+ CreateSearchIndexResponse response = otsClient.CreateSearchIndex(request);
+
+ Console.WriteLine("Searchindex is created: " + IndexName);
+ }
+
+ ///
+ /// 查询多元索引的描述信息
+ ///
+ ///
+ public static void DescribeSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Describe searchindex...");
+
+ //设置表名和索引名
+ DescribeSearchIndexRequest request = new DescribeSearchIndexRequest(TableName, IndexName);
+
+ DescribeSearchIndexResponse response = otsClient.DescribeSearchIndex(request);
+ string serializedObjectString = JsonConvert.SerializeObject(response);
+ Console.WriteLine(serializedObjectString);
+ }
+
+ ///
+ /// 删除多元索引
+ ///
+ ///
+ public static void DeleteSearchIndex(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start Delete searchindex...");
+
+ //设置表名和索引名
+ DeleteSearchIndexRequest request = new DeleteSearchIndexRequest(TableName, IndexName);
+ DeleteSearchIndexResponse response = otsClient.DeleteSearchIndex(request);
+
+ Console.WriteLine("Searchindex is deleted:" + IndexName);
+ }
+
+ ///
+ /// 通过PutRow 接口写入一些数据到TableStore,数据将自动同步到索引表
+ ///
+ ///
+ public static void PutRow(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start put row...");
+ List colList = new List() {
+ "TableStore SearchIndex Sample",
+ "TableStore",
+ "SearchIndex",
+ "Sample",
+ "SearchIndex Sample",
+ "TableStore Sample",
+ "TableStore SearchIndex"
+ };
+ for (int i = 0; i < 7; i++)
+ {
+ PrimaryKey primaryKey = new PrimaryKey{
+ { Pk0, new ColumnValue(i) },
+ { Pk1, new ColumnValue("pk1value") }
+ };
+ AttributeColumns attribute = new AttributeColumns{
+ { Long_type_col, new ColumnValue(i) },
+ { Text_type_col, new ColumnValue(colList[i]) },
+ { Keyword_type_col, new ColumnValue(colList[i]) }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.PutRow(request);
+ }
+ Console.WriteLine("Put row succeed.");
+ }
+
+ ///
+ /// 等待数据同步到索引表完成
+ ///
+ ///
+ ///
+ public static void WaiteAllDataSyncSuccess(OTSClient otsClient, int expectTotalCount)
+ {
+ Console.WriteLine("wait all rows sync success");
+ int timeoutSeconds = 3 * 60;
+ var beginTime = DateTime.Now;
+ while (true)
+ {
+ var searchQuery = new SearchQuery();
+ searchQuery.GetTotalCount = true;
+ searchQuery.Query = new MatchAllQuery();
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+
+ var response = otsClient.Search(request);
+ if (response.TotalCount == expectTotalCount)
+ {
+ break;
+ }
+ else if ((DateTime.Now - beginTime).Seconds > timeoutSeconds)
+ {
+ throw new Exception("searchIndex sync data timeout");
+ }
+ Thread.Sleep(1000);
+ }
+ }
+
+ private static string PrintColumnValue(ColumnValue value)
+ {
+ switch (value.Type)
+ {
+ case ColumnValueType.String: return value.StringValue;
+ case ColumnValueType.Integer: return value.IntegerValue.ToString();
+ case ColumnValueType.Boolean: return value.BooleanValue.ToString();
+ case ColumnValueType.Double: return value.DoubleValue.ToString();
+ case ColumnValueType.Binary: return value.BinaryValue.ToString();
+ }
+
+ throw new Exception("Unknow type.");
+ }
+
+ private static void PrintRow(Row row)
+ {
+ PrimaryKey primaryKeyRead = row.PrimaryKey;
+ AttributeColumns attributesRead = row.AttributeColumns;
+
+ Console.WriteLine("Primary key: ");
+ foreach (KeyValuePair entry in primaryKeyRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Attributes: ");
+ foreach (KeyValuePair entry in attributesRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+ }
+
+ ///
+ /// 查询所有行,返回行数
+ ///
+ ///
+ public static void MatchAllQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start matchAll query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new MatchAllQuery();
+ searchQuery.GetTotalCount = true; // 需要设置GetTotalCount = true 才会返回满足条件的数据总行数
+ /*
+ * MatchAllQuery 结果中的Totalcount可以表示数据的总行数(数据量很大时为估算值)
+ * 如果只是为了查询TotalHit,可以设置limit=0,即不返回任意一行数据。
+ */
+ searchQuery.Limit = 0;
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("IsAllSuccess:" + response.IsAllSuccess);
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ }
+
+
+ ///
+ /// 模糊匹配和短语或邻近查询,返回指定列
+ ///
+ ///
+ public static void MatchQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start match query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new MatchQuery(Text_type_col, "SearchIndex");
+ searchQuery.GetTotalCount = true;
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ searchQuery.Sort = new Sort(new List() { new ScoreSort() });
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ Columns = new List() { Long_type_col, Text_type_col, Keyword_type_col }
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+ ///
+ /// 类似MatchQuery(MatchQuery 仅匹配某个词即可),但是 MatchPhraseQuery会匹配所有的短语。
+ ///
+ ///
+ public static void MatchPhraseQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start MatchPhrase query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new MatchPhraseQuery(Text_type_col, "TableStore SearchIndex");
+ searchQuery.GetTotalCount = true;
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ Columns = new List() { Long_type_col, Text_type_col, Keyword_type_col }
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+ ///
+ /// 范围查询。通过设置一个范围(from,to),查询该范围内的所有数据。
+ ///
+ ///
+ public static void RangeQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start range query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.GetTotalCount = true;
+ var rangeQuery = new RangeQuery(Long_type_col, new ColumnValue(0), new ColumnValue(6));
+ //包括下边界(大于等于0)
+ rangeQuery.IncludeLower = true;
+ searchQuery.Query = rangeQuery;
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+
+ ///
+ /// 前缀查询。
+ ///
+ ///
+ public static void PrefixQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start prefix query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new PrefixQuery(Keyword_type_col, "Search");
+ searchQuery.GetTotalCount = true;
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ ReturnAll = true
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+ ///
+ /// 精确的term查询
+ ///
+ ///
+ public static void TermQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start term query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.GetTotalCount = true;
+ searchQuery.Query = new TermQuery(Keyword_type_col, new ColumnValue("SearchIndex"));
+
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ ReturnAll = true
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+ ///
+ /// 精确的terms查询,查询Keyword_type_col这一列精确匹配"TableStore"或者"SearchIndex"的数据
+ /// TermsQuery可以使用多个Term同时查询
+ ///
+ ///
+ public static void TermsQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start terms query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.GetTotalCount = true;
+ var query = new TermsQuery();
+ query.FieldName = Keyword_type_col;
+ query.Terms = new List() { new ColumnValue("TableStore"), new ColumnValue("SearchIndex") };
+
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ ReturnAll = true
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+
+
+ ///
+ ///通配符查询。支持 *( 任意0或多个)和 ?(任意1个字符)。
+ ///
+ ///
+ public static void WildcardQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start wildcard query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.Query = new WildcardQuery(Keyword_type_col, "*Search*");
+ searchQuery.GetTotalCount = true;
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ ReturnAll = true
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+ ///
+ ///联合查询(复杂查询条件下用的最多的一个查询)。Bool查询由一个或者多个子句组成,每个子句都有特定的类型。
+ ///must: 文档必须完全匹配条件
+ ///should: should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
+ ///must_not: 文档必须不匹配条件
+ ///MinimumShouldMatch: should查询的条件至少满足几个
+ ///
+ ///
+ public static void BoolQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start bool query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.GetTotalCount = true;
+ var boolQuery = new BoolQuery();
+ var shouldQuerys = new List();
+ shouldQuerys.Add(new TermQuery(Keyword_type_col, new ColumnValue("SearchIndex")));
+ shouldQuerys.Add(new TermQuery(Keyword_type_col, new ColumnValue("TableStore")));
+ boolQuery.ShouldQueries = shouldQuerys;
+ boolQuery.MinimumShouldMatch = 1;
+
+ searchQuery.Query = boolQuery;
+
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ ReturnAll = true
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+
+ ///
+ /// 有一个类型为NESTED的列,子文档包含nested_1和nested_2两列,现在查询col1_nested.nested_1为"tablestore"的数据
+ ///
+ ///
+ public static void NestedQuery(OTSClient otsClient)
+ {
+ Console.WriteLine("\n Start bool query...");
+
+ var searchQuery = new SearchQuery();
+ searchQuery.GetTotalCount = true;
+ var nestedQuery = new NestedQuery();
+ nestedQuery.Path = "col1_nested"; //设置nested字段路径
+ TermQuery termQuery = new TermQuery("col1_nested.nested_1",new ColumnValue("tablestore"));//构造NestedQuery的子查询
+ nestedQuery.Query = termQuery;
+ nestedQuery.ScoreMode = ScoreMode.None;
+
+ var request = new SearchRequest(TableName, IndexName, searchQuery);
+ request.ColumnsToGet = new ColumnsToGet()
+ {
+ ReturnAll = true
+ };
+
+ var response = otsClient.Search(request);
+
+ Console.WriteLine("Total Count:" + response.TotalCount);
+ foreach (var row in response.Rows)
+ {
+ PrintRow(row);
+ }
+ }
+ }
+}
diff --git a/netcore-sample/Samples/SingleRowReadWriteSample.cs b/netcore-sample/Samples/SingleRowReadWriteSample.cs
new file mode 100644
index 0000000..c5300d8
--- /dev/null
+++ b/netcore-sample/Samples/SingleRowReadWriteSample.cs
@@ -0,0 +1,239 @@
+using System;
+using System.Collections.Generic;
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using Aliyun.OTS.DataModel.ConditionalUpdate;
+using System.Threading.Tasks;
+
+namespace Aliyun.OTS.Samples
+{
+ public static class SingleRowReadWriteSample
+ {
+
+ private static readonly string TableName = "singleRowReadWriteSample";
+
+ private static void PrepareTable()
+ {
+ // 创建表
+ OTSClient otsClient = Config.GetClient();
+
+ IList tables = otsClient.ListTable(new ListTableRequest()).TableNames;
+ if (tables.Contains(TableName)) {
+ return;
+ }
+
+
+ PrimaryKeySchema primaryKeySchema = new PrimaryKeySchema
+ {
+ { "pk0", ColumnValueType.Integer },
+ { "pk1", ColumnValueType.String }
+ };
+ TableMeta tableMeta = new TableMeta(TableName, primaryKeySchema);
+
+ CapacityUnit reservedThroughput = new CapacityUnit(0, 0);
+ CreateTableRequest request = new CreateTableRequest(tableMeta, reservedThroughput);
+ otsClient.CreateTable(request);
+
+ }
+
+ public static void PutRow()
+ {
+ Console.WriteLine("Start put row...");
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(0) },
+ { "pk1", new ColumnValue("abc") }
+ };
+
+ // 定义要写入该行的属性列
+ AttributeColumns attribute = new AttributeColumns
+ {
+ { "col0", new ColumnValue(0) },
+ { "col1", new ColumnValue("a") },
+ { "col2", new ColumnValue(true) }
+ };
+ PutRowRequest request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.PutRow(request);
+ Console.WriteLine("Put row succeed.");
+ }
+
+ public static void PutRowAsync()
+ {
+ Console.WriteLine("Start put row async...");
+ PrepareTable();
+ OTSClient TabeStoreClient = Config.GetClient();
+
+ try
+ {
+ var putRowTaskList = new List>();
+ for (int i = 0; i < 100; i++)
+ {
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ var primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(i) },
+ { "pk1", new ColumnValue("abc") }
+ };
+
+ // 定义要写入改行的属性列
+ var attribute = new AttributeColumns
+ {
+ { "col0", new ColumnValue(i) },
+ { "col1", new ColumnValue("a") },
+ { "col2", new ColumnValue(true) }
+ };
+
+ var request = new PutRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE),
+ primaryKey, attribute);
+
+ putRowTaskList.Add(TabeStoreClient.PutRowAsync(request));
+ }
+
+ foreach (var task in putRowTaskList)
+ {
+ task.Wait();
+ Console.WriteLine("consumed read:{0}, write:{1}", task.Result.ConsumedCapacityUnit.Read,
+ task.Result.ConsumedCapacityUnit.Write);
+ }
+
+ Console.WriteLine("Put row async succeeded.");
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine("Put row async failed. exception:{0}", ex.Message);
+ }
+ }
+
+ public static void UpdateRow()
+ {
+ Console.WriteLine("Start update row...");
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(0) },
+ { "pk1", new ColumnValue("abc") }
+ };
+
+ // 定义要写入该行的属性列
+ UpdateOfAttribute attribute = new UpdateOfAttribute();
+ attribute.AddAttributeColumnToPut("col0", new ColumnValue(0));
+ attribute.AddAttributeColumnToPut("col1", new ColumnValue("b")); // 将原先的值'a'改为'b'
+ attribute.AddAttributeColumnToPut("col2", new ColumnValue(true));
+ UpdateRowRequest request = new UpdateRowRequest(TableName, new Condition(RowExistenceExpectation.IGNORE), primaryKey, attribute);
+
+ otsClient.UpdateRow(request);
+ Console.WriteLine("Update row succeed.");
+ }
+
+ private static string PrintColumnValue(ColumnValue value)
+ {
+ switch(value.Type)
+ {
+ case ColumnValueType.String: return value.StringValue;
+ case ColumnValueType.Integer: return value.IntegerValue.ToString();
+ case ColumnValueType.Boolean: return value.BooleanValue.ToString();
+ case ColumnValueType.Double: return value.DoubleValue.ToString();
+ case ColumnValueType.Binary: return value.BinaryValue.ToString();
+ }
+
+ throw new Exception("Unknow type.");
+ }
+
+ public static void GetRow()
+ {
+ Console.WriteLine("Start get row...");
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(0) },
+ { "pk1", new ColumnValue("abc") }
+ };
+
+ GetRowRequest request = new GetRowRequest(TableName, primaryKey); // 未指定读哪列,默认读整行
+ GetRowResponse response = otsClient.GetRow(request);
+ PrimaryKey primaryKeyRead = response.PrimaryKey;
+ AttributeColumns attributesRead = response.Attribute;
+
+ Console.WriteLine("Primary key read: ");
+ foreach(KeyValuePair entry in primaryKeyRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Attributes read: ");
+ foreach (KeyValuePair entry in attributesRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Get row succeed.");
+ }
+
+ public static void GetRowWithFilter()
+ {
+ Console.WriteLine("Start get row with filter ...");
+ PrepareTable();
+ OTSClient otsClient = Config.GetClient();
+
+ // 定义行的主键,必须与创建表时的TableMeta中定义的一致
+ PrimaryKey primaryKey = new PrimaryKey
+ {
+ { "pk0", new ColumnValue(0) },
+ { "pk1", new ColumnValue("abc") }
+ };
+
+ var rowQueryCriteria = new SingleRowQueryCriteria(TableName)
+ {
+ RowPrimaryKey = primaryKey
+ };
+
+ // 只返回col0的值等于5的行或者col1不等于ff的行
+ var filter1 = new RelationalCondition("col0",
+ CompareOperator.EQUAL,
+ new ColumnValue(5));
+
+ var filter2 = new RelationalCondition("col1", CompareOperator.NOT_EQUAL, new ColumnValue("ff"));
+
+ var filter = new CompositeCondition(LogicOperator.OR);
+ filter.AddCondition(filter1);
+ filter.AddCondition(filter2);
+
+ rowQueryCriteria.Filter = filter.ToFilter();
+ rowQueryCriteria.AddColumnsToGet("col0");
+ rowQueryCriteria.AddColumnsToGet("col1");
+
+ GetRowRequest request = new GetRowRequest(rowQueryCriteria);
+
+ // 查询
+ GetRowResponse response = otsClient.GetRow(request);
+ PrimaryKey primaryKeyRead = response.PrimaryKey;
+ AttributeColumns attributesRead = response.Attribute;
+
+ Console.WriteLine("Primary key read: ");
+ foreach (KeyValuePair entry in primaryKeyRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Attributes read: ");
+ foreach (KeyValuePair entry in attributesRead)
+ {
+ Console.WriteLine(entry.Key + ":" + PrintColumnValue(entry.Value));
+ }
+
+ Console.WriteLine("Get row with filter succeed.");
+ }
+ }
+}
diff --git a/netcore-sample/aliyun-tablestore-netcore-sdk-sample.csproj b/netcore-sample/aliyun-tablestore-netcore-sdk-sample.csproj
new file mode 100644
index 0000000..dc44945
--- /dev/null
+++ b/netcore-sample/aliyun-tablestore-netcore-sdk-sample.csproj
@@ -0,0 +1,17 @@
+
+
+
+ Exe
+ netcoreapp3.1
+ aliyun_tablestore_netcore_sdk_sample
+
+
+
+
+
+
+
+
+
+
+
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/AttributeColumns.cs b/netstandard-sdk/Aliyun/OTS/DataModel/AttributeColumns.cs
new file mode 100644
index 0000000..3ca4b82
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/AttributeColumns.cs
@@ -0,0 +1,99 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示若干属性列组成的属性。可以使用Add方法指定列名和列值来添加属性列。
+ ///
+ public class AttributeColumns : Dictionary
+ {
+ ///
+ /// 某些列会有多个版本的数据,需要把这些数据保存下来
+ ///
+ private readonly Dictionary> multiVersionColumns = new Dictionary>();
+
+ public static Dictionary ParseColumnArray(Column[] columns)
+ {
+ AttributeColumns keyValuePairs = new AttributeColumns();
+ foreach(var column in columns)
+ {
+ keyValuePairs.Add(column);
+ }
+
+ return keyValuePairs;
+ }
+
+ public void Add(Column column)
+ {
+ if (!this.ContainsKey(column.Name))
+ {
+ this.Add(column.Name, column.Value);
+ }
+ else
+ {
+ if(!this.multiVersionColumns.ContainsKey(column.Name))
+ {
+ this.multiVersionColumns.Add(column.Name, new List());
+ }
+
+ this.multiVersionColumns[column.Name].Add(column.Value);
+ }
+ }
+
+ ///
+ /// 得到某一列的多个版本的值
+ ///
+ /// The all column values.
+ /// Column name.
+ public List GetAllColumnValues(string columnName)
+ {
+ List columnValues = new List();
+ if(this.ContainsKey(columnName))
+ {
+ columnValues.Add(this[columnName]);
+ }
+
+ if(this.multiVersionColumns.ContainsKey(columnName))
+ {
+ columnValues.AddRange(this.multiVersionColumns[columnName]);
+ }
+
+ return columnValues;
+ }
+
+ ///
+ /// 得到所有返回值的版本
+ ///
+ /// The all attribute columns.
+ public Dictionary> GetAllAttributeColumns()
+ {
+ Dictionary> attributeColumns = new Dictionary>();
+
+ foreach(var key in this.Keys)
+ {
+ if(attributeColumns.ContainsKey(key))
+ {
+ attributeColumns[key].AddRange(this.multiVersionColumns[key]);
+ }
+ else
+ {
+ attributeColumns.Add(key, new List());
+ attributeColumns[key].Add(this[key]);
+ }
+ }
+
+ return attributeColumns;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/BloomFilterType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/BloomFilterType.cs
new file mode 100644
index 0000000..5091968
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/BloomFilterType.cs
@@ -0,0 +1,9 @@
+namespace Aliyun.OTS.DataModel
+{
+ public enum BloomFilterType
+ {
+ NONE = 1,
+ CELL = 2,
+ ROW = 3,
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/CapacityUnit.cs b/netstandard-sdk/Aliyun/OTS/DataModel/CapacityUnit.cs
new file mode 100644
index 0000000..093bfc8
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/CapacityUnit.cs
@@ -0,0 +1,48 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// CapacityUnit(读写能力单元)是OTS用来计量的单位。
+ ///
+ /// 请参见:阿里云官网关于读写能力单元的描述。
+ ///
+ ///
+ public class CapacityUnit
+ {
+ ///
+ /// 读能力单元
+ ///
+ public int? Read { get; set; }
+
+ ///
+ /// 写能力单元
+ ///
+ public int? Write { get; set; }
+
+ ///
+ /// CapacityUnit的构造函数。
+ ///
+ /// 当UpdateRow指定预留读写吞吐量时,读和写预留吞吐量可以指定其中一个,表示只调节一个值;也可以两个都指定。
+ /// 其他情况下构造CapacityUnit必须同时指定read和write参数。
+ ///
+ ///
+ /// 读能力单元
+ /// 写能力单元
+ public CapacityUnit(int? read = null, int? write = null)
+ {
+ Read = read;
+ Write = write;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Column.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Column.cs
new file mode 100644
index 0000000..bff4c43
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Column.cs
@@ -0,0 +1,69 @@
+using System;
+using Aliyun.OTS.Util;
+namespace Aliyun.OTS.DataModel
+{
+ /**
+ * TableStore中每行数据都包含主键({@link PrimaryKey}),
+ * 主键由多列主键列构成({@link PrimaryKeyColumn}),
+ * 每一个主键列包含主键列名称和主键列的值{@link PrimaryKeyValue}。
+ */
+ public class Column: PrimaryKeyColumn
+ {
+ ///
+ /// 序列化后占用的数据大小
+ ///
+ private int dataSize = -1;
+
+ ///
+ /// 属性列的时间戳
+ ///
+ public long? Timestamp { get; set; }
+
+ public static NameTimestampComparator NAME_TIMESTAMP_COMPARATOR = new NameTimestampComparator();
+
+ ///
+ /// 根据指定的主键列的名称和主键列的值构造主键列。
+ /// 主键列的名称不能为null pointer及空字符串。
+ /// 主键列的值不能为null pointer。
+ ///
+ /// 列名
+ /// 列值
+ public Column(string name, ColumnValue columnValue):base(name, columnValue)
+ {
+ }
+
+ ///
+ /// 构造一个属性列,必须包含名称、值和时间戳。
+ /// 属性列的名称不能为null pointer及空字符串。
+ /// 属性列的值不能为null pointer。
+ ///
+ /// 列名
+ /// 列值
+ /// 列的时间戳
+ public Column(String name, ColumnValue columnValue, long timestamp):this(name, columnValue)
+ {
+ this.Timestamp = timestamp;
+ }
+
+ public new int GetDataSize()
+ {
+ if (dataSize == -1)
+ {
+ int size = OtsUtils.CalcStringSizeInBytes(Name) + Value.GetDataSize();
+ if (this.Timestamp.HasValue)
+ {
+ size += 8;
+ }
+
+ dataSize = size;
+ }
+
+ return dataSize;
+ }
+
+ public override string ToString()
+ {
+ return "'" + Name + "':" + Value + "," + Timestamp;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ColumnValue.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ColumnValue.cs
new file mode 100644
index 0000000..8f5a2ef
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ColumnValue.cs
@@ -0,0 +1,297 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+using com.alicloud.openservices.tablestore.core.protocol;
+using System.IO;
+using Aliyun.OTS.Util;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示一个列值,包含类型和值。
+ ///
+ public class ColumnValue : IComparable, IMeasurable
+ {
+ ///
+ /// 表示一个最大值(不分类型)
+ ///
+ public readonly static ColumnValue INF_MAX = new ColumnValue("INF_MAX");
+
+ ///
+ /// 表示一个最小值(不分类型)
+ ///
+ public readonly static ColumnValue INF_MIN = new ColumnValue("INF_MIN");
+
+ ///
+ /// 表示一个自增值(不分类型)
+ ///
+ public readonly static ColumnValue AUTO_INCREMENT = new ColumnValue("AUTO_INCREMENT");
+
+ ///
+ /// 列值的类型
+ ///
+ public ColumnValueType Type { get; private set; }
+
+ public Int64 IntegerValue;
+ public string StringValue;
+ public bool BooleanValue = true;
+ public double DoubleValue;
+ public byte[] BinaryValue;
+
+ private ColumnValue()
+ {
+ }
+
+ ///
+ /// 构造一个整数类型的列值。
+ ///
+ ///
+ public ColumnValue(Int64 value)
+ {
+ Type = ColumnValueType.Integer;
+ IntegerValue = value;
+ }
+
+ public ColumnValue(ulong value)
+ {
+ Type = ColumnValueType.Integer;
+ IntegerValue = (Int64)value;
+ }
+
+ ///
+ /// 构造一个字符串类型的列值。
+ ///
+ ///
+ public ColumnValue(string value)
+ {
+ Type = ColumnValueType.String;
+ StringValue = value;
+ }
+
+ ///
+ /// 构造一个布尔类型的列值。
+ ///
+ ///
+ public ColumnValue(bool value)
+ {
+ Type = ColumnValueType.Boolean;
+ BooleanValue = value;
+ }
+
+ ///
+ /// 构造一个浮点类型的列值。
+ ///
+ ///
+ public ColumnValue(double value)
+ {
+ Type = ColumnValueType.Double;
+ DoubleValue = value;
+ }
+
+ ///
+ /// 构造一个二进制串类型的列值。
+ ///
+ ///
+ public ColumnValue(byte[] value)
+ {
+ Type = ColumnValueType.Binary;
+ BinaryValue = value;
+ }
+
+ ///
+ /// 这个column value是否可以为 primary key value
+ ///
+ /// true, column value类型可以成为primary key, false otherwise.
+ public bool CanBePrimaryKeyValue()
+ {
+ switch (this.Type)
+ {
+ case ColumnValueType.String:
+ case ColumnValueType.Integer:
+ case ColumnValueType.Binary:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public byte[] AsStringInBytes()
+ {
+ return System.Text.Encoding.UTF8.GetBytes(this.StringValue);
+ }
+
+ public bool IsInfMin()
+ {
+ return this.StringValue == "INF_MIN";
+ }
+
+ public bool IsInfMax()
+ {
+ return this.StringValue == "INF_MAX";
+ }
+
+ public bool IsPlaceHolderForAutoIncr()
+ {
+ return this.StringValue == "AUTO_INCREMENT";
+ }
+
+ ///
+ /// 采用crc8算法得到一个checksum,主要用于计算cell的checksum
+ ///
+ /// The checksum.
+ /// Crc.
+ public byte GetChecksum(byte crc)
+ {
+ if (IsInfMin())
+ {
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_INF_MIN);
+ return crc;
+ }
+
+ if (IsInfMax())
+ {
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_INF_MAX);
+ return crc;
+ }
+
+ if (IsPlaceHolderForAutoIncr())
+ {
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_AUTO_INCREMENT);
+ return crc;
+ }
+
+ switch (this.Type)
+ {
+ case ColumnValueType.String:
+ {
+ byte[] rawData = AsStringInBytes();
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_STRING);
+ crc = PlainBufferCrc8.crc8(crc, rawData.Length);
+ crc = PlainBufferCrc8.crc8(crc, rawData);
+ break;
+ }
+ case ColumnValueType.Integer:
+ {
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_INTEGER);
+ crc = PlainBufferCrc8.crc8(crc, (long)this.IntegerValue);
+ break;
+ }
+ case ColumnValueType.Binary:
+ {
+ byte[] rawData = this.BinaryValue;
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_BLOB);
+ crc = PlainBufferCrc8.crc8(crc, rawData.Length);
+ crc = PlainBufferCrc8.crc8(crc, rawData);
+ break;
+ }
+ case ColumnValueType.Double:
+ {
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_DOUBLE);
+ crc = PlainBufferCrc8.crc8(crc, BitConverter.DoubleToInt64Bits(this.DoubleValue));
+ break;
+ }
+ case ColumnValueType.Boolean:
+ {
+ crc = PlainBufferCrc8.crc8(crc, PlainBufferConsts.VT_BOOLEAN);
+ crc = PlainBufferCrc8.crc8(crc, this.BooleanValue ? (byte)0x1 : (byte)0x0);
+ break;
+ }
+ default:
+ throw new IOException("Bug: unsupported column type: " + this.Type);
+ }
+
+ return crc;
+ }
+
+ public int GetDataSize()
+ {
+ int dataSize = 0;
+ switch (this.Type)
+ {
+ case ColumnValueType.Integer:
+ dataSize = 8;
+ break;
+ case ColumnValueType.String:
+
+ dataSize = this.StringValue == null ? 0 : OtsUtils.CalcStringSizeInBytes(this.StringValue);
+ break;
+ case ColumnValueType.Binary:
+ dataSize = this.BinaryValue.Length;
+ break;
+ case ColumnValueType.Double:
+ dataSize = 8;
+ break;
+ case ColumnValueType.Boolean:
+ dataSize = 1;
+ break;
+ default:
+ throw new TypeLoadException("Bug: not support the type : " + this.Type);
+ }
+
+ return dataSize;
+ }
+
+ public int CompareTo(Object obj)
+ {
+ var target = obj as ColumnValue;
+
+ if (this.Type != target.Type)
+ {
+ throw new ArgumentException("The type of column to compare must be the same.");
+ }
+
+ switch (this.Type)
+ {
+ case ColumnValueType.String:
+ return string.Compare(this.StringValue, target.StringValue, StringComparison.Ordinal);
+ case ColumnValueType.Integer:
+ return this.IntegerValue.CompareTo(target.IntegerValue);
+ case ColumnValueType.Binary:
+ int ret = OtsUtils.CompareByteArrayInLexOrder(this.BinaryValue, 0, this.BinaryValue.Length, target.BinaryValue, 0, target.BinaryValue.Length);
+ return ret;
+ case ColumnValueType.Double:
+ return this.DoubleValue.CompareTo(target.DoubleValue);
+ case ColumnValueType.Boolean:
+ return this.BooleanValue.CompareTo(target.BooleanValue);
+ default:
+ throw new ArgumentException("Unknown type: " + this.Type);
+ }
+ }
+
+ public override string ToString()
+ {
+ string result = "";
+ switch (Type)
+ {
+ case ColumnValueType.String:
+ result = StringValue + "(string)";
+ break;
+ case ColumnValueType.Integer:
+ result = IntegerValue + "(int)";
+ break;
+ case ColumnValueType.Binary:
+ result = BinaryValue + "(binary)";
+ break;
+ case ColumnValueType.Double:
+ result = DoubleValue + "(double)";
+ break;
+ case ColumnValueType.Boolean:
+ result = BooleanValue + "(boolean)";
+ break;
+ default:
+ throw new ArgumentException("Unknown type: " + this.Type);
+ }
+
+ return result;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ColumnValueType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ColumnValueType.cs
new file mode 100644
index 0000000..2e3e827
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ColumnValueType.cs
@@ -0,0 +1,33 @@
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 列值的类型枚举定义
+ ///
+ public enum ColumnValueType
+ {
+ ///
+ /// 整数类型
+ ///
+ Integer = 1,
+
+ ///
+ /// 字符串类型
+ ///
+ String = 2,
+
+ ///
+ /// 二进制串类型
+ ///
+ Binary = 3,
+
+ ///
+ /// 布尔类型
+ ///
+ Boolean,
+
+ ///
+ /// 浮点数类型
+ ///
+ Double,
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/CompareOperator.cs b/netstandard-sdk/Aliyun/OTS/DataModel/CompareOperator.cs
new file mode 100644
index 0000000..ec3538b
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/CompareOperator.cs
@@ -0,0 +1,7 @@
+namespace Aliyun.OTS.DataModel
+{
+ public enum CompareOperator
+ {
+ EQUAL, NOT_EQUAL, GREATER_THAN, GREATER_EQUAL, LESS_THAN, LESS_EQUAL
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Condition.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Condition.cs
new file mode 100644
index 0000000..dab4bbe
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Condition.cs
@@ -0,0 +1,36 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using Aliyun.OTS.DataModel.ConditionalUpdate;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 写操作(包括、、
+ /// 和)
+ /// 的检查条件。当检查条件满足时,响应的操作才会执行;否则操作出错。
+ ///
+ public class Condition
+ {
+ ///
+ /// condition update的新接口
+ ///
+ public RowExistenceExpectation RowExistenceExpect { get; set; }
+ public IColumnCondition ColumnCondition { get; set; }
+
+ public Condition() { }
+
+ public Condition(RowExistenceExpectation rowExist)
+ {
+ RowExistenceExpect = rowExist;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnCondition.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnCondition.cs
new file mode 100644
index 0000000..bbd2540
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnCondition.cs
@@ -0,0 +1,7 @@
+namespace Aliyun.OTS.DataModel.ConditionalUpdate
+{
+ public interface ColumnCondition
+ {
+ ColumnConditionType GetType();
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnConditionType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnConditionType.cs
new file mode 100644
index 0000000..1953bb5
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/ColumnConditionType.cs
@@ -0,0 +1,8 @@
+namespace Aliyun.OTS.DataModel.ConditionalUpdate
+{
+ public enum ColumnConditionType
+ {
+ COMPOSITE_CONDITION,
+ RELATIONAL_CONDITION // same as SINGLE_COLUMN_VALUE_CONDITION
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/CompositeCondition.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/CompositeCondition.cs
new file mode 100644
index 0000000..46466b8
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/CompositeCondition.cs
@@ -0,0 +1,54 @@
+using System.Collections.Generic;
+using Google.ProtocolBuffers;
+using Aliyun.OTS.DataModel.Filter;
+
+namespace Aliyun.OTS.DataModel.ConditionalUpdate
+{
+ public class CompositeCondition : IColumnCondition
+ {
+ private List subConditions;
+
+ public LogicOperator LogicOperator { get; set; }
+
+ public List SubConditions
+ {
+ get { return subConditions; }
+ }
+
+ public CompositeCondition(LogicOperator logicOperator)
+ {
+ LogicOperator = logicOperator;
+ subConditions = new List();
+ }
+
+ public CompositeCondition AddCondition(IColumnCondition condition)
+ {
+ subConditions.Add(condition);
+ return this;
+ }
+
+ public void Clear() { subConditions.Clear(); }
+
+ public ColumnConditionType GetConditionType()
+ {
+ return ColumnConditionType.COMPOSITE_CONDITION;
+ }
+
+ public ByteString Serialize()
+ {
+ return ToFilter().Serialize();
+ }
+
+ public IFilter ToFilter()
+ {
+ CompositeColumnValueFilter compositeColumnValueFilter = new CompositeColumnValueFilter(LogicOperator);
+
+ foreach (IColumnCondition condition in SubConditions)
+ {
+ compositeColumnValueFilter.AddFilter(condition.ToFilter());
+ }
+
+ return compositeColumnValueFilter;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/IColumnCondition.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/IColumnCondition.cs
new file mode 100644
index 0000000..c099196
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/IColumnCondition.cs
@@ -0,0 +1,12 @@
+using Google.ProtocolBuffers;
+using Aliyun.OTS.DataModel.Filter;
+
+namespace Aliyun.OTS.DataModel.ConditionalUpdate
+{
+ public interface IColumnCondition
+ {
+ ColumnConditionType GetConditionType();
+ ByteString Serialize();
+ IFilter ToFilter();
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/RelationalCondition.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/RelationalCondition.cs
new file mode 100644
index 0000000..8290b35
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ConditionalUpdate/RelationalCondition.cs
@@ -0,0 +1,46 @@
+using Google.ProtocolBuffers;
+using Aliyun.OTS.DataModel.Filter;
+
+namespace Aliyun.OTS.DataModel.ConditionalUpdate
+{
+ public class RelationalCondition : IColumnCondition
+ {
+ public CompareOperator Operator { get; set; }
+ public string ColumnName { get;set;}
+ public ColumnValue ColumnValue { get; set; }
+ public bool PassIfMissing {get;set;}
+ public bool LatestVersionsOnly { get; set; }
+
+ public RelationalCondition(string columnName, CompareOperator oper, ColumnValue columnValue)
+ {
+ Operator = oper;
+ ColumnName = columnName;
+ ColumnValue = columnValue;
+ PassIfMissing = true;
+ LatestVersionsOnly = true;
+ }
+
+ public ColumnConditionType GetConditionType()
+ {
+ return ColumnConditionType.RELATIONAL_CONDITION;
+ }
+
+ public ByteString Serialize()
+ {
+
+ return ToFilter().Serialize();
+ }
+
+ public IFilter ToFilter()
+ {
+
+ SingleColumnValueFilter singleColumnValueFilter = new SingleColumnValueFilter(ColumnName, Operator, ColumnValue)
+ {
+ LatestVersionsOnly = LatestVersionsOnly,
+ PassIfMissing = PassIfMissing
+ };
+
+ return singleColumnValueFilter;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnSchema.cs b/netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnSchema.cs
new file mode 100644
index 0000000..ccd5ff8
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnSchema.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ public class DefinedColumnSchema : List>
+ {
+ ///
+ /// 添加一个预定义列的设计
+ ///
+ ///
+ ///
+ public void Add(string name, DefinedColumnType type)
+ {
+ var tuple = new Tuple(name, type);
+
+ Add(tuple);
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnType.cs
new file mode 100644
index 0000000..661c602
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/DefinedColumnType.cs
@@ -0,0 +1,15 @@
+namespace Aliyun.OTS.DataModel
+{
+ public enum DefinedColumnType
+ {
+ INTEGER,
+
+ DOUBLE,
+
+ BOOLEAN,
+
+ STRING,
+
+ BINARY
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Filter/ColumnPaginationFilter.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/ColumnPaginationFilter.cs
new file mode 100644
index 0000000..0d0414d
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/ColumnPaginationFilter.cs
@@ -0,0 +1,35 @@
+using System;
+using Google.ProtocolBuffers;
+using PB = com.alicloud.openservices.tablestore.core.protocol;
+
+namespace Aliyun.OTS.DataModel.Filter
+{
+ public class ColumnPaginationFilter : IFilter
+ {
+ public int Limit { get; set; }
+ public int Offset { get; set; }
+
+ public ColumnPaginationFilter(int limit) : this(limit, 0)
+ {
+ }
+
+ public ColumnPaginationFilter(int limit, int offset)
+ {
+ this.Limit = limit;
+ this.Offset = offset;
+ }
+
+ public FilterType GetFilterType()
+ {
+ return FilterType.COLUMN_PAGINATION_FILTER;
+ }
+
+ public ByteString Serialize()
+ {
+ PB.ColumnPaginationFilter.Builder builder = PB.ColumnPaginationFilter.CreateBuilder();
+ builder.SetLimit(this.Limit);
+ builder.SetOffset(this.Offset);
+ return builder.Build().ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Filter/CompositeColumnValueFilter.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/CompositeColumnValueFilter.cs
new file mode 100644
index 0000000..2d3c545
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/CompositeColumnValueFilter.cs
@@ -0,0 +1,128 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using PB = com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Filter
+{
+ /**
+ * TableStore查询操作时使用的过滤器,CompositeColumnValueFilter用于表示ColumnValueFilter之间的逻辑关系条件,主要有NOT、AND和OR三种逻辑关系条件,其中NOT和AND表示二元或多元的关系,NOT只表示一元的关系。
+ * 逻辑关系通过构造函数{@link CompositeColumnValueFilter#CompositeColumnValueFilter(CompositeColumnValueFilter.LogicOperator)}的参数提供。
+ * 若逻辑关系为{@link CompositeColumnValueFilter.LogicOperator#NOT},可以通过{@link CompositeColumnValueFilter#addFilter(ColumnValueFilter)}添加ColumnValueFilter,添加的ColumnValueFilter有且只有一个。
+ * 若逻辑关系为{@link CompositeColumnValueFilter.LogicOperator#AND},可以通过{@link CompositeColumnValueFilter#addFilter(ColumnValueFilter)}添加ColumnValueFilter,添加的ColumnValueFilter必须大于等于两个。
+ * 若逻辑关系为{@link CompositeColumnValueFilter.LogicOperator#OR},可以通过{@link CompositeColumnValueFilter#addFilter(ColumnValueFilter)}添加ColumnValueFilter,添加的ColumnValueFilter必须大于等于两个。
+ */
+ public class CompositeColumnValueFilter : IFilter
+ {
+ private readonly LogicOperator type;
+ private readonly List filters;
+
+ public CompositeColumnValueFilter(LogicOperator loType)
+ {
+ this.type = loType;
+ this.filters = new List();
+ }
+
+ ///
+ /// 增加逻辑关系组中的ColumnValueFilter。
+ /// 若逻辑关系为{@link CompositeColumnValueFilter.LogicOperator#NOT},有且只能添加一个ColumnValueFilter。
+ /// 若逻辑关系为{@link CompositeColumnValueFilter.LogicOperator#AND},必须添加至少两个ColumnValueFilter。
+ /// 若逻辑关系为{ @link CompositeColumnValueFilter.LogicOperator#OR},必须添加至少两个ColumnValueFilter。
+ ///
+ /// The Composite filter.
+ /// Filter.
+ public CompositeColumnValueFilter AddFilter(IFilter filter)
+ {
+ Contract.Requires(filter != null);
+ this.filters.Add(filter);
+ return this;
+ }
+
+ public void Clear()
+ {
+ this.filters.Clear();
+ }
+
+ ///
+ /// 查看当前设置的逻辑关系
+ ///
+ /// 逻辑关系符号
+ public LogicOperator GetOperationType()
+ {
+ return this.type;
+ }
+
+ ///
+ /// 返回逻辑关系组中的所有ColumnValueFilter。
+ ///
+ /// The sub filters.
+ public List GetSubFilters()
+ {
+ return this.filters;
+ }
+
+
+ public FilterType GetFilterType()
+ {
+ return FilterType.COMPOSITE_COLUMN_VALUE_FILTER;
+ }
+
+
+ public ByteString Serialize()
+ {
+ return BuildCompositeColumnValueFilter(this);
+ }
+
+ private static ByteString BuildCompositeColumnValueFilter(CompositeColumnValueFilter filter)
+ {
+ PB.CompositeColumnValueFilter.Builder builder = PB.CompositeColumnValueFilter.CreateBuilder();
+ builder.SetCombinator(ToPBLogicalOperator(filter.GetOperationType()));
+
+ foreach (IFilter f in filter.GetSubFilters())
+ {
+ builder.AddSubFilters(ToPBFilter(f));
+ }
+
+ return builder.Build().ToByteString();
+ }
+
+ private static PB.LogicalOperator ToPBLogicalOperator(LogicOperator type)
+ {
+ switch (type)
+ {
+ case LogicOperator.NOT:
+ return PB.LogicalOperator.LO_NOT;
+ case LogicOperator.AND:
+ return PB.LogicalOperator.LO_AND;
+ case LogicOperator.OR:
+ return PB.LogicalOperator.LO_OR;
+ default:
+ throw new ArgumentException("Unknown logic operation type: " + type);
+ }
+ }
+
+ private static PB.Filter ToPBFilter(IFilter f)
+ {
+ PB.Filter.Builder builder = PB.Filter.CreateBuilder();
+ builder.SetType(ToPBFilterType(f.GetFilterType()));
+ builder.SetFilter_(f.Serialize());
+ return builder.Build();
+ }
+
+ private static PB.FilterType ToPBFilterType(FilterType type)
+ {
+ switch (type)
+ {
+ case FilterType.COMPOSITE_COLUMN_VALUE_FILTER:
+ return PB.FilterType.FT_COMPOSITE_COLUMN_VALUE;
+ case FilterType.SINGLE_COLUMN_VALUE_FILTER:
+ return PB.FilterType.FT_SINGLE_COLUMN_VALUE;
+ case FilterType.COLUMN_PAGINATION_FILTER:
+ return PB.FilterType.FT_COLUMN_PAGINATION;
+ default:
+ throw new ArgumentException("Unknown filter type: " + type);
+ }
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Filter/FilterType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/FilterType.cs
new file mode 100644
index 0000000..0865212
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/FilterType.cs
@@ -0,0 +1,10 @@
+using System;
+namespace Aliyun.OTS.DataModel.Filter
+{
+ public enum FilterType
+ {
+ SINGLE_COLUMN_VALUE_FILTER,
+ COMPOSITE_COLUMN_VALUE_FILTER,
+ COLUMN_PAGINATION_FILTER
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Filter/IFilter.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/IFilter.cs
new file mode 100644
index 0000000..a670e60
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/IFilter.cs
@@ -0,0 +1,12 @@
+using System;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Filter
+{
+ public interface IFilter
+ {
+ FilterType GetFilterType();
+
+ ByteString Serialize();
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Filter/SingleColumnValueFilter.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/SingleColumnValueFilter.cs
new file mode 100644
index 0000000..3303bed
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Filter/SingleColumnValueFilter.cs
@@ -0,0 +1,93 @@
+using System.IO;
+using Google.ProtocolBuffers;
+using System;
+using PB = com.alicloud.openservices.tablestore.core.protocol;
+namespace Aliyun.OTS.DataModel.Filter
+{
+ ///
+ /// TableStore查询操作时使用的过滤器,SingleColumnValueFilter用于表示查询的行内数据列和数据值的比较关系。
+ /// 可以表示的列与值的比较关系包括:EQUAL(=), NOT_EQUAL(!=), GREATER_THAN(>), GREATER_EQUAL(>=), LESS_THAN(<)以及LESS_EQUAL(<=)。
+ /// 由于TableStore一行的属性列不固定,有可能存在有filter条件的列在该行不存在的情况,这时{@link SingleColumnValueFilter#passIfMissing}参数控制在这种情况下对该行的过滤结果。
+ /// 如果设置
+ /// {@link SingleColumnValueFilter#passIfMissing}为true,则若列在该行中不存在,则返回该行;
+ /// 如果设置{@ref SingleColumnValueFilter#passIfMissing}为false,则若列在该行中不存在,则不返回该行。
+ /// 默认值为true。
+ /// < p > 由于TableStore的属性列可能有多个版本,有可能存在该列的一个版本的值与给定值匹配但是另一个版本的值不匹配的情况, p >
+ /// 这时{@link SingleColumnValueFilter#latestVersionsOnly}参数控制在这种情况下对该行的过滤结果。
+ /// 如果设置{@link SingleColumnValueFilter#latestVersionsOnly}为true,则只会对最新版本的值进行比较,否则会对该列的所有版本(最新的max_versions个)进行比较,
+ /// 只要有一个版本的值匹配就认为条件成立。默认值为true。
+ ///
+ public class SingleColumnValueFilter : IFilter
+ {
+ public CompareOperator CompareOperator { get; set; }
+ public string ColumnName { get; set; }
+ public ColumnValue ColumnValue { get; set; }
+ public bool PassIfMissing { get; set;}
+ public bool LatestVersionsOnly { get; set; }
+
+ ///
+ /// 构造函数。
+ ///
+ /// 列的名称
+ /// 比较函数
+ /// 列的值
+ public SingleColumnValueFilter(string columnName, CompareOperator compareOperator, ColumnValue columnValue)
+ {
+ ColumnName = columnName;
+ CompareOperator = compareOperator;
+ ColumnValue = columnValue;
+ PassIfMissing = true;
+ LatestVersionsOnly = true;
+ }
+
+ public FilterType GetFilterType()
+ {
+ return FilterType.SINGLE_COLUMN_VALUE_FILTER;
+ }
+
+ public ByteString Serialize()
+ {
+ return BuildSingleColumnValueFilter(this);
+ }
+
+ private static ByteString BuildSingleColumnValueFilter(SingleColumnValueFilter filter)
+ {
+ PB.SingleColumnValueFilter.Builder builder = PB.SingleColumnValueFilter.CreateBuilder();
+ builder.SetColumnName(filter.ColumnName);
+ builder.SetComparator(ToComparatorType(filter.CompareOperator));
+ try
+ {
+ builder.SetColumnValue(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildColumnValueWithoutLengthPrefix(filter.ColumnValue)));
+ }
+ catch (IOException e)
+ {
+ throw new OTSClientException("Bug: serialize column value failed." + e.Message);
+ }
+
+ builder.SetFilterIfMissing(!filter.PassIfMissing);
+ builder.SetLatestVersionOnly(filter.LatestVersionsOnly);
+
+ return builder.Build().ToByteString();
+ }
+
+ private static PB.ComparatorType ToComparatorType(CompareOperator compareOperator)
+ {
+ switch (compareOperator) {
+ case CompareOperator.EQUAL:
+ return PB.ComparatorType.CT_EQUAL;
+ case CompareOperator.NOT_EQUAL:
+ return PB.ComparatorType.CT_NOT_EQUAL;
+ case CompareOperator.GREATER_THAN:
+ return PB.ComparatorType.CT_GREATER_THAN;
+ case CompareOperator.GREATER_EQUAL:
+ return PB.ComparatorType.CT_GREATER_EQUAL;
+ case CompareOperator.LESS_THAN:
+ return PB.ComparatorType.CT_LESS_THAN;
+ case CompareOperator.LESS_EQUAL:
+ return PB.ComparatorType.CT_LESS_EQUAL;
+ default:
+ throw new ArgumentException("Unknown compare operator: " + compareOperator);
+ }
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/IMeasurable.cs b/netstandard-sdk/Aliyun/OTS/DataModel/IMeasurable.cs
new file mode 100644
index 0000000..f9ca7dc
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/IMeasurable.cs
@@ -0,0 +1,11 @@
+namespace Aliyun.OTS.DataModel
+{
+ public interface IMeasurable
+ {
+ ///
+ /// 序列化后占用的数据大小
+ ///
+ /// 序列化后占用的数据大小
+ int GetDataSize();
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/IRow.cs b/netstandard-sdk/Aliyun/OTS/DataModel/IRow.cs
new file mode 100644
index 0000000..78a5aad
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/IRow.cs
@@ -0,0 +1,8 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ public interface IRow : IComparable
+ {
+ PrimaryKey GetPrimaryKey();
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/IndexMeta.cs b/netstandard-sdk/Aliyun/OTS/DataModel/IndexMeta.cs
new file mode 100644
index 0000000..9970fa3
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/IndexMeta.cs
@@ -0,0 +1,25 @@
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 索引表的结构信息,包含索引表的名称以及索引表的主键及预定义列定义
+ ///
+ public class IndexMeta
+ {
+ public string IndexName { get; set; }
+
+ public List PrimaryKey { get; set; }
+
+ public List DefinedColumns { get; set; }
+
+ public IndexUpdateMode IndexUpdateModel { get; set; }
+
+ public IndexType IndexType { get; set; }
+
+ public IndexMeta(string indexName)
+ {
+ this.IndexName = indexName;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/IndexType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/IndexType.cs
new file mode 100644
index 0000000..203c48c
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/IndexType.cs
@@ -0,0 +1,13 @@
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示索引类型
+ ///
+ public enum IndexType
+ {
+ ///
+ /// 全局索引
+ ///
+ IT_GLOBAL_INDEX
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/IndexUpdateMode.cs b/netstandard-sdk/Aliyun/OTS/DataModel/IndexUpdateMode.cs
new file mode 100644
index 0000000..ff7062a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/IndexUpdateMode.cs
@@ -0,0 +1,13 @@
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示索引更新模式
+ ///
+ public enum IndexUpdateMode
+ {
+ ///
+ /// 异步更新索引
+ ///
+ IUM_ASYNC_INDEX
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/LogicOperator.cs b/netstandard-sdk/Aliyun/OTS/DataModel/LogicOperator.cs
new file mode 100644
index 0000000..f242809
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/LogicOperator.cs
@@ -0,0 +1,7 @@
+namespace Aliyun.OTS.DataModel
+{
+ public enum LogicOperator
+ {
+ NOT, AND, OR,
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/MultiRowQueryCriteria.cs b/netstandard-sdk/Aliyun/OTS/DataModel/MultiRowQueryCriteria.cs
new file mode 100644
index 0000000..8c18a12
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/MultiRowQueryCriteria.cs
@@ -0,0 +1,128 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ */
+
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ ///从TableStore表中查询多行数据所需的参数,可以支持以下几种读取行为:
+ ///
+ ///- 读取某些列或所有列的某个特定版本
+ ///- 读取某些列或所有列的某个版本范围内的所有版本或最大的N个版本
+ ///- 读取某些列或所有列的最大的N个版本(N最小为 1,最大为MaxVersions)
+ ///
+ ///注意:读取参数不能为每行单独设置,多行必须使用相同的查询参数。
+ ///
+ ///
+ public class MultiRowQueryCriteria : RowQueryCriteria
+ {
+ private List rowPrimaryKeys = new List();
+ private List tokens;
+
+ ///
+ /// 构造一个在给定名称的表中查询的条件
+ ///
+ ///
+ public MultiRowQueryCriteria(string tableName)
+ : base(tableName)
+ {
+ rowPrimaryKeys = new List();
+ tokens = new List();
+ }
+
+ ///
+ /// 向多行查询条件中插入要查询的行的主键
+ ///
+ /// 要查询的行的主键
+ public void AddRowKey(PrimaryKey primaryKey)
+ {
+ AddRowKey(primaryKey, new byte[0]);
+ }
+
+ public void AddRowKey(PrimaryKey primaryKey, byte[] token)
+ {
+ this.rowPrimaryKeys.Add(primaryKey);
+ this.tokens.Add(token);
+ }
+
+ ///
+ /// 设置该表中所有要查询的行的主键
+ ///
+ /// 所有行的主键
+ public void SetRowKeys(List primaryKeys)
+ {
+ rowPrimaryKeys = primaryKeys;
+ for (int i = 0; i < primaryKeys.Count; i++)
+ {
+ tokens.Add(new byte[0]);
+ }
+ }
+
+ ///
+ /// 获取该表中所要要查询的行的主键。
+ ///
+ /// 所有行的主键。
+ public List GetRowKeys()
+ {
+ return rowPrimaryKeys;
+ }
+
+ public List GetTokens()
+ {
+ return tokens;
+ }
+
+ ///
+ /// 获取某行的主键,若该行index不存在,则返回null。
+ ///
+ /// 该行的索引
+ /// 若该行存在,则返回该行主键,否则返回null
+ public PrimaryKey Get(int index)
+ {
+ if (index < rowPrimaryKeys.Count())
+ {
+ return rowPrimaryKeys[index];
+ }
+
+ return null;
+ }
+
+ ///
+ /// 清空要查询的所有行
+ ///
+ public void Clear()
+ {
+ rowPrimaryKeys.Clear();
+ }
+
+ ///
+ /// 获取要查询的行的个数。
+ ///
+ /// The size.
+ public int Size()
+ {
+ return rowPrimaryKeys.Count;
+ }
+
+ public bool IsEmpty()
+ {
+ return rowPrimaryKeys.Count == 0;
+ }
+
+ public MultiRowQueryCriteria CloneWithoutRowKeys()
+ {
+ MultiRowQueryCriteria newCriteria = new MultiRowQueryCriteria(this.TableName);
+ this.CopyTo(newCriteria);
+ return newCriteria;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/NameTimestampComparator.cs b/netstandard-sdk/Aliyun/OTS/DataModel/NameTimestampComparator.cs
new file mode 100644
index 0000000..f560d8e
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/NameTimestampComparator.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections;
+namespace Aliyun.OTS.DataModel
+{
+ public class NameTimestampComparator: IComparer
+ {
+ public int Compare(Object obj1, Object obj2)
+ {
+ var c1 = obj1 as Column;
+ var c2 = obj2 as Column;
+ int ret = string.Compare(c1.Name, c2.Name, StringComparison.Ordinal);
+
+ if (ret != 0)
+ {
+ return ret;
+ }
+
+ long t1 = c1.Timestamp.Value;
+ long t2 = c2.Timestamp.Value;
+ return t1 == t2 ? 0 : (t1 < t2 ? 1 : -1);
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/PartitionRange.cs b/netstandard-sdk/Aliyun/OTS/DataModel/PartitionRange.cs
new file mode 100644
index 0000000..273ec57
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/PartitionRange.cs
@@ -0,0 +1,24 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ public class PartitionRange
+ {
+ ///
+ /// 范围的起始值
+ ///
+ /// The begin.
+ public ColumnValue Begin { get; set; }
+
+ ///
+ /// 范围的结束值
+ ///
+ /// The end.
+ public ColumnValue End { get; set; }
+
+ public PartitionRange(ColumnValue begin, ColumnValue end)
+ {
+ Begin = begin;
+ End = end;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKey.cs b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKey.cs
new file mode 100644
index 0000000..4bf5446
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKey.cs
@@ -0,0 +1,112 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using Aliyun.OTS.Util;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示若干主键列组成的主键。可以使用Add方法指定列名和列值来添加主键列。
+ ///
+ public class PrimaryKey : Dictionary, IComparable, IMeasurable
+ {
+ ///
+ /// 获取所有的主键列。
+ /// 主键中包含的主键列的个数以及主键列的顺序与创建表时TableMeta中定义的一致。
+ ///
+ /// The primary key columns.
+ public PrimaryKeyColumn[] GetPrimaryKeyColumns()
+ {
+ if (this == null)
+ {
+ return null;
+ }
+
+ PrimaryKeyColumn[] keyColumns = new PrimaryKeyColumn[this.Count];
+
+ var enumerator = this.GetEnumerator();
+
+ for (var i = 0; enumerator.MoveNext();i++)
+ {
+ keyColumns[i] = new PrimaryKeyColumn(enumerator.Current);
+ }
+
+ return keyColumns;
+ }
+
+ ///
+ /// 获取行主键的数据大小总和,大小总和包括所有主键列的名称和值。
+ ///
+ /// 行主键的数据大小总和
+ public int GetDataSize()
+ {
+ if (this.Keys == null)
+ {
+ return 0;
+ }
+
+
+ int size = 0;
+ foreach (var key in this.Keys)
+ {
+ size += OtsUtils.CalcStringSizeInBytes(key);
+ size += this[key].GetDataSize();
+ }
+
+ return size;
+ }
+
+ public override string ToString()
+ {
+ var primaryColumns = GetPrimaryKeyColumns();
+ string result = "";
+
+ if(primaryColumns == null)
+ {
+ return result;
+ }
+
+ foreach(var col in primaryColumns)
+ {
+ result += col + ",";
+ }
+
+ return result;
+ }
+
+ ///
+ /// 比较两个主键
+ /// 对比的两个主键必须为相同的schema,即列数、主键名称和顺序都完全一致。
+ ///
+ /// 比较结果
+ /// Target.
+ public int CompareTo(PrimaryKey target)
+ {
+ if (this.Keys.Count != target.Keys.Count)
+ {
+ throw new ArgumentException("The schema of the two primary key compared is not the same.");
+ }
+
+ for (int i = 0; i < this.Count; i++)
+ {
+ int ret = string.Compare(this.Keys.GetEnumerator().Current, target.Keys.GetEnumerator().Current, StringComparison.Ordinal);
+ if (ret != 0)
+ {
+ return ret;
+ }
+ }
+
+ return 0;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyColumn.cs b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyColumn.cs
new file mode 100644
index 0000000..6601cc0
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyColumn.cs
@@ -0,0 +1,109 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+using Aliyun.OTS.Util;
+namespace Aliyun.OTS.DataModel
+{
+ public class PrimaryKeyColumn : IComparable, IMeasurable
+ {
+ ///
+ /// 主键列名
+ ///
+ /// The name.
+ public string Name { get; set; }
+
+ ///
+ /// 列值
+ ///
+ public ColumnValue Value { get; set; }
+
+ ///
+ /// 序列化后占用的数据大小
+ ///
+ private int dataSize = -1;
+
+ ///
+ /// 根据指定的主键列的名称和主键列的值构造主键列。
+ /// 主键列的名称不能为null pointer及空字符串。
+ /// 主键列的值不能为null pointer。
+ ///
+ /// 列名
+ /// 列值
+ public PrimaryKeyColumn(string name, ColumnValue columnValue)
+ {
+ Contract.Requires(!string.IsNullOrEmpty(name));
+ Contract.Requires(columnValue != null);
+ this.Name = name;
+ this.Value = columnValue;
+ }
+
+ public PrimaryKeyColumn(KeyValuePair pair)
+ {
+ this.Name = pair.Key;
+ this.Value = pair.Value;
+ }
+
+ public byte[] GetNameRawData()
+ {
+ return OtsUtils.String2Bytes(Name);
+ }
+
+ public int HashCode()
+ {
+ return Name.GetHashCode() ^ Value.GetHashCode();
+ }
+
+ public override int GetHashCode()
+ {
+ return HashCode();
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj == null || !(obj is PrimaryKeyColumn))
+ {
+ return false;
+ }
+
+ PrimaryKeyColumn col = (PrimaryKeyColumn)obj;
+ return this.Name.Equals(col.Name) && this.Value.Equals(col.Value);
+ }
+
+ ///
+ /// 比较两个主键列的大小
+ /// 对比的两个主键列必须含有相同的名称和类型。
+ ///
+ /// 若相等返回0,若大于返回1,若小于返回-1
+ /// 比较对象
+ public int CompareTo(Object obj)
+ {
+ var target = obj as PrimaryKeyColumn;
+ if (!this.Name.Equals(target.Name))
+ {
+ throw new ArgumentException("The name of primary key to be compared must be the same.");
+ }
+
+ return this.Value.CompareTo(target.Value);
+ }
+
+ public int GetDataSize()
+ {
+ if (dataSize == -1)
+ {
+ dataSize = OtsUtils.CalcStringSizeInBytes(Name) + Value.GetDataSize();
+ }
+
+ return dataSize;
+ }
+
+ public override string ToString()
+ {
+ return "'" + Name + "':" + Value;
+ }
+
+ public Column ToColumn()
+ {
+ return new Column(this.Name, this.Value);
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyOption.cs b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyOption.cs
new file mode 100644
index 0000000..9b25ce1
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeyOption.cs
@@ -0,0 +1,8 @@
+namespace Aliyun.OTS.DataModel
+{
+ public enum PrimaryKeyOption
+ {
+ NONE = 0,
+ AUTO_INCREMENT = 1
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeySchema.cs b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeySchema.cs
new file mode 100644
index 0000000..8986608
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/PrimaryKeySchema.cs
@@ -0,0 +1,56 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示主键的设计,包括每个主键列的名称和列值类型。
+ ///
+ public class PrimaryKeySchema : List>
+ {
+ ///
+ /// 添加一个主键列的设计,PrimaryKey。
+ ///
+ /// 列名
+ /// 列值类型
+ public void Add(string primaryKeyColumnName, ColumnValueType columnValueType)
+ {
+ var tuple = new Tuple(primaryKeyColumnName, columnValueType, PrimaryKeyOption.NONE);
+ Add(tuple);
+ }
+
+ ///
+ /// 添加一个主键列的设计。
+ ///
+ /// 列名
+ /// 列值类型
+ public void Add(string primaryKeyColumnName, ColumnValueType columnValueType, PrimaryKeyOption primaryKeyOption)
+ {
+ var tuple = new Tuple(primaryKeyColumnName, columnValueType, primaryKeyOption);
+ Add(tuple);
+ }
+
+ public override String ToString()
+ {
+ String schema = "";
+ foreach (Tuple v in this)
+ {
+ var item2 = v.Item3 == PrimaryKeyOption.AUTO_INCREMENT ? PrimaryKeyOption.AUTO_INCREMENT.ToString(): v.Item2.ToString();
+ schema += v.Item1 + ":" + v.Item2 + ",";
+ }
+
+ return schema;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RangeRowQueryCriteria.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RangeRowQueryCriteria.cs
new file mode 100644
index 0000000..72a2495
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RangeRowQueryCriteria.cs
@@ -0,0 +1,59 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ */
+
+using Aliyun.OTS.Request;
+
+namespace Aliyun.OTS.DataModel
+{
+ public class RangeRowQueryCriteria : RowQueryCriteria
+ {
+ ///
+ /// 设置或获取范围查询的读取顺序(正序(FORWARD)或反序(BACKWARD))。
+ ///
+ public GetRangeDirection Direction { get; set; }
+
+ ///
+ /// 设置或获取查询返回的最大行数,若limit未设置,则返回查询范围下的所有行
+ ///
+ public int? Limit { get; set; }
+
+ ///
+ /// 设置或获取范围查询的左边界的主键值
+ ///
+ public PrimaryKey InclusiveStartPrimaryKey { get; set; }
+
+ ///
+ /// 设置或获取获取范围查询的右边界的主键值
+ ///
+ public PrimaryKey ExclusiveEndPrimaryKey { get; set; }
+
+ ///
+ /// 用于行内流式读, 标记位置和状态信息.
+ ///
+ public byte[] Token { get; set; }
+
+ ///
+ /// 构造一个在给定名称的表中查询的条件。
+ ///
+ /// 表名称
+ public RangeRowQueryCriteria(string tableName)
+ : base(tableName)
+ {
+ Direction = GetRangeDirection.Forward;
+ InclusiveStartPrimaryKey = new PrimaryKey();
+ ExclusiveEndPrimaryKey = new PrimaryKey();
+ }
+
+ public bool HasSetToken()
+ {
+ return Token != null;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ReservedThroughputDetails.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ReservedThroughputDetails.cs
new file mode 100644
index 0000000..2c3ff09
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ReservedThroughputDetails.cs
@@ -0,0 +1,61 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 和的返回中包含的
+ /// 预留读写吞吐量详细信息。
+ ///
+ public class ReservedThroughputDetails
+ {
+ ///
+ /// 读写能力单元
+ ///
+ public CapacityUnit CapacityUnit { get; private set; }
+
+ ///
+ /// 最后一次上调的时间
+ ///
+ public Int64 LastIncreaseTime { get; private set; }
+
+ ///
+ /// 最后一次下调的时间
+ ///
+ public Int64 LastDecreaseTime { get; private set; }
+
+ ///
+ /// 本日预留读写吞吐量下调的次数
+ ///
+ public int NumberOfDecreasesToday { get; private set; }
+
+ public ReservedThroughputDetails(CapacityUnit capacityUnit,
+ Int64 lastIncreaseTime,
+ Int64 lastDecreaseTime,
+ int numberOfDecreasesToday) :
+ this(capacityUnit,
+ lastIncreaseTime,
+ lastDecreaseTime)
+ {
+ NumberOfDecreasesToday = numberOfDecreasesToday;
+ }
+
+ public ReservedThroughputDetails(CapacityUnit capacityUnit,
+ Int64 lastIncreaseTime, Int64 lastDecreaseTime)
+ {
+ CapacityUnit = capacityUnit;
+ LastIncreaseTime = lastIncreaseTime;
+ LastDecreaseTime = lastDecreaseTime;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/ReturnType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/ReturnType.cs
new file mode 100644
index 0000000..d4924cf
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/ReturnType.cs
@@ -0,0 +1,24 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ /**
+ * 表示操作(PUT,UPDATE,DELETE)的返回结果中是否附带PK值,对于PK递增列,应该设置返回PK
+ */
+ public enum ReturnType
+ {
+ ///
+ /// 不返回任何行数据。
+ ///
+ RT_NONE,
+
+ ///
+ /// 返回PK列的数据。
+ ///
+ RT_PK,
+
+ ///
+ /// 返回修改列的数据(如原子加的结果返回)
+ ///
+ RT_AFTER_MODIFY,
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Row.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Row.cs
new file mode 100644
index 0000000..69dd7f4
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Row.cs
@@ -0,0 +1,221 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Aliyun.OTS.DataModel
+{
+ public class Row : IRow
+ {
+ public PrimaryKey PrimaryKey { get; set; }
+
+ public AttributeColumns AttributeColumns{
+ get{
+ if(columns == null)
+ {
+ return null;
+ }
+
+ var attributeColumns = new AttributeColumns();
+
+ foreach(var column in columns)
+ {
+ attributeColumns.Add(column);
+ }
+
+ return attributeColumns;
+ }
+ }
+
+ private readonly Column[] columns;
+
+ ///
+ /// 构造函数。
+ ///
+ /// 行的主键,不能为null或者为空
+ /// 该行的属性列,不能为null
+ public Row(PrimaryKey primaryKey, List columns) : this(primaryKey, columns.ToArray())
+ {
+
+ }
+
+ ///
+ /// 构造函数。
+ ///
+ /// 行的主键,不能为null或者为空
+ /// 该行的属性列,不能为null
+ public Row(PrimaryKey primaryKey, Column[] columns)
+ {
+ PrimaryKey = primaryKey;
+ this.columns = columns;
+ SortColumns(); // it may not been sorted, so we should sort it first
+ }
+
+ public PrimaryKey GetPrimaryKey()
+ {
+ return PrimaryKey;
+ }
+
+ ///
+ /// 获取所有的属性列。数组中的所有属性列按名称升序排列,相同名称的属性列按timestamp降序排列。
+ ///
+ /// 所有属性列
+ public Column[] GetColumns()
+ {
+ return columns;
+ }
+
+ ///
+ /// 获取某个特定名称的属性列的所有版本的值。返回结果中这些属性列按timestamp降序排列.
+ ///
+ /// 若该属性列存在,则返回所有版本的值,按timestamp降序排列,否则返回空列表
+ /// 属性列的名称
+ public List GetColumn(String columnName)
+ {
+ List result = new List();
+
+ if (columns == null || columns.Length == 0)
+ {
+ return result;
+ }
+
+ int pos = BinarySearch(columnName);
+ if (pos == -1)
+ {
+ return result;
+ }
+
+ for (int i = pos; i < columns.Length; i++)
+ {
+ Column col = columns[i];
+ if (col.Name.Equals(columnName))
+ {
+ result.Add(col);
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ ///
+ /// 获取该属性列中最新版本的值。
+ ///
+ /// 若该属性列存在,则返回最新版本的值,否则返回null
+ /// 属性列的名称
+ public Column GetLatestColumn(String name)
+ {
+ if (columns == null || columns.Length == 0)
+ {
+ return null;
+ }
+
+ int pos = BinarySearch(name);
+ if (pos == -1)
+ {
+ return null;
+ }
+
+ Column col = columns[pos];
+
+ if (col.Name.Equals(name))
+ {
+ return col;
+ }
+
+ return null;
+ }
+
+ ///
+ /// 检查该行中是否有该名称的属性列。
+ ///
+ /// 若存在,则返回true,否则返回false
+ /// Name.
+ public bool Contains(String name)
+ {
+ return GetLatestColumn(name) != null;
+ }
+
+ ///
+ /// 检查该行是否包含属性列。
+ ///
+ /// 若该行不包含任何属性列,则返回true,否则返回false
+ public bool IsEmpty()
+ {
+ return columns == null || columns.Length == 0;
+ }
+
+ public int CompareTo(IRow o)
+ {
+
+ return this.PrimaryKey.CompareTo(o.GetPrimaryKey());
+ }
+
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("[PrimaryKey]:");
+ sb.Append(this.PrimaryKey);
+ sb.Append("\n[Columns]:");
+ foreach (Column column in this.GetColumns())
+ {
+ sb.Append("(");
+ sb.Append(column);
+ sb.Append(")");
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// 将数组中的所有属性列按名称升序、timestamp降序的顺序重新排列。
+ ///
+ private void SortColumns()
+ {
+ // check if it is already sorted, optimized as in most time it is sorted.
+ bool sorted = true;
+ for (int i = 0; i < columns.Length - 1; i++)
+ {
+ int ret = Column.NAME_TIMESTAMP_COMPARATOR.Compare(columns[i], columns[i + 1]);
+ if (ret > 0)
+ {
+ sorted = false;
+ break;
+ }
+ }
+
+ if (!sorted)
+ {
+ Array.Sort(this.columns, Column.NAME_TIMESTAMP_COMPARATOR);
+ }
+ }
+
+ ///
+ /// 二分查找指定的列.
+ ///
+ /// T如果包含查找的列, 返回对应的index; 如果不包含该列, 返回可以插入该列的位置; 如果所有元素都小于该列, 返回-1.
+ /// 要查找的列名
+ private int BinarySearch(String name)
+ {
+ Column searchTerm = new Column(name, null, long.MaxValue);
+
+ // 若数组中有多列与searchTerm相同,那不保证一定返回第一列,Row中的数据是TableStore返回的,不会出现这种情况。
+ // pos === ( -(insertion point) - 1)
+ int pos = Array.BinarySearch(columns, searchTerm, Column.NAME_TIMESTAMP_COMPARATOR);
+
+ if (pos < 0)
+ {
+ pos = (pos + 1) * -1;
+ }
+
+ if (pos == columns.Length)
+ {
+ return -1;
+ }
+
+ return pos;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowChange.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowChange.cs
new file mode 100644
index 0000000..2257bfe
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowChange.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics.Contracts;
+namespace Aliyun.OTS.DataModel
+{
+ /**
+ * 单行的数据变更操作的基础结构。
+ * 若是PutRow操作,请参考{@link RowPutChange}。
+ * 若是UpdateRow操作,请参考{@link RowUpdateChange}。
+ * 若是DeleteRow操作,请参考{@link RowDeleteChange}。
+ */
+ public abstract class RowChange : IRow, IMeasurable
+ {
+ ///
+ /// 表的名称。
+ ///
+ /// The name of the table.
+ public String TableName { get; set; }
+
+ ///
+ /// 表的主键。
+ ///
+ /// The primary key.
+ public PrimaryKey PrimaryKey { get; set; }
+
+ ///
+ /// 判断条件。
+ ///
+ /// The condition.
+ public Condition Condition { get; set; }
+
+ ///
+ /// 返回的数据类型,默认是不返回。
+ ///
+ /// The type of the return.
+ public ReturnType ReturnType { get; set; }
+
+ ///
+ /// 指定本次需要返回的列名
+ ///
+ public List ReturnColumnNames { get; set; }
+
+ ///
+ /// Initializes a new instance of the class.
+ /// 表的名称不能为null或者为空。
+ /// 行的主键不能为null或者为空。
+ ///
+ /// 表的名称
+ /// 表的主键
+ protected RowChange(string tableName, PrimaryKey primaryKey)
+ {
+ Contract.Requires(!string.IsNullOrEmpty(tableName), "表的名称不能为null或者为空。");
+ this.TableName = tableName;
+ this.PrimaryKey = primaryKey;
+ this.Condition = new Condition();
+ this.ReturnType = ReturnType.RT_NONE;
+ }
+
+ ///
+ /// 构造函数。internal use
+ /// 表的名称不能为null或者为空。
+ ///
+ /// 表的名称
+ protected RowChange(String tableName) : this(tableName, null)
+ {
+ }
+
+ public int CompareTo(IRow row)
+ {
+ return this.PrimaryKey.CompareTo(row.GetPrimaryKey());
+ }
+
+ public PrimaryKey GetPrimaryKey()
+ {
+ return this.PrimaryKey;
+ }
+
+ public int GetDataSize()
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowChangeType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowChangeType.cs
new file mode 100644
index 0000000..a13aaa1
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowChangeType.cs
@@ -0,0 +1,25 @@
+namespace Aliyun.OTS.DataModel
+{
+ public enum RowChangeType
+ {
+ ///
+ /// 代表写入该Column的某个特定版本的值。
+ ///
+ PUT,
+
+ ///
+ /// 代表删除该Column的某个特定版本,版本号的时间戳等于{@link Column#timestamp}。
+ ///
+ DELETE,
+
+ ///
+ /// 代表删除该Column的所有版本的值。
+ ///
+ DELETE_ALL,
+
+ ///
+ /// 代表对该column的最新版本执行原子加。
+ ///
+ INCREMENT
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowChanges.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowChanges.cs
new file mode 100644
index 0000000..a366e05
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowChanges.cs
@@ -0,0 +1,125 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 用来表示中同一个表的多行操作,包括Put, Update和Delete。
+ ///
+ public class RowChanges
+ {
+ ///
+ /// 表示多个Put操作。
+ ///
+ public List> PutOperations { get; set; }
+
+ ///
+ /// 表示多个Update操作。
+ ///
+ public List> UpdateOperations { get; set; }
+
+ ///
+ /// 表示多个Delete操作。
+ ///
+ public List> DeleteOperations { get; set;}
+
+
+ ///
+ /// 表示多个Put操作。
+ ///
+ public List RowPutChanges;
+
+ ///
+ /// 表示多个Update操作。
+ ///
+ public List RowUpdateChanges;
+
+ ///
+ /// 表示多个Delete操作。
+ ///
+ public List RowDeleteChanges;
+
+ public string TableName { get; set;}
+
+ public RowChanges(string tableName)
+ {
+ RowPutChanges = new List();
+ RowUpdateChanges = new List();
+ RowDeleteChanges = new List();
+ TableName = tableName;
+ }
+
+ ///
+ /// 添加一个Put操作
+ ///
+ /// 检查条件
+ /// 主键
+ /// 属性
+ public void AddPut(Condition condition, PrimaryKey primaryKey, AttributeColumns attributeColumns)
+ {
+ var item = new RowPutChange(TableName, primaryKey)
+ {
+ Condition = condition
+ };
+
+ if (attributeColumns != null)
+ {
+ foreach (var column in attributeColumns)
+ {
+ item.AddColumn(column.Key, column.Value);
+ }
+ }
+
+ RowPutChanges.Add(item);
+ }
+
+ ///
+ /// 添加一个Delete操作
+ ///
+ ///
+ ///
+ public void AddDelete(Condition condition, PrimaryKey primaryKey)
+ {
+ var item = new RowDeleteChange(TableName, primaryKey)
+ {
+ Condition = condition
+ };
+
+ RowDeleteChanges.Add(item);
+ }
+
+ ///
+ /// 添加一个Update操作
+ ///
+ ///
+ ///
+ ///
+ public void AddUpdate(Condition condition, PrimaryKey primaryKey, UpdateOfAttribute updateAttributes)
+ {
+ var item = new RowUpdateChange(TableName, primaryKey)
+ {
+ Condition = condition
+ };
+
+ item.FromUpdateOfAtrribute(updateAttributes);
+
+ RowUpdateChanges.Add(item);
+ }
+
+ public bool IsEmpty()
+ {
+ return RowPutChanges.Count + RowUpdateChanges.Count + RowDeleteChanges.Count == 0;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowDeleteChange.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowDeleteChange.cs
new file mode 100644
index 0000000..82a178e
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowDeleteChange.cs
@@ -0,0 +1,28 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ public class RowDeleteChange : RowChange
+ {
+ ///
+ /// 构造函数。
+ ///
+ /// 表的名称
+ /// 要删除的行的主键
+ public RowDeleteChange(String tableName, PrimaryKey primaryKey) : base(tableName, primaryKey)
+ {
+ }
+
+ ///
+ /// 构造函数。
+ ///
+ /// 表的名称
+ public RowDeleteChange(String tableName) : base(tableName)
+ {
+ }
+
+ public new int GetDataSize()
+ {
+ return GetPrimaryKey().GetDataSize();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowExistenceExpectation.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowExistenceExpectation.cs
new file mode 100644
index 0000000..7dfbd0a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowExistenceExpectation.cs
@@ -0,0 +1,23 @@
+namespace Aliyun.OTS.DataModel
+{
+ public enum RowExistenceExpectation
+ {
+ ///
+ /// 表示写操作(包括PutRow, DeleteRow, UpdateRow, BatchWriteRow)中的IGNORE条件。
+ /// 即不论该行是否存在均执行操作。
+ ///
+ IGNORE,
+
+ ///
+ /// 表示写操作(包括PutRow, DeleteRow, UpdateRow, BatchWriteRow)EXPECT_EXIST条件。
+ /// 即仅在该行存在的情况下执行操作;否则操作出错。
+ ///
+ EXPECT_EXIST,
+
+ ///
+ /// 表示写操作PutRow和BatchWriteRow中的put操作的EXPECT_NOT_EXIST条件。
+ /// 即仅在该行不存在的情况下执行操作;否则操作出错。
+ ///
+ EXPECT_NOT_EXIST
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowPutChange.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowPutChange.cs
new file mode 100644
index 0000000..4ce5538
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowPutChange.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ public class RowPutChange : RowChange
+ {
+ ///
+ /// 行的属性列集合。
+ ///
+ private readonly List columnsToPut = new List();
+
+ private long? timestamp;
+
+ ///
+ /// 构造函数。
+ ///
+ /// 表的名称
+ public RowPutChange(String tableName) : base(tableName)
+ {
+ }
+
+ ///
+ /// 构造函数。
+ ///
+ /// 表的名称
+ /// 行的主键
+ public RowPutChange(String tableName, PrimaryKey primaryKey) : base(tableName, primaryKey)
+ {
+ }
+
+ ///
+ /// 构造函数。
+ /// 允许用户设置一个默认的时间戳,若写入的列没有带时间戳,则会使用该默认时间戳。
+ ///
+ /// 表的名称.
+ /// 行的主键
+ /// 默认时间戳
+ public RowPutChange(String tableName, PrimaryKey primaryKey, long timestamp) : base(tableName, primaryKey)
+ {
+ this.timestamp = timestamp;
+ }
+
+ ///
+ /// 拷贝构造函数
+ ///
+ /// To copy.
+ public RowPutChange(RowPutChange toCopy) : base(toCopy.TableName, toCopy.GetPrimaryKey())
+ {
+ if (toCopy.timestamp.HasValue)
+ {
+ timestamp = toCopy.timestamp;
+ }
+
+ columnsToPut.AddRange(toCopy.columnsToPut);
+ }
+
+ ///
+ /// 新写入一个属性列。
+ ///
+ /// The column.
+ /// Column(for invocation chain).
+ public RowPutChange AddColumn(Column column)
+ {
+ this.columnsToPut.Add(column);
+ return this;
+ }
+
+ ///
+ /// 新写入一个属性列。
+ /// 若设置过{@link #timestamp},则使用该默认的时间戳。
+ ///
+ /// The column(for invocation chain).
+ /// 属性列的名称
+ /// 属性列的值
+ public RowPutChange AddColumn(String name, ColumnValue value)
+ {
+ Column column = null;
+ if (this.timestamp.HasValue)
+ {
+ column = new Column(name, value, this.timestamp.Value);
+ }
+ else
+ {
+ column = new Column(name, value);
+ }
+
+ this.columnsToPut.Add(column);
+ return this;
+ }
+
+ ///
+ /// 新写入一个属性列。
+ ///
+ /// The column.
+ /// 属性列的名称
+ /// 属性列的值
+ /// T属性列的时间戳
+ public RowPutChange AddColumn(String name, ColumnValue value, long timestamp)
+ {
+ this.columnsToPut.Add(new Column(name, value, timestamp));
+ return this;
+ }
+
+ ///
+ /// 新写入一批属性列。
+ /// 属性列的写入顺序与列表中的顺序一致。
+ ///
+ /// The columns(for invocation chain).
+ /// 属性列列表
+ public RowPutChange AddColumns(IEnumerable columns)
+ {
+ this.columnsToPut.AddRange(columns);
+ return this;
+ }
+
+ ///
+ /// 新写入一批属性列。
+ /// 属性列的写入顺序与列表中的顺序一致。
+ ///
+ /// The columns(for invocation chain).
+ /// 属性列列表
+ public RowPutChange AddColumns(AttributeColumns columns)
+ {
+ foreach (var key in columns.Keys)
+ {
+ this.columnsToPut.Add(new Column(key, columns[key]));
+ }
+
+ return this;
+ }
+
+ ///
+ /// 获取所有要写入的属性列列表。
+ ///
+ /// 属性列列表
+ public List GetColumnsToPut()
+ {
+ return this.columnsToPut;
+ }
+
+ ///
+ /// 获取名称与指定名称相同的所有属性列的列表
+ ///
+ /// 属性列名称
+ /// 若找到对应的属性列,则返回包含这些元素的列表,否则返回一个空列表。
+ public List GetColumnsToPut(string name)
+ {
+ List result = new List();
+
+ foreach (Column col in columnsToPut)
+ {
+ if (col.Name.Equals(name))
+ {
+ result.Add(col);
+ }
+ }
+
+ return result;
+ }
+
+ public new int GetDataSize()
+ {
+ int valueTotalSize = 0;
+ foreach (Column col in columnsToPut)
+ {
+ valueTotalSize += col.GetDataSize();
+ }
+ return GetPrimaryKey().GetDataSize() + valueTotalSize;
+ }
+
+ ///
+ /// 检查是否已经有相同名称的属性列写入,忽略时间戳和值是否相等。
+ ///
+ /// 若有返回true,否则返回false
+ /// 属性列名称
+ public bool Has(String name)
+ {
+ foreach (Column col in columnsToPut)
+ {
+ if (col.Name.Equals(name))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// 检查是否有相同名称和相同时间戳的属性列写入,忽略值是否相等。
+ ///
+ /// 若有返回true,否则返回false
+ /// 属性列名称
+ /// 属性列时间戳
+ public bool Has(String name, long ts)
+ {
+ foreach (Column col in columnsToPut)
+ {
+ if (col.Name.Equals(name) && (col.Timestamp.HasValue && col.Timestamp == ts))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// 检查是否有相同名称和相同值的属性列写入,忽略时间戳是否相等。
+ ///
+ /// 若有返回true,否则返回false
+ /// 属性列名称
+ /// 属性列值
+ public bool Has(String name, ColumnValue value)
+ {
+ foreach (Column col in columnsToPut)
+ {
+ if (col.Name.Equals(name) && col.Value.Equals(value))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ ///
+ /// 检查是否有相同名称、相同时间戳并且相同值的属性列写入。
+ ///
+ /// 若有返回true,否则返回false
+ /// 属性列名称
+ /// 属性列时间戳
+ /// 属性列值
+ public bool Has(String name, long ts, ColumnValue value)
+ {
+ foreach (Column col in columnsToPut)
+ {
+ if (col.Name.Equals(name) && (col.Timestamp.HasValue && col.Timestamp == ts) &&
+ value.Equals(col.Value))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowQueryCriteria.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowQueryCriteria.cs
new file mode 100644
index 0000000..41ca82a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowQueryCriteria.cs
@@ -0,0 +1,122 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ */
+
+using System.Collections.Generic;
+using Aliyun.OTS.DataModel.Filter;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示返回行的查询条件
+ ///
+ public class RowQueryCriteria
+ {
+ ///
+ /// 查询的表的名称。
+ ///
+ public string TableName { get; set; }
+
+ ///
+ /// 要查询的列的名称,若未指定查询的列,则查询整行
+ ///
+ private HashSet columnsToGet = new HashSet();
+
+ ///
+ /// 要读取的时间戳的范围,若未设置,则代表读取所有的版本。
+ ///
+ public TimeRange TimeRange { get; set; }
+
+ ///
+ /// 要返回的列的版本的个数,若未设置,则返回OTS当前保留的所有版本。
+ ///
+ public int? MaxVersions { get; set; }
+
+ ///
+ /// 本次查询使用的Filter
+ ///
+ public IFilter Filter { get; set; }
+
+ ///
+ /// 查询的列范围的起始位置.
+ ///
+ public string StartColumn { get; set; }
+
+ ///
+ /// 查询的列范围的终止位置.
+ ///
+ public string EndColumn { get; set; }
+
+ ///
+ /// 内部参数。
+ ///
+ public bool? CacheBlocks { get; set; }
+
+
+ ///
+ /// 构造一个在给定名称的表中查询的条件
+ ///
+ /// 要查询的表名称
+ public RowQueryCriteria(string tableName)
+ {
+ TableName = tableName;
+ }
+
+ ///
+ /// 获取返回列的名称的列表
+ ///
+ /// 返回列的名称列表
+ public HashSet GetColumnsToGet()
+ {
+ return columnsToGet;
+ }
+
+ ///
+ /// 添加要返回的列
+ ///
+ /// 返回的列的名称
+ public void AddColumnsToGet(string columnName)
+ {
+ columnsToGet.Add(columnName);
+ }
+
+ ///
+ /// 添加要返回的列。
+ ///
+ /// 要返回列的名称
+ public void AddColumnsToGet(HashSet columnNames)
+ {
+ foreach (string column in columnNames)
+ {
+ columnsToGet.Add(column);
+ }
+ }
+
+ ///
+ /// 设置需要读取的列的列表。若List为空,则读取所有列
+ ///
+ /// 需要读取的列的列表
+ public void SetColumnsToGet(HashSet columnNames)
+ {
+ this.columnsToGet = columnNames;
+ }
+
+ public void CopyTo(RowQueryCriteria target)
+ {
+ target.TableName = TableName;
+ target.columnsToGet.UnionWith(this.columnsToGet);
+ target.TimeRange = TimeRange;
+ target.MaxVersions = MaxVersions;
+ target.CacheBlocks = CacheBlocks;
+ target.Filter = Filter;
+ target.StartColumn = StartColumn;
+ target.EndColumn = EndColumn;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/RowUpdateChange.cs b/netstandard-sdk/Aliyun/OTS/DataModel/RowUpdateChange.cs
new file mode 100644
index 0000000..d6f17ea
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/RowUpdateChange.cs
@@ -0,0 +1,191 @@
+using System;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ public class RowUpdateChange : RowChange
+ {
+
+ ///
+ ///
+ ///所有要更新的属性列。
+ ///若类型为{@link Type#PUT},则代表写入一个属性列。
+ ///若类型为{@link Type#DELETE},则代表删除一个属性列的某个特定版本,对应的Column中的value无效。
+ ///若类型为{@link Type#DELETE_ALL},则代表删除一个属性列的所有版本,对应的Column中的value和timestamp均无效。
+ ///
+ ///
+ private readonly List> columnsToUpdate = new List>();
+
+ private long? timestamp;
+
+ public RowUpdateChange(String tableName) : base(tableName)
+ {
+
+ }
+
+ public RowUpdateChange(String tableName, PrimaryKey primaryKey) : base(tableName, primaryKey)
+ {
+
+ }
+
+ public RowUpdateChange(String tableName, PrimaryKey primaryKey, long ts) : base(tableName, primaryKey)
+ {
+ this.timestamp = ts;
+ }
+
+ public RowUpdateChange(RowUpdateChange toCopy) : base(toCopy.TableName, toCopy.PrimaryKey)
+ {
+ if (toCopy.timestamp.HasValue)
+ {
+ timestamp = toCopy.timestamp;
+ }
+
+ columnsToUpdate.AddRange(toCopy.columnsToUpdate);
+ }
+
+ ///
+ /// 新写入一个属性列。
+ ///
+ /// The put.
+ /// Column.
+ public RowUpdateChange Put(Column column)
+ {
+ this.columnsToUpdate.Add(new Tuple(column, RowChangeType.PUT));
+ return this;
+ }
+
+ ///
+ /// 新写入一个属性列。
+ /// 若设置过{@link #timestamp},则使用该默认的时间戳。
+ ///
+ /// The put.
+ /// 属性列的名称
+ /// 属性列的值
+ public RowUpdateChange Put(String name, ColumnValue value)
+ {
+ Column column = null;
+ if (this.timestamp.HasValue)
+ {
+ column = new Column(name, value, this.timestamp.Value);
+ }
+ else
+ {
+ column = new Column(name, value);
+ }
+
+ this.columnsToUpdate.Add(new Tuple(column, RowChangeType.PUT));
+ return this;
+ }
+
+ ///
+ /// 新写入一个属性列。
+ ///
+ /// The put.
+ /// 属性列的名称
+ /// 属性列的值
+ /// 属性列的时间戳
+ public RowUpdateChange Put(String name, ColumnValue value, long ts)
+ {
+ this.columnsToUpdate.Add(new Tuple(new Column(name, value, ts), RowChangeType.PUT));
+ return this;
+ }
+
+ ///
+ /// 新写入一批属性列。
+ /// 属性列的写入顺序与列表中的顺序一致。
+ ///
+ /// The put.
+ /// 属性列列表
+ public RowUpdateChange Put(List columns)
+ {
+ foreach (Column col in columns)
+ {
+ Put(col);
+ }
+
+ return this;
+ }
+
+ ///
+ /// 删除某一属性列的特定版本。
+ ///
+ /// The column.
+ /// 属性列的名称
+ /// 属性列的时间戳
+ public RowUpdateChange DeleteColumn(String name, long ts)
+ {
+ this.columnsToUpdate.Add(new Tuple(new Column(name, null, ts), RowChangeType.DELETE));
+ return this;
+ }
+
+ ///
+ /// 删除某一属性列的所有版本。
+ ///
+ /// The column.
+ /// 属性列的名称
+ public RowUpdateChange DeleteColumn(String name)
+ {
+ this.columnsToUpdate.Add(new Tuple(new Column(name, null), RowChangeType.DELETE_ALL));
+ return this;
+ }
+
+ ///
+ /// 添加一列原子自增
+ ///
+ ///
+ ///
+ public RowUpdateChange Increment(Column column)
+ {
+ this.columnsToUpdate.Add(new Tuple(column, RowChangeType.INCREMENT));
+ return this;
+ }
+
+ ///
+ ///
+ ///所有要更新的属性列。
+ ///若类型为{@link Type#PUT},则代表写入一个属性列。
+ ///若类型为{@link Type#DELETE},则代表删除一个属性列的某个特定版本,对应的Column中的value无效。
+ ///若类型为{@link Type#DELETE_ALL},则代表删除一个属性列的所有版本,对应的Column中的value和timestamp均无效。
+ ///
+ ///
+ /// 所有要更新的列
+ public List> GetColumnsToUpdate()
+ {
+ return this.columnsToUpdate;
+ }
+
+
+ public new int GetDataSize()
+ {
+ int valueTotalSize = 0;
+ foreach (Tuple col in columnsToUpdate)
+ {
+ valueTotalSize += col.Item1.GetDataSize();
+ }
+
+ return GetPrimaryKey().GetDataSize() + valueTotalSize;
+ }
+
+
+ public RowUpdateChange FromUpdateOfAtrribute(UpdateOfAttribute updateOfAttribute)
+ {
+ if (updateOfAttribute.AttributeColumnsToDelete != null)
+ {
+ foreach (var attributeColumnToDelete in updateOfAttribute.AttributeColumnsToDelete)
+ {
+ this.DeleteColumn(attributeColumnToDelete);
+ }
+ }
+
+ if (updateOfAttribute.AttributeColumnsToPut != null)
+ {
+ foreach (var attributeColumnToPut in updateOfAttribute.AttributeColumnsToPut)
+ {
+ this.Put(attributeColumnToPut.Key, attributeColumnToPut.Value);
+ }
+ }
+
+ return this;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Collapse.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Collapse.cs
new file mode 100644
index 0000000..7b2a64e
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Collapse.cs
@@ -0,0 +1,13 @@
+/**
+ * 字段折叠,能够实现某个字段的结果去重
+ * 场景举例:
+ * app点餐场景下,我想吃八大菜系最火的菜。如果用传统的方法,我们可能需要对8个菜的type进行分别查询最火的菜。
+ * 但是我们通过设置{@link Collapse}为菜系type,就可以返回8个最火的菜(每个菜系只返回一个,因为{@link Collapse}帮我们进行了去重)。一次查询搞定用户的需求。
+ */
+namespace Aliyun.OTS.DataModel.Search
+{
+ public class Collapse
+ {
+ public string FieldName { get; set; }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/ColumnsToGet.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/ColumnsToGet.cs
new file mode 100644
index 0000000..92ba9ee
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/ColumnsToGet.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel.Search
+{
+ public class ColumnsToGet
+ {
+ public List Columns { get; set; }
+ public bool ReturnAll { get; set; }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldSchema.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldSchema.cs
new file mode 100644
index 0000000..4cf4e6e
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldSchema.cs
@@ -0,0 +1,64 @@
+using System;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel.Search
+{
+ public enum Analyzer
+ {
+ NotAnalyzed,
+ SingleWord,
+ MaxWord
+
+ }
+
+ public class FieldSchema
+ {
+ ///
+ /// 字段名
+ ///
+ public string FieldName { get; set; }
+ ///
+ /// 字段类型,详见{@link FieldType}
+ ///
+ public FieldType FieldType { get; set; }
+
+ ///
+ /// 是否开启索引,默认开启
+ ///
+ public Boolean index = true;
+ ///
+ /// 倒排索引的配置选项
+ ///
+ public IndexOptions IndexOptions { get; set; }
+ ///
+ /// 分词器设置
+ ///
+ public Analyzer Analyzer { get; set; }
+ ///
+ /// 是否开启排序和聚合功能
+ ///
+ public bool EnableSortAndAgg { get; set; }
+
+ ///
+ /// 附加存储,是否在SearchIndex中附加存储该字段的值。
+ ///开启后,可以直接从SearchIndex中读取该字段的值,而不必反查主表,可用于查询性能优化。
+ ///
+ public bool Store { get; set; }
+
+ ///
+ /// 存的值是否是一个数组
+ ///
+ public bool IsArray { get; set; }
+
+ ///
+ /// 如果 FiledType 是 NESTED ,则可使用该字段,声明一个嵌套的FieldSchema
+ ///
+ public List SubFieldSchemas { get; set; }
+
+ public FieldSchema(string fieldName, FieldType fieldType)
+ {
+ this.FieldName = fieldName;
+ this.FieldType = fieldType;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldType.cs
new file mode 100644
index 0000000..8533e53
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/FieldType.cs
@@ -0,0 +1,19 @@
+namespace Aliyun.OTS.DataModel.Search
+{
+ public enum FieldType
+ {
+ LONG,
+ DOUBLE,
+ BOOLEAN,
+ ///
+ /// 字符串类型,同Text的区别是keyword不分词,一般作为一个整体,如果想进行聚合统计分析,请使用该类型。
+ ///
+ KEYWORD,
+ ///
+ /// 字符串类型,同keyword的区别是text会进行分词,一般在模糊查询的场景使用。
+ ///
+ TEXT,
+ NESTED,
+ GEO_POINT
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/GeoPoint.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/GeoPoint.cs
new file mode 100644
index 0000000..3c16307
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/GeoPoint.cs
@@ -0,0 +1,17 @@
+namespace Aliyun.OTS.DataModel.Search
+{
+ ///
+ /// 经纬度
+ ///
+ public class GeoPoint
+ {
+ public double Lat { get; set; }
+ public double Lon { get; set; }
+
+ public GeoPoint(double lat, double lon)
+ {
+ this.Lat = lat;
+ this.Lon = lon;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexOptions.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexOptions.cs
new file mode 100644
index 0000000..5c5f130
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexOptions.cs
@@ -0,0 +1,16 @@
+namespace Aliyun.OTS.DataModel.Search
+{
+
+ ///
+ /// 支持的索引选项控制
+ ///
+ public enum IndexOptions
+ {
+ NULL,
+ DOCS,
+ FREQS,
+ POSITIONS,
+ OFFSETS
+ }
+
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSchema.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSchema.cs
new file mode 100644
index 0000000..2cda0be
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSchema.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using Aliyun.OTS.DataModel.Search.Sort;
+
+namespace Aliyun.OTS.DataModel.Search
+{
+ public class IndexSchema
+ {
+ public IndexSchema() { }
+
+ public IndexSetting IndexSetting { get; set; }
+
+ public List FieldSchemas { get; set; }
+
+ ///
+ /// 自定义索引的预排序方式
+ ///
+ public Sort.Sort IndexSort { get; set; }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSetting.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSetting.cs
new file mode 100644
index 0000000..3a19158
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/IndexSetting.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel.Search
+{
+ public class IndexSetting
+ {
+ public IndexSetting() { }
+ public List RoutingFields { get; set; }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/BoolQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/BoolQuery.cs
new file mode 100644
index 0000000..580fbc0
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/BoolQuery.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using Google.ProtocolBuffers;
+using com.alicloud.openservices.tablestore.core.protocol;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ ///联合查询(复杂查询条件下用的最多的一个查询)。Bool查询对应Lucene中的BooleanQuery,它由一个或者多个子句组成,每个子句都有特定的类型。
+ ///must: 文档必须完全匹配条件
+ ///should: should下面会带一个以上的条件,至少满足一个条件,这个文档就符合should
+ ///must_not: 文档必须不匹配条件
+ ///
+ public class BoolQuery : IQuery
+ {
+ ///
+ /// 文档必须完全匹配所有的子query
+ ///
+ public List MustQueries { get; set; }
+ ///
+ /// 文档必须不能匹配任何子query
+ ///
+ public List MustNotQueries { get; set; }
+ ///
+ /// 文档必须完全匹配所有的子filter,filter类似于query,区别是不会进行算分
+ ///
+ public List FilterQueries { get; set; }
+ ///
+ /// 文档应该至少匹配一个should,匹配多的得分会高
+ ///
+ public List ShouldQueries { get; set; }
+ ///
+ /// 定义了至少满足几个should子句,默认是1。
+ ///
+ public int? MinimumShouldMatch { get; set; }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_BoolQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildBoolQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ConstScoreQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ConstScoreQuery.cs
new file mode 100644
index 0000000..8a56d6d
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ConstScoreQuery.cs
@@ -0,0 +1,24 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 当我们不关心检索词频率TF(Term Frequency)对搜索结果排序的影响时,可以使用constant_score将查询语句query或者过滤语句filter包装起来,达到提高搜索速度。
+ ///举例:我们班有100个人,有一个字段叫“name”,我们想要获得名字中包含“王”的人,我们并不关心排序结果,使用ConstScoreQuery(将原来的Query放在" private Query filter;"中)将会大大提高搜索速度。
+ ///
+ public class ConstScoreQuery:IQuery
+ {
+ public IQuery Filter { get; set; }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_ConstScoreQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildConstScoreQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FieldValueFactor.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FieldValueFactor.cs
new file mode 100644
index 0000000..75915d4
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FieldValueFactor.cs
@@ -0,0 +1,16 @@
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// field_value_factor的目的是通过文档中某个字段的值计算出一个分数,以此分数来影响文档的排序。请结合{@link FunctionScoreQuery} 使用。
+ ///举例:HR管理系统的场景,我们想查名字中包含“王”、出生地包含“京”的人,但是想让结果根据根据身高排序。就可以把身高设置在FieldValueFactor中
+ ///
+ public class FieldValueFactor
+ {
+ public string FieldName { get; set; }
+
+ public FieldValueFactor(string fieldName)
+ {
+ this.FieldName = fieldName;
+ }
+ }
+}
\ No newline at end of file
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FunctionScoreQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FunctionScoreQuery.cs
new file mode 100644
index 0000000..02ca64a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/FunctionScoreQuery.cs
@@ -0,0 +1,31 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 用于处理文档分值的Query,它会在查询结束后对每一个匹配的文档进行一系列的重打分操作,最后以生成的最终分数进行排序。
+ ///举例见{@link FieldValueFactor}
+ ///
+ public class FunctionScoreQuery : IQuery
+ {
+ public IQuery Query { get; set; }
+ public FieldValueFactor FieldValueFactor { get; set; }
+
+ public FunctionScoreQuery(IQuery query, FieldValueFactor fieldValueFactor)
+ {
+ this.Query = query;
+ this.FieldValueFactor = fieldValueFactor;
+ }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_FunctionScoreQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildFunctionScoreQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoBoundingBoxQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoBoundingBoxQuery.cs
new file mode 100644
index 0000000..469b725
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoBoundingBoxQuery.cs
@@ -0,0 +1,35 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 找出经纬度落在指定矩形内的数据。
+ ///场景举例:订单区域画像分析的场景,想分析A小区购买力,而恰好这A小区是矩形的。我们通过统计A小区订单数量(或总价)即可。
+ ///方法:在SearchQuery的中构造一个{@link BoolQuery},其 mustQueries 中放入一个{@link GeoBoundingBoxQuery}的矩形地理位置,然后mustQueries再放入查询订单数量的query,就可以获得想要的结果。
+ ///
+ public class GeoBoundingBoxQuery : IQuery
+ {
+ public string FieldName { get; set; }
+ /**
+ * 矩形的左上角的经纬度
+ * 示例:"46.24123424, 23.2342424"
+ */
+ public string TopLeft { get; set; }
+ /**
+ * 矩形的右下角经纬度
+ * 示例:"46.24123424, 23.2342424"
+ */
+ public string BottomRight { get; set; }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_GeoBoundingBoxQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildGeoBoundingBoxQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoDistanceQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoDistanceQuery.cs
new file mode 100644
index 0000000..f2a642a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoDistanceQuery.cs
@@ -0,0 +1,36 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 找出与某个位置某个距离内的数据。
+ ///常用场景:搜索我附近1千米内的人。
+ ///通过设置我的centerPoint(一个经纬度信息),然后设置举例信息distanceInMeter=1000,进行查询即可
+ ///
+ public class GeoDistanceQuery : IQuery
+ {
+ ///
+ /// 字段名
+ ///
+ public string FieldName { get; set; }
+ ///
+ /// 中心点
+ ///
+ public string CenterPoint { get; set; }
+ ///
+ /// 与中心点的距离(单位:米)
+ ///
+ public double DistanceInMeter { get; set; }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_GeoDistanceQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildGeoDistanceQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoPolygonQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoPolygonQuery.cs
new file mode 100644
index 0000000..1f31990
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/GeoPolygonQuery.cs
@@ -0,0 +1,33 @@
+using System.Collections.Generic;
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 找出落在指定多边形包围起来的图形内的数据
+ ///注意:这个查询器使用代价很大,请避免使用
+ ///场景举例:小黄车只能在繁华的地方服务,出了市区要收额外的服务费,而繁华的城市的边界是多边形的。我们想查询该车辆是否需要付额外的服务费,就需要通过搜索用户的经纬度是否在多边形内。
+ ///
+ public class GeoPolygonQuery : IQuery
+ {
+ ///
+ /// 字段名
+ ///
+ public string FieldName { get; set; }
+ ///
+ /// 经纬度字符串的List
+ ///
+ public List Points { get; set; }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_GeoPolygonQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildGeoPolygonQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/IQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/IQuery.cs
new file mode 100644
index 0000000..b937c54
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/IQuery.cs
@@ -0,0 +1,16 @@
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ /**
+ * IQuery接口,具体介绍请查看具体的实现类的说明
+ */
+ public interface IQuery
+ {
+
+ QueryType GetQueryType();
+
+ ByteString Serialize();
+
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchAllQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchAllQuery.cs
new file mode 100644
index 0000000..11f6703
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchAllQuery.cs
@@ -0,0 +1,21 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 获取所有的文档,所有文档分数为1。返回的结果中:命中数永远都是正确的。加入返回的结果过多,SearchIndex会只返回部分数据。
+ ///
+ public class MatchAllQuery : IQuery
+ {
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_MatchAllQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildMatchAllQuery().ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchPhraseQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchPhraseQuery.cs
new file mode 100644
index 0000000..20fa777
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchPhraseQuery.cs
@@ -0,0 +1,30 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 类似 {@link MatchQuery} (MatchQuery 仅匹配某个词即可),但是 MatchPhraseQuery会匹配所有的短语。
+ ///
+ public class MatchPhraseQuery : IQuery
+ {
+ public string FieldName { get; set; }
+ public string Text { get; set; }
+
+ public MatchPhraseQuery(string fieldName, string text)
+ {
+ this.FieldName = fieldName;
+ this.Text = text;
+ }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_MatchPhraseQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildMatchPhraseQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchQuery.cs
new file mode 100644
index 0000000..21124c4
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/MatchQuery.cs
@@ -0,0 +1,46 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 包括模糊匹配和短语或邻近查询
+ ///
+ public class MatchQuery : IQuery
+ {
+ ///
+ /// 字段
+ ///
+ public string FieldName { get; set; }
+ ///
+ /// 模糊匹配的值
+ ///
+ public string Text { get; set; }
+
+ ///
+ /// 最小匹配个数
+ ///
+ public int? MinimumShouldMatch { get; set; }
+
+ ///
+ /// 操作符
+ ///
+ public QueryOperator Operator { get; set; }
+
+ public MatchQuery(string fieldName, string text)
+ {
+ this.FieldName = fieldName;
+ this.Text = text;
+ }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_MatchQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildMatchQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/NestedQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/NestedQuery.cs
new file mode 100644
index 0000000..b2ad64c
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/NestedQuery.cs
@@ -0,0 +1,36 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ ///嵌套查询可以查询嵌套的对象/文档。
+ ///举例:我们的文档是这样的:{"id":"1","os":{"name":"win7","ip":"127.0.0.1"}},我们想搜索os的name,
+ ///但是不能直接查询,需要通过{@link NestedQuery}来进行查询。在"path"设置为“os”,然后query中放一个正常的Query
+ ///
+ public class NestedQuery : IQuery
+ {
+ ///
+ /// 嵌套文档的路径
+ ///
+ public string Path { get; set; }
+ ///
+ /// 一个query
+ ///
+ public IQuery Query { get; set; }
+ ///
+ /// 多值字段获取文档得分的模式
+ ///
+ public ScoreMode ScoreMode { get; set; }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_NestedQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildNestedQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/PrefixQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/PrefixQuery.cs
new file mode 100644
index 0000000..1d352e8
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/PrefixQuery.cs
@@ -0,0 +1,32 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 匹配前缀。比如搜索“name”是以“王”字开头的所有人。
+ ///
+ public class PrefixQuery : IQuery
+ {
+ public string FieldName { get; set; }
+ /**
+ * 字符串前缀
+ */
+ public string Prefix { get; set; }
+
+ public PrefixQuery(string fieldName, string prefix) {
+ this.FieldName = fieldName;
+ this.Prefix = prefix;
+ }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_PrefixQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildPrefixQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryOperator.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryOperator.cs
new file mode 100644
index 0000000..be370e1
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryOperator.cs
@@ -0,0 +1,8 @@
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ public enum QueryOperator
+ {
+ OR,
+ AND
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryType.cs
new file mode 100644
index 0000000..fe32272
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/QueryType.cs
@@ -0,0 +1,25 @@
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ /**
+ * SearchIndex支持的Query类型
+ */
+ public enum QueryType
+ {
+ QueryType_None,
+ QueryType_MatchQuery,
+ QueryType_MatchPhraseQuery,
+ QueryType_TermQuery,
+ QueryType_RangeQuery,
+ QueryType_PrefixQuery,
+ QueryType_BoolQuery,
+ QueryType_ConstScoreQuery,
+ QueryType_FunctionScoreQuery,
+ QueryType_NestedQuery,
+ QueryType_WildcardQuery,
+ QueryType_MatchAllQuery,
+ QueryType_GeoBoundingBoxQuery,
+ QueryType_GeoDistanceQuery,
+ QueryType_GeoPolygonQuery,
+ QueryType_TermsQuery
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/RangeQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/RangeQuery.cs
new file mode 100644
index 0000000..4f72b05
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/RangeQuery.cs
@@ -0,0 +1,49 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 范围查询。通过设置一个范围(from,to),查询该范围内的所有数据。
+ ///
+ public class RangeQuery : IQuery
+ {
+ ///
+ /// 字段名
+ ///
+ public string FieldName { get; set; }
+ ///
+ /// 字段取值的下界
+ ///
+ public ColumnValue From { get; set; }
+ ///
+ /// 字段取值的上界
+ ///
+ public ColumnValue To { get; set; }
+ ///
+ /// 范围取值是否包含下界
+ ///
+ public bool IncludeLower { get; set; }
+ ///
+ /// 范围取值是否包含上界
+ ///
+ public bool IncludeUpper { get; set; }
+
+ public RangeQuery(string fieldName, ColumnValue from, ColumnValue to)
+ {
+ this.FieldName = fieldName;
+ this.From = from;
+ this.To = to;
+ }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_RangeQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildRangeQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ScoreMode.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ScoreMode.cs
new file mode 100644
index 0000000..d06b4e3
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/ScoreMode.cs
@@ -0,0 +1,16 @@
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+
+ ///
+ /// 一个字段多个值的情况下,采用哪个值来进行排序。
+ ///举例:有一个小学生学生状态监测系统,其中存了小学生的身高,但是小学生身高一直在长,所以“身高”这个字段,采用了array的方式。然后我们查询的时候,想根据身高进行排序,就可以设置ScoreMode为MAX,这样就能得到最近的一次身高
+ ///
+ public enum ScoreMode
+ {
+ None,
+ Avg,
+ Max,
+ Min,
+ Total,
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermQuery.cs
new file mode 100644
index 0000000..b8bebd5
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermQuery.cs
@@ -0,0 +1,30 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 精确的term查询。
+ ///
+ public class TermQuery : IQuery
+ {
+ public string FieldName { get; set; }
+ public ColumnValue Term { get; set; }
+
+ public TermQuery(string fieldName, ColumnValue term)
+ {
+ this.FieldName = fieldName;
+ this.Term = term;
+ }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_TermQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildTermQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermsQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermsQuery.cs
new file mode 100644
index 0000000..26fd5f8
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/TermsQuery.cs
@@ -0,0 +1,23 @@
+using System.Collections.Generic;
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ public class TermsQuery : IQuery
+ {
+ public string FieldName { get; set; }
+
+ public List Terms { get; set; }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_TermsQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildTermsQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/WildcardQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/WildcardQuery.cs
new file mode 100644
index 0000000..d112a3e
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Query/WildcardQuery.cs
@@ -0,0 +1,31 @@
+using com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+
+namespace Aliyun.OTS.DataModel.Search.Query
+{
+ ///
+ /// 通配符查询。支持 *( 任意0或多个)和 ?(任意1个字符)。
+ ///举例:名字字段是“name”,想查询名字中包含“龙”的人,就可以“* 龙*” ,但是效率可能不高。
+ ///
+ public class WildcardQuery : IQuery
+ {
+ public string FieldName { get; set; }
+ public string Value { get; set; }
+
+ public WildcardQuery(string fieldName, string value)
+ {
+ this.FieldName = fieldName;
+ this.Value = value;
+ }
+
+ public QueryType GetQueryType()
+ {
+ return QueryType.QueryType_WildcardQuery;
+ }
+
+ public ByteString Serialize()
+ {
+ return SearchQueryBuilder.BuildWildcardQuery(this).ToByteString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchIndexInfo.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchIndexInfo.cs
new file mode 100644
index 0000000..ba1dd7c
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchIndexInfo.cs
@@ -0,0 +1,8 @@
+namespace Aliyun.OTS.DataModel.Search
+{
+ public class SearchIndexInfo
+ {
+ public string TableName { get; set; }
+ public string IndexName { get; set; }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchQuery.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchQuery.cs
new file mode 100644
index 0000000..35f4566
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/SearchQuery.cs
@@ -0,0 +1,50 @@
+using Aliyun.OTS.DataModel.Search.Query;
+
+namespace Aliyun.OTS.DataModel.Search
+{
+ public class SearchQuery
+ {
+ ///
+ /// 分页起始数量
+ ///
+ public int? Offset { get; set; }
+ ///
+ /// 分页大小,即返回的行数
+ ///
+ public int? Limit { get; set; }
+ ///
+ /// 查询语句
+ ///
+ public IQuery Query { get; set; }
+ ///
+ /// 字段折叠
+ /// 能够实现某个字段的结果去重。
+ ///
+ public Collapse Collapse { get; set; }
+ ///
+ /// 排序
+ /// 设置结果的排序方式,该参数支持多字段排序
+ ///
+ public Sort.Sort Sort { get; set; }
+ ///
+ /// 获取总行数,默认设置为false
+ ///
+ public bool GetTotalCount { get; set; }
+
+ private byte[] token { get; set; }
+
+ public byte[] Token
+ {
+ get
+ {
+ return this.token;
+ }
+ set
+ {
+ //Token中编码了Sort条件,所以设置Token时不需要设置Sort
+ this.token = value;
+ this.Sort = null;
+ }
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/FieldSort.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/FieldSort.cs
new file mode 100644
index 0000000..de8b1ed
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/FieldSort.cs
@@ -0,0 +1,24 @@
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ public class FieldSort : ISorter
+ {
+ private SortOrder order = SortOrder.ASC;
+
+ public string FieldName { get; set; }
+ public SortMode Mode { get; set; }
+ public NestedFilter NestedFilter { get; set; }
+
+ public SortOrder Order
+ {
+ get { return order; }
+ set { order = value; }
+ }
+
+ public FieldSort(string fieldName, SortOrder order)
+ {
+ this.FieldName = fieldName;
+ this.Order = order;
+ }
+ }
+}
+
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceSort.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceSort.cs
new file mode 100644
index 0000000..cde38f8
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceSort.cs
@@ -0,0 +1,39 @@
+using System;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ public class GeoDistanceSort : ISorter
+ {
+ /**
+ * 排序的字段
+ */
+ public string FieldName { get; set; }
+ /**
+ * 排序的地理位置点
+ */
+ public List Points { get; set; }
+ /**
+ * 升序或降序
+ */
+ public SortOrder Order { get; set; }
+ /**
+ * 多值字段的排序依据
+ */
+ public SortMode Mode { get; set; }
+ /**
+ * 计算两点距离的算法
+ */
+ public GeoDistanceType DistanceType { get; set; }
+ /**
+ * 嵌套的过滤器
+ */
+ public NestedFilter NestedFilter { get; set; }
+
+ public GeoDistanceSort(String fieldName, List points)
+ {
+ this.FieldName = fieldName;
+ this.Points = points;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceType.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceType.cs
new file mode 100644
index 0000000..2e19cd4
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/GeoDistanceType.cs
@@ -0,0 +1,18 @@
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+
+ /**
+ * 地理空间类型的Field在计算距离的时候采用的模型(默认为ARC)
+ */
+ public enum GeoDistanceType
+ {
+ /**
+ * 弧形(因为地球是弧形的,采用该设置可精确距离,但计算量较大)
+ */
+ ARC,
+ /**
+ * 把地球看成平面,计算两点距离(精确值不够,但是计算量小)
+ */
+ PLANE
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ISorter.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ISorter.cs
new file mode 100644
index 0000000..fe54ecb
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ISorter.cs
@@ -0,0 +1,6 @@
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ public interface ISorter
+ {
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/NestedFilter.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/NestedFilter.cs
new file mode 100644
index 0000000..c24847e
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/NestedFilter.cs
@@ -0,0 +1,19 @@
+using Aliyun.OTS.DataModel.Search.Query;
+
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ /**
+ * 一个嵌套的过滤器
+ */
+ public class NestedFilter
+ {
+ public string Path { get; set; }
+ public IQuery Query { get; set; }
+
+ public NestedFilter(string path, IQuery query)
+ {
+ this.Path = path;
+ this.Query = query;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/PrimaryKeySort.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/PrimaryKeySort.cs
new file mode 100644
index 0000000..d0b3bd6
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/PrimaryKeySort.cs
@@ -0,0 +1,14 @@
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ public class PrimaryKeySort : ISorter
+ {
+ public SortOrder Order { get; set; }
+
+ public PrimaryKeySort() { }
+
+ public PrimaryKeySort(SortOrder order)
+ {
+ this.Order = order;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ScoreSort.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ScoreSort.cs
new file mode 100644
index 0000000..c2b5e89
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/ScoreSort.cs
@@ -0,0 +1,19 @@
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ public class ScoreSort : ISorter
+ {
+ private SortOrder order = SortOrder.DESC;
+
+ public SortOrder Order
+ {
+ get
+ {
+ return order;
+ }
+ set
+ {
+ order = value;
+ }
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/Sort.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/Sort.cs
new file mode 100644
index 0000000..10f5403
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/Sort.cs
@@ -0,0 +1,14 @@
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ public class Sort
+ {
+ public List Sorters { get; set; }
+
+ public Sort(List sorters)
+ {
+ this.Sorters = sorters;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortMode.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortMode.cs
new file mode 100644
index 0000000..03d5d00
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortMode.cs
@@ -0,0 +1,15 @@
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+
+ /**
+ * 选取一个Field的哪个值进行排序
+ * 大多数情况下,一个字段只有一个值,所以这项无意义,默认为 MIN
+ * 当一个字段是一个集合(Array)时候,可以设置用该集合中的某一个值作为排序的依据
+ */
+ public enum SortMode
+ {
+ MIN,
+ MAX,
+ AVG
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortOrder.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortOrder.cs
new file mode 100644
index 0000000..10613b2
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/Sort/SortOrder.cs
@@ -0,0 +1,11 @@
+namespace Aliyun.OTS.DataModel.Search.Sort
+{
+ /**
+ * 排序的顺序(升序或降序)
+ */
+ public enum SortOrder
+ {
+ ASC,
+ DESC
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/Search/SyncStat.cs b/netstandard-sdk/Aliyun/OTS/DataModel/Search/SyncStat.cs
new file mode 100644
index 0000000..882a821
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/Search/SyncStat.cs
@@ -0,0 +1,15 @@
+namespace Aliyun.OTS.DataModel.Search
+{
+ public enum SyncPhase
+ {
+ FULL,
+ INCR
+ }
+
+ public class SyncStat
+ {
+
+ public SyncPhase SyncPhase;
+ public long CurrentSyncTimestamp;
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/SingleRowQueryCriteria.cs b/netstandard-sdk/Aliyun/OTS/DataModel/SingleRowQueryCriteria.cs
new file mode 100644
index 0000000..bc7987b
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/SingleRowQueryCriteria.cs
@@ -0,0 +1,44 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ */
+
+namespace Aliyun.OTS.DataModel
+{
+ public class SingleRowQueryCriteria : RowQueryCriteria, IRow
+ {
+ ///
+ /// 设置和获取主键
+ ///
+ public PrimaryKey RowPrimaryKey {get;set;}
+
+ ///
+ /// 用于行内流式读, 标记位置和状态信息.
+ ///
+ /// The token.
+ public byte[] Token { get; set; }
+
+ ///
+ /// 构造一个在给定名称的表中查询的条件。
+ ///
+ /// 查询的表名
+ public SingleRowQueryCriteria(string tableName)
+ : base(tableName)
+ { }
+
+ public PrimaryKey GetPrimaryKey()
+ {
+ return this.RowPrimaryKey;
+ }
+
+ public int CompareTo(IRow other)
+ {
+ return this.RowPrimaryKey.CompareTo(other.GetPrimaryKey());
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/StreamDetails.cs b/netstandard-sdk/Aliyun/OTS/DataModel/StreamDetails.cs
new file mode 100644
index 0000000..b23870a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/StreamDetails.cs
@@ -0,0 +1,32 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ public class StreamDetails
+ {
+ ///
+ /// 该表是否打开stream
+ ///
+ public bool EnableStream { private set; get; }
+
+ ///
+ /// 该表的stream的id
+ ///
+ public string StreamId { set; get; }
+
+ ///
+ /// 该表的stream的过期时间
+ ///
+ public int ExpirationTime { set; get; }
+
+ ///
+ /// 该stream的打开的时间
+ ///
+ public Int64 LastEnableTime { set; get; }
+
+
+ public StreamDetails(bool enableStream)
+ {
+ EnableStream = enableStream;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/StreamSpecification.cs b/netstandard-sdk/Aliyun/OTS/DataModel/StreamSpecification.cs
new file mode 100644
index 0000000..6ef86e9
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/StreamSpecification.cs
@@ -0,0 +1,15 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ public class StreamSpecification
+ {
+ public bool EnableStream { get; set; }
+
+ public int ExpirationTime { get; set; }
+
+ public StreamSpecification( bool enableStream)
+ {
+ EnableStream = enableStream;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/TableMeta.cs b/netstandard-sdk/Aliyun/OTS/DataModel/TableMeta.cs
new file mode 100644
index 0000000..d00d68b
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/TableMeta.cs
@@ -0,0 +1,49 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表的元信息。建表时需要设定TableMeta,DescribeTable时可以返回这个TableMeta。
+ ///
+ public class TableMeta
+ {
+ ///
+ /// 表名
+ ///
+ public string TableName { get; set; }
+
+ ///
+ /// 主键的设计,包括每一个主键列的列名和列值类型,有序。
+ ///
+ public PrimaryKeySchema PrimaryKeySchema { get; set; }
+
+ ///
+ /// 预定义列
+ ///
+ public DefinedColumnSchema DefinedColumnSchema { get; set; }
+
+ public TableMeta(string tableName, PrimaryKeySchema primaryKeySchema)
+ {
+ TableName = tableName;
+ PrimaryKeySchema = primaryKeySchema;
+ }
+
+ public TableMeta(string tableName, DefinedColumnSchema definedColumnSchema)
+ {
+ TableName = tableName;
+ DefinedColumnSchema = definedColumnSchema;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/TableOptions.cs b/netstandard-sdk/Aliyun/OTS/DataModel/TableOptions.cs
new file mode 100644
index 0000000..bbd4cac
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/TableOptions.cs
@@ -0,0 +1,28 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ public class TableOptions
+ {
+ ///
+ /// 本张表中保存的数据的存活时间,单位秒
+ ///
+ public int? TimeToLive{ get; set; }
+
+ ///
+ /// 本张表保留的最大版本数
+ ///
+ public int? MaxVersions{ get; set; }
+
+ ///
+ /// 最大版本偏差,目的主要是为了禁止写入与预期较大的数据
+ ///
+ public Int64? DeviationCellVersionInSec { get; set; }
+
+ public BloomFilterType? BloomFilterType { get; set; } // 可以动态更改
+
+ ///
+ /// 最大版本偏差,目的主要是为了禁止写入与预期较大的数据
+ ///
+ public int? BlockSize { get; set; }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/TimeRange.cs b/netstandard-sdk/Aliyun/OTS/DataModel/TimeRange.cs
new file mode 100644
index 0000000..bcd7b35
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/TimeRange.cs
@@ -0,0 +1,10 @@
+using System;
+namespace Aliyun.OTS.DataModel
+{
+ public class TimeRange
+ {
+ public Int64? StartTime { get; set; }
+ public Int64? EndTime { get; set; }
+ public Int64? SpecificTime { get; set; }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/DataModel/UpdateOfAttribute.cs b/netstandard-sdk/Aliyun/OTS/DataModel/UpdateOfAttribute.cs
new file mode 100644
index 0000000..cfb3407
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/DataModel/UpdateOfAttribute.cs
@@ -0,0 +1,47 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Collections.Generic;
+
+namespace Aliyun.OTS.DataModel
+{
+ ///
+ /// 表示对属性的修改,用于接口。
+ ///
+ public class UpdateOfAttribute
+ {
+ ///
+ /// 表示要删除的列的列名List。
+ ///
+ public IList AttributeColumnsToDelete { get; private set; }
+
+ ///
+ /// 表示要写入的列的列名和列值。
+ ///
+ public IDictionary AttributeColumnsToPut { get; private set; }
+
+ public UpdateOfAttribute()
+ {
+ AttributeColumnsToDelete = new List();
+ AttributeColumnsToPut = new Dictionary();
+ }
+
+ public void AddAttributeColumnToDelete(string columnName)
+ {
+ AttributeColumnsToDelete.Add(columnName);
+ }
+
+ public void AddAttributeColumnToPut(string columnName, ColumnValue columnValue)
+ {
+ AttributeColumnsToPut.Add(columnName, columnValue);
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/Context.cs b/netstandard-sdk/Aliyun/OTS/Handler/Context.cs
new file mode 100644
index 0000000..84cdca0
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/Context.cs
@@ -0,0 +1,50 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Collections.Generic;
+using System.Net;
+using System.Net.Http;
+using System.Threading.Tasks;
+
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+
+namespace Aliyun.OTS.Handler
+{
+ public class Context
+ {
+ public OTSClientConfig ClientConfig { get; set; }
+
+ public HttpClient HttpClient { get; set; }
+ public string APIName { get; set; }
+ public Task HttpTask;
+
+ public int RetryTimes { get; set; }
+
+ // For Request
+ public OTSRequest OTSRequest { get; set; }
+ public string HttpRequestQuery { get; set; }
+ public Dictionary HttpRequestHeaders { get; set; }
+ public byte[] HttpRequestBody { get; set; }
+
+ // For Response
+ public OTSResponse OTSReponse { get; set; }
+ public HttpResponseMessage HttpResponseMessage { get; set; }
+ public HttpStatusCode HttpResponseStatusCode { get; set; }
+ public Dictionary HttpResponseHeaders { get; set; }
+ public byte[] HttpResponseBody { get; set; }
+
+ public Context()
+ {
+ RetryTimes = 0;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/ErrorHandler.cs b/netstandard-sdk/Aliyun/OTS/Handler/ErrorHandler.cs
new file mode 100644
index 0000000..6c6a654
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/ErrorHandler.cs
@@ -0,0 +1,89 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+
+using PB = com.alicloud.openservices.tablestore.core.protocol;
+
+namespace Aliyun.OTS.Handler
+{
+ public class ErrorHandler : PipelineHandler
+ {
+ public ErrorHandler(PipelineHandler innerHandler) : base(innerHandler) { }
+
+ public override void HandleBefore(Context context)
+ {
+ InnerHandler.HandleBefore(context);
+ }
+
+ private void throwOTSServerException(Context context)
+ {
+ var exception = new OTSServerException(context.APIName, context.HttpResponseStatusCode);
+ if (context.ClientConfig.OTSErrorLogHandler != null) {
+ context.ClientConfig.OTSErrorLogHandler(exception.ToString() + "\n");
+ }
+ throw exception;
+ }
+
+ public override void HandleAfter(Context context)
+ {
+
+ OTSServerException exception;
+ InnerHandler.HandleAfter(context);
+
+ var statusCode = context.HttpResponseStatusCode;
+
+ if ((int)statusCode >= 200 && (int)statusCode < 300)
+ {
+ return;
+ }
+
+ var builder = PB.Error.CreateBuilder();
+ string errorCode = null, errorMessage = null;
+
+ try
+ {
+ builder.MergeFrom(context.HttpResponseBody);
+ var message = builder.Build();
+ errorCode = message.Code;
+ errorMessage = message.Message;
+ } catch (Google.ProtocolBuffers.InvalidProtocolBufferException) {
+ throwOTSServerException(context);
+ } catch (Google.ProtocolBuffers.UninitializedMessageException) {
+ throwOTSServerException(context);
+ }
+
+ string requestID;
+ if (context.HttpResponseHeaders.ContainsKey("x-ots-requestid"))
+ {
+ requestID = context.HttpResponseHeaders["x-ots-requestid"];
+ }
+ else
+ {
+ requestID = null;
+ }
+
+ exception = new OTSServerException(
+ context.APIName,
+ statusCode,
+ errorCode,
+ errorMessage,
+ requestID
+ );
+
+ if(context.ClientConfig.OTSErrorLogHandler != null)
+ {
+ context.ClientConfig.OTSErrorLogHandler.Invoke(exception.ToString());
+ }
+
+ throw exception;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/HttpHandler.cs b/netstandard-sdk/Aliyun/OTS/Handler/HttpHandler.cs
new file mode 100644
index 0000000..15bcec3
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/HttpHandler.cs
@@ -0,0 +1,74 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Collections.Generic;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Net.Http;
+
+
+namespace Aliyun.OTS.Handler
+{
+ public class HttpHandler : PipelineHandler
+ {
+ public override void HandleBefore(Context context)
+ {
+ HttpContent content = new ByteArrayContent(context.HttpRequestBody);
+ content.Headers.Clear();
+
+ foreach (var item in context.HttpRequestHeaders)
+ {
+ content.Headers.Add(item.Key, item.Value);
+ }
+
+ Task task = context.HttpClient.PostAsync(context.APIName, content);
+ context.HttpTask = task;
+ }
+
+ public override void HandleAfter(Context context)
+ {
+ HttpResponseMessage responseMessage = context.HttpTask.Result;
+ var task = responseMessage.Content.ReadAsByteArrayAsync();
+ task.Wait();
+
+ if (OTSClientTestHelper.HTTPResponseBodyIsSet)
+ {
+ context.HttpResponseBody = OTSClientTestHelper.HTTPResponseBody;
+ }
+ else
+ {
+ context.HttpResponseBody = task.Result;
+ }
+
+ if (OTSClientTestHelper.HttpStatusCodeIsSet)
+ {
+ context.HttpResponseStatusCode = OTSClientTestHelper.HttpStatusCode;
+ }
+ else
+ {
+ context.HttpResponseStatusCode = responseMessage.StatusCode;
+ }
+
+ if (OTSClientTestHelper.HttpResponseHeadersIsSet)
+ {
+ context.HttpResponseHeaders = OTSClientTestHelper.HttpRequestHeaders;
+ }
+ else
+ {
+ context.HttpResponseHeaders = new Dictionary();
+ foreach (var item in responseMessage.Headers)
+ {
+ context.HttpResponseHeaders.Add(item.Key.ToLower(), item.Value.ElementAt(0));
+ }
+ }
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/HttpHeaderHandler.cs b/netstandard-sdk/Aliyun/OTS/Handler/HttpHeaderHandler.cs
new file mode 100644
index 0000000..002297a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/HttpHeaderHandler.cs
@@ -0,0 +1,231 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using System.Net;
+using System.Security.Cryptography;
+
+namespace Aliyun.OTS.Handler
+{
+ public class HttpHeaderHandler : PipelineHandler
+ {
+ public static int MAX_TIME_DEVIATION_IN_MINUTES = 15;
+
+ private static readonly string[] HeaderNames = {
+ "x-ots-contentmd5",
+ "x-ots-requestid",
+ "x-ots-date",
+ "x-ots-contenttype",
+ };
+
+ public HttpHeaderHandler(PipelineHandler innerHandler) : base(innerHandler) { }
+
+ private string MakeHeaderString(Dictionary headers)
+ {
+ List items = new List();
+
+ foreach (var item in headers)
+ {
+ if (item.Key.StartsWith("x-ots-", StringComparison.Ordinal))
+ {
+ items.Add(String.Format("{0}:{1}", item.Key, item.Value));
+ }
+ }
+
+ items.Sort();
+ return String.Join("\n", items);
+ }
+
+ private string ComputeSignature(string signatureString, string accessKeySecret)
+ {
+ var hmac = new HMACSHA1(System.Text.Encoding.ASCII.GetBytes(accessKeySecret));
+ byte[] hashValue = hmac.ComputeHash(System.Text.Encoding.ASCII.GetBytes(signatureString));
+ string signature = System.Convert.ToBase64String(hashValue);
+ return signature;
+ }
+
+ private string MakeRequestSignature(Context context, Dictionary headers)
+ {
+ string headerString = MakeHeaderString(headers);
+ string signatureString = context.APIName + "\nPOST\n\n" + headerString + '\n';
+ return ComputeSignature(signatureString, context.ClientConfig.AccessKeySecret);
+ }
+
+ private string MakeResponseSignature(Context context)
+ {
+ string headerString = MakeHeaderString(context.HttpResponseHeaders);
+ string signatureString = headerString + "\n" + context.APIName;
+ return ComputeSignature(signatureString, context.ClientConfig.AccessKeySecret);
+ }
+
+ public override void HandleBefore(Context context)
+ {
+
+ var headers = new Dictionary();
+
+ // Step 1, compute Content MD5
+ var md5hash = MD5.Create();
+ byte[] hashData = md5hash.ComputeHash(context.HttpRequestBody);
+ string contentMD5 = Convert.ToBase64String(hashData);
+ headers.Add("x-ots-contentmd5", contentMD5);
+
+ // Step 2, make date time string
+ var dateString = Util.OtsUtils.FormatDateTimeStr(DateTime.UtcNow);
+ headers.Add("x-ots-date", dateString);
+
+ // Step 3, other headers
+ headers.Add("x-ots-apiversion", context.ClientConfig.APIVersion);
+ headers.Add("x-ots-accesskeyid", context.ClientConfig.AccessKeyID);
+ headers.Add("x-ots-instancename", context.ClientConfig.InstanceName);
+
+ headers.Add("x-ots-user-agent", context.ClientConfig.UserAgent);
+
+ // Step 4, compute signature
+ string signature = MakeRequestSignature(context, headers);
+ headers.Add("x-ots-signature", signature);
+
+ context.HttpRequestHeaders = headers;
+
+ InnerHandler.HandleBefore(context);
+ }
+
+ private void CheckOtherHeaders(Context context)
+ {
+ var headers = context.HttpResponseHeaders;
+
+ // Step 1, make sure we have all headers
+ if ((int)context.HttpResponseStatusCode >= 200
+ && (int)context.HttpResponseStatusCode < 300)
+ {
+ foreach (string name in HeaderNames)
+ {
+ if (!headers.ContainsKey(name))
+ {
+ throw new OTSClientException(String.Format(
+ "{0} is missing in response header.", name
+ ));
+ }
+ }
+ }
+
+ // Step 2, check md5
+ if (headers.ContainsKey("x-ots-contentmd5"))
+ {
+ var md5hash = MD5.Create();
+ byte[] hashData = md5hash.ComputeHash(context.HttpResponseBody);
+ string contentMD5 = System.Convert.ToBase64String(hashData);
+ if (contentMD5 != headers["x-ots-contentmd5"])
+ {
+ throw new OTSClientException("MD5 mismatch in response.");
+ }
+ }
+
+ // Step 3, check date
+ if (headers.ContainsKey("x-ots-date"))
+ {
+ string serverTimeString = headers["x-ots-date"];
+ DateTime serverTime;
+ try
+ {
+ serverTime = DateTime.Parse(serverTimeString).ToUniversalTime();
+ }
+ catch (System.FormatException)
+ {
+ throw new OTSClientException(String.Format(
+ "Invalid date format in response: {0}", serverTimeString
+ ));
+ }
+
+ var clientTime = DateTime.UtcNow;
+ if (Math.Abs((serverTime - clientTime).TotalSeconds) > MAX_TIME_DEVIATION_IN_MINUTES * 60)
+ {
+ throw new OTSClientException("The difference between date in response and system time is more than 15 minutes.");
+ }
+ }
+
+ }
+
+ private void CheckAuthorization(Context context)
+ {
+ // Step 1, Check if authorization header is there
+ if (!context.HttpResponseHeaders.ContainsKey("authorization"))
+ {
+ if ((int)context.HttpResponseStatusCode >= 200
+ && (int)context.HttpResponseStatusCode < 300)
+ {
+ throw new OTSClientException("\"Authorization\" is missing in response header.");
+ }
+
+ return;
+ }
+
+ string authorization = context.HttpResponseHeaders["authorization"];
+
+ // Step 2, check if authorization is valid
+ if (!authorization.StartsWith("OTS ", StringComparison.Ordinal))
+ {
+ throw new OTSClientException("Invalid Authorization in response.");
+ }
+
+ string[] splits = authorization.Substring(4).Split(':');
+ if (splits.Length != 2)
+ {
+ throw new OTSClientException("Invalid Authorization in response.");
+ }
+
+ // Step 3, check accessKeyID
+ string accessKeyID = splits[0];
+ if (accessKeyID != context.ClientConfig.AccessKeyID)
+ {
+ throw new OTSClientException("Access Key ID mismatch in response.");
+ }
+
+ // Step 4, check signature
+ string signature = splits[1];
+ if (signature != MakeResponseSignature(context))
+ {
+ throw new OTSClientException("Signature mismatch in response.");
+ }
+ }
+
+ public override void HandleAfter(Context context)
+ {
+ InnerHandler.HandleAfter(context);
+
+ // Disable reponse validation
+ if (context.ClientConfig.SkipResponseValidation)
+ {
+ return;
+ }
+
+ try
+ {
+ CheckOtherHeaders(context);
+
+ // Header['authorization'] is not neccessarily available
+ // when HttpStatusCode.Forbidden happens.
+ if (context.HttpResponseStatusCode != HttpStatusCode.Forbidden)
+ {
+ CheckAuthorization(context);
+ }
+ }
+ catch (OTSClientException e)
+ {
+ // re-throw the exception with additonal information
+ throw new OTSClientException(
+ String.Format("{0} HTTP Status: {1}.", e.Message, context.HttpResponseStatusCode),
+ context.HttpResponseStatusCode
+ );
+ }
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/OTSHandler.cs b/netstandard-sdk/Aliyun/OTS/Handler/OTSHandler.cs
new file mode 100644
index 0000000..fd1a5b2
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/OTSHandler.cs
@@ -0,0 +1,40 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+
+namespace Aliyun.OTS.Handler
+{
+ public class OTSHandler : PipelineHandler
+ {
+ public OTSHandler()
+ {
+ PipelineHandler inner;
+ inner = new HttpHandler();
+ inner = new HttpHeaderHandler(inner);
+ inner = new ErrorHandler(inner);
+ inner = new ProtocolBufferDecoder(inner);
+ inner = new ProtocolBufferEncoder(inner);
+ inner = new RetryHandler(inner);
+ InnerHandler = inner;
+ }
+
+
+ public override void HandleBefore(Context context)
+ {
+ InnerHandler.HandleBefore(context);
+ }
+
+ public override void HandleAfter(Context context)
+ {
+ InnerHandler.HandleAfter(context);
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/PipelineHandler.cs b/netstandard-sdk/Aliyun/OTS/Handler/PipelineHandler.cs
new file mode 100644
index 0000000..9112c7a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/PipelineHandler.cs
@@ -0,0 +1,32 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+
+namespace Aliyun.OTS.Handler
+{
+ public abstract class PipelineHandler
+ {
+ protected PipelineHandler InnerHandler { get; set; }
+
+ protected PipelineHandler()
+ {
+ InnerHandler = null;
+ }
+
+ protected PipelineHandler(PipelineHandler innerHandler)
+ {
+ InnerHandler = innerHandler;
+ }
+
+ public abstract void HandleBefore(Context context);
+ public abstract void HandleAfter(Context context);
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferDecoder.cs b/netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferDecoder.cs
new file mode 100644
index 0000000..8668e0b
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferDecoder.cs
@@ -0,0 +1,772 @@
+using System;
+using System.Collections.Generic;
+using Google.ProtocolBuffers;
+using System.IO;
+using PB = com.alicloud.openservices.tablestore.core.protocol;
+using Aliyun.OTS.DataModel.Search;
+using com.alicloud.openservices.tablestore.core.protocol;
+
+namespace Aliyun.OTS.Handler
+{
+ public class ProtocolBufferDecoder : PipelineHandler
+ {
+ private delegate Response.OTSResponse ResponseDecoder(byte[] body, out IMessage message);
+ private readonly Dictionary DecoderMap;
+
+ public ProtocolBufferDecoder(PipelineHandler innerHandler) : base(innerHandler)
+ {
+ DecoderMap = new Dictionary() {
+ { "/CreateTable", DecodeCreateTable },
+ { "/DeleteTable", DecodeDeleteTable },
+ { "/UpdateTable", DecodeUpdateTable },
+ { "/DescribeTable", DecodeDescribeTable },
+ { "/ListTable", DecodeListTable },
+
+ { "/PutRow", DecodePutRow },
+ { "/GetRow", DecodeGetRow },
+ { "/UpdateRow", DecodeUpdateRow },
+ { "/DeleteRow", DecodeDeleteRow },
+
+ { "/BatchWriteRow", DecodeBatchWriteRow },
+ { "/BatchGetRow", DecodeBatchGetRow },
+ { "/GetRange", DecodeGetRange },
+
+ { "/ListSearchIndex", DecodeListSearchIndex },
+ { "/CreateSearchIndex", DecodeCreateSearchIndex },
+ { "/DescribeSearchIndex", DecodeDescribeSearchIndex },
+ { "/DeleteSearchIndex", DecodeDeleteSearchIndex },
+ { "/Search", DecodeSearch },
+
+ { "/CreateIndex", DecodeCreateGlobalIndex },
+ { "/DropIndex", DecodeDeleteGlobalIndex },
+ };
+ }
+
+ public override void HandleBefore(Context context)
+ {
+ InnerHandler.HandleBefore(context);
+ }
+
+ public override void HandleAfter(Context context)
+ {
+ InnerHandler.HandleAfter(context);
+ IMessage message;
+ context.OTSReponse = DecoderMap[context.APIName](context.HttpResponseBody, out message);
+ LogEncodedMessage(context, message);
+ }
+
+ private void LogEncodedMessage(Context context, IMessage message)
+ {
+ if (context.ClientConfig.OTSDebugLogHandler != null)
+ {
+ string requestID = "";
+ if (context.HttpResponseHeaders.ContainsKey("x-ots-requestid"))
+ {
+ requestID = context.HttpResponseHeaders["x-ots-requestid"];
+ }
+ var msgString = String.Format("OTS Response API: {0} RequestID: {1} Protobuf: {2}\n",
+ context.APIName,
+ requestID,
+ TextFormat.PrintToString(message));
+
+ context.ClientConfig.OTSDebugLogHandler(msgString);
+ }
+ }
+
+ private Response.OTSResponse DecodeCreateTable(byte[] body, out IMessage _message)
+ {
+ var response = new Response.CreateTableResponse();
+ var builder = PB.CreateTableResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeDeleteTable(byte[] body, out IMessage _message)
+ {
+ var response = new Response.DeleteTableResponse();
+ var builder = PB.DeleteTableResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeUpdateTable(byte[] body, out IMessage _message)
+ {
+ var builder = PB.UpdateTableResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ var response = new Response.UpdateTableResponse(
+ ParseReservedThroughputDetails(message.ReservedThroughputDetails)
+ );
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeListTable(byte[] body, out IMessage _message)
+ {
+ var response = new Response.ListTableResponse
+ {
+ TableNames = new List()
+ };
+
+ var builder = PB.ListTableResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+
+ for (int i = 0; i < message.TableNamesCount; i++)
+ {
+ response.TableNames.Add(message.GetTableNames(i));
+ }
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeDescribeTable(byte[] body, out IMessage _message)
+ {
+ var response = new Response.DescribeTableResponse();
+ var builder = PB.DescribeTableResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ response.TableMeta = ParseTableMeta(message.TableMeta);
+ response.ReservedThroughputDetails = ParseReservedThroughputDetails(message.ReservedThroughputDetails);
+ response.StreamDetails = ParseStreamDetails(message.StreamDetails);
+ response.TableOptions = ParseTableOptions(message.TableOptions);
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodePutRow(byte[] body, out IMessage _message)
+ {
+ var builder = PB.PutRowResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+
+ DataModel.Row row = null;
+ if (message.HasRow && !message.Row.IsEmpty)
+ {
+ row = ParseRow(message.Row);
+ }
+ else
+ {
+ row = new DataModel.Row(new DataModel.PrimaryKey(), new List());
+ }
+
+ var response = new Response.PutRowResponse(
+ ParseCapacityUnit(message.Consumed.CapacityUnit),
+ row
+ );
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeGetRow(byte[] body, out IMessage _message)
+ {
+ var builder = PB.GetRowResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+
+ DataModel.Row row = null;
+
+ if (message.HasRow && !message.Row.IsEmpty)
+ {
+ row = ParseRow(message.Row);
+ }
+ else
+ {
+ row = new DataModel.Row(new DataModel.PrimaryKey(), new List());
+ }
+
+ var primaryKey = row.GetPrimaryKey();
+ var columns = row.GetColumns();
+
+ var response = new Response.GetRowResponse(
+ ParseCapacityUnit(message.Consumed.CapacityUnit),
+ row
+ );
+
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeUpdateRow(byte[] body, out IMessage _message)
+ {
+ var builder = PB.UpdateRowResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+
+ DataModel.Row row = null;
+
+ if (message.HasRow && !message.Row.IsEmpty)
+ {
+ row = ParseRow(message.Row);
+ }
+ else
+ {
+ row = new DataModel.Row(new DataModel.PrimaryKey(), new List());
+ }
+
+ var response = new Response.UpdateRowResponse(
+ ParseCapacityUnit(message.Consumed.CapacityUnit),
+ row
+ );
+ _message = message;
+ return response;
+ }
+
+
+
+ private Response.OTSResponse DecodeDeleteRow(byte[] body, out IMessage _message)
+ {
+ var builder = PB.DeleteRowResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+
+ DataModel.Row row = null;
+ if (message.HasRow && !message.Row.IsEmpty)
+ {
+ row = ParseRow(message.Row);
+ }
+ else
+ {
+ row = new DataModel.Row(new DataModel.PrimaryKey(), new List());
+ }
+
+ var response = new Response.DeleteRowResponse(
+ ParseCapacityUnit(message.Consumed.CapacityUnit),
+ row
+ );
+ _message = message;
+ return response;
+ }
+
+ private DataModel.Row ParseRow(ByteString row)
+ {
+ PB.PlainBufferCodedInputStream inputStream = new PB.PlainBufferCodedInputStream(row.CreateCodedInput());
+ List rows = inputStream.ReadRowsWithHeader();
+ if (rows.Count != 1)
+ {
+ throw new IOException("Expect only returns one row. Row count: " + rows.Count);
+ }
+
+ return PB.PlainBufferConversion.ToRow(rows[0]) as DataModel.Row;
+ }
+
+ private Response.OTSResponse DecodeBatchWriteRow(byte[] body, out IMessage _message)
+ {
+ var builder = PB.BatchWriteRowResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+
+ var response = new Response.BatchWriteRowResponse();
+
+ foreach (var table in message.TablesList)
+ {
+ var item = ParseTableInBatchWriteRowResponse(table);
+ response.TableRespones.Add(table.TableName, item);
+ }
+
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeBatchGetRow(byte[] body, out IMessage _message)
+ {
+ var builder = PB.BatchGetRowResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ var response = new Response.BatchGetRowResponse();
+
+ foreach (var table in message.TablesList)
+ {
+ response.Add(table.TableName, ParseTableInBatchGetRowResponse(table));
+ }
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeGetRange(byte[] body, out IMessage _message)
+ {
+ var builder = PB.GetRangeResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ var response = new Response.GetRangeResponse
+ {
+ ConsumedCapacityUnit = ParseCapacityUnit(message.Consumed.CapacityUnit)
+ };
+
+ if (!message.HasNextStartPrimaryKey)
+ {
+ response.NextPrimaryKey = null;
+ }
+ else
+ {
+ var inputStream = new PB.PlainBufferCodedInputStream(message.NextStartPrimaryKey.CreateCodedInput());
+ var rows = inputStream.ReadRowsWithHeader();
+ if (rows.Count != 1)
+ {
+ throw new IOException("Expect only one row return. Row count: " + rows.Count);
+ }
+
+ PB.PlainBufferRow row = rows[0];
+ if (row.HasDeleteMarker() || row.HasCells())
+ {
+ throw new IOException("The next primary key should only have primary key: " + row);
+ }
+
+ response.NextPrimaryKey = PB.PlainBufferConversion.ToPrimaryKey(row.GetPrimaryKey());
+ }
+
+
+ if (message.HasRows && !message.Rows.IsEmpty)
+ {
+ List rows = new List();
+ var inputStream = new PB.PlainBufferCodedInputStream(message.Rows.CreateCodedInput());
+
+ List pbRows = inputStream.ReadRowsWithHeader();
+ foreach (var pbRow in pbRows)
+ {
+
+ rows.Add((DataModel.Row)PB.PlainBufferConversion.ToRow(pbRow));
+ }
+
+ response.RowDataList = rows;
+ }
+
+ if (message.HasNextToken)
+ {
+ response.NextToken = message.NextToken.ToByteArray();
+ }
+
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeListSearchIndex(byte[] body, out IMessage _message)
+ {
+ var response = new Response.ListSearchIndexResponse
+ {
+ IndexInfos = new List()
+ };
+
+ var builder = PB.ListSearchIndexResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+
+ for (int i = 0; i < message.IndicesCount; i++)
+ {
+ PB.IndexInfo indexInfo = message.GetIndices(i);
+ SearchIndexInfo searchIndexInfo = new SearchIndexInfo();
+ searchIndexInfo.TableName = indexInfo.TableName;
+ searchIndexInfo.IndexName = indexInfo.IndexName;
+ response.IndexInfos.Add(searchIndexInfo);
+ }
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeCreateSearchIndex(byte[] body, out IMessage _message)
+ {
+ var response = new Response.CreateSearchIndexResponse();
+ var builder = PB.CreateSearchIndexResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeDeleteSearchIndex(byte[] body, out IMessage _message)
+ {
+ var response = new Response.DeleteSearchIndexResponse();
+ var builder = PB.DeleteSearchIndexResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ _message = message;
+ return response;
+ }
+
+ private Response.OTSResponse DecodeSearch(byte[] body, out IMessage _message)
+ {
+ var response = new Response.SearchResponse();
+ var builder = PB.SearchResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ _message = message;
+
+ response.TotalCount = message.TotalHits;
+ response.IsAllSuccess = message.IsAllSucceeded;
+ response.Rows = new List();
+
+ foreach (var item in message.RowsList)
+ {
+ PlainBufferCodedInputStream coded = new PlainBufferCodedInputStream(item.CreateCodedInput());
+ List plainBufferRows = coded.ReadRowsWithHeader();
+ if (plainBufferRows.Count != 1)
+ {
+ throw new IOException("Expect only returns one row. Row count: " + plainBufferRows.Count);
+ }
+ var row = PlainBufferConversion.ToRow(plainBufferRows[0]);
+ response.Rows.Add(row as DataModel.Row);
+ }
+ if (message.HasNextToken)
+ {
+ response.NextToken = message.NextToken.ToByteArray();
+ }
+
+ return response;
+ }
+
+ private Response.OTSResponse DecodeDescribeSearchIndex(byte[] body, out IMessage _message)
+ {
+ var response = new Response.DescribeSearchIndexResponse();
+ var builder = PB.DescribeSearchIndexResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ response.Schema = ParseIndexSchema(message.Schema);
+ response.SyncStat = ParseSyncStat(message.SyncStat);
+ _message = message;
+ return response;
+ }
+
+ private DataModel.Search.SyncStat ParseSyncStat(PB.SyncStat syncStat)
+ {
+ var ret = new DataModel.Search.SyncStat();
+ ret.CurrentSyncTimestamp = syncStat.CurrentSyncTimestamp;
+ ret.SyncPhase = ParseSyncPhase(syncStat.SyncPhase);
+ return ret;
+ }
+
+ private DataModel.Search.SyncPhase ParseSyncPhase(PB.SyncPhase syncPhase)
+ {
+ switch (syncPhase)
+ {
+ case PB.SyncPhase.FULL:
+ return DataModel.Search.SyncPhase.FULL;
+ case PB.SyncPhase.INCR:
+ return DataModel.Search.SyncPhase.INCR;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid indexOptions SyncPhase type {0}", syncPhase)
+ );
+ }
+
+ }
+
+ private DataModel.Search.IndexSchema ParseIndexSchema(PB.IndexSchema indexSchema)
+ {
+ var ret = new DataModel.Search.IndexSchema();
+ ret.IndexSetting = ParseIndexSetting(indexSchema.IndexSetting);
+ ret.FieldSchemas = new List();
+ foreach (var item in indexSchema.FieldSchemasList)
+ {
+ ret.FieldSchemas.Add(ParseFieldSchema(item));
+ }
+ return ret;
+ }
+
+ private DataModel.Search.FieldSchema ParseFieldSchema(PB.FieldSchema fieldSchema)
+ {
+ var ret = new DataModel.Search.FieldSchema(fieldSchema.FieldName, ParseFieldType(fieldSchema.FieldType));
+ ret.Analyzer = ParseAnalyzer(fieldSchema.Analyzer);
+ ret.EnableSortAndAgg = fieldSchema.DocValues;
+ ret.index = fieldSchema.Index;
+ ret.Store = fieldSchema.Store;
+ ret.IsArray = fieldSchema.IsArray;
+ ret.IndexOptions = ParseIndexOption(fieldSchema.IndexOptions);
+ foreach (var item in fieldSchema.FieldSchemasList)
+ {
+ ret.SubFieldSchemas.Add(ParseFieldSchema(item));
+ }
+
+ return ret;
+ }
+
+ private DataModel.Search.IndexOptions ParseIndexOption(PB.IndexOptions indexOptions)
+ {
+ switch (indexOptions)
+ {
+ case PB.IndexOptions.DOCS:
+ return DataModel.Search.IndexOptions.DOCS;
+ case PB.IndexOptions.FREQS:
+ return DataModel.Search.IndexOptions.FREQS;
+ case PB.IndexOptions.OFFSETS:
+ return DataModel.Search.IndexOptions.OFFSETS;
+ case PB.IndexOptions.POSITIONS:
+ return DataModel.Search.IndexOptions.POSITIONS;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid indexOptions type {0}", indexOptions)
+ );
+ }
+ }
+
+ private DataModel.Search.FieldType ParseFieldType(PB.FieldType fieldType)
+ {
+ switch (fieldType)
+ {
+ case PB.FieldType.BOOLEAN:
+ return DataModel.Search.FieldType.BOOLEAN;
+ case PB.FieldType.DOUBLE:
+ return DataModel.Search.FieldType.DOUBLE;
+ case PB.FieldType.GEO_POINT:
+ return DataModel.Search.FieldType.GEO_POINT;
+ case PB.FieldType.KEYWORD:
+ return DataModel.Search.FieldType.KEYWORD;
+ case PB.FieldType.LONG:
+ return DataModel.Search.FieldType.LONG;
+ case PB.FieldType.NESTED:
+ return DataModel.Search.FieldType.NESTED;
+ case PB.FieldType.TEXT:
+ return DataModel.Search.FieldType.TEXT;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid FieldType type {0}", fieldType)
+ );
+ }
+ }
+
+ private DataModel.Search.Analyzer ParseAnalyzer(string analyzer)
+ {
+ switch (analyzer)
+ {
+ case "max_word":
+ return Analyzer.MaxWord;
+ case "single_word":
+ return Analyzer.SingleWord;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid Analyzer type {0}", analyzer)
+ );
+ }
+ }
+
+ private DataModel.Search.IndexSetting ParseIndexSetting(PB.IndexSetting indexSetting)
+ {
+ var ret = new DataModel.Search.IndexSetting();
+ foreach (var item in indexSetting.RoutingFieldsList)
+ {
+ ret.RoutingFields.Add(item);
+ }
+
+ return ret;
+ }
+
+
+ private IList ParseTableInBatchGetRowResponse(PB.TableInBatchGetRowResponse table)
+ {
+ var ret = new List();
+ int index = 0;
+
+ foreach (var row in table.RowsList)
+ {
+ DataModel.IRow result = null;
+ if (!row.IsOk)
+ {
+ ret.Add(new Response.BatchGetRowResponseItem(row.Error.Code, row.Error.Message));
+ continue;
+ }
+
+ if (row.HasRow && !row.Row.IsEmpty)
+ {
+ var inputStream = new PB.PlainBufferCodedInputStream(row.Row.CreateCodedInput());
+ List rows = inputStream.ReadRowsWithHeader();
+ if (rows.Count != 1)
+ {
+ throw new IOException("Expect only returns one row. Row count: " + rows.Count);
+ }
+
+ result = PB.PlainBufferConversion.ToRow(rows[0]);
+ }
+
+ Response.BatchGetRowResponseItem item = null;
+
+ var capacityUnit = ParseCapacityUnit(row.Consumed.CapacityUnit);
+
+ if (row.HasNextToken)
+ {
+ item = new Response.BatchGetRowResponseItem(table.TableName, result, capacityUnit, index, row.NextToken.ToByteArray());
+ }
+ else
+ {
+ item = new Response.BatchGetRowResponseItem(table.TableName, result, capacityUnit, index);
+ }
+
+ index++;
+
+ ret.Add(item);
+
+ }
+
+ return ret;
+ }
+
+ private DataModel.TableMeta ParseTableMeta(PB.TableMeta tableMeta)
+ {
+ var schema = new DataModel.PrimaryKeySchema();
+
+ for (int i = 0; i < tableMeta.PrimaryKeyCount; i++)
+ {
+ var item = tableMeta.GetPrimaryKey(i);
+
+ schema.Add(item.Name, ParseColumnValueType(item.Type));
+ }
+
+ var ret = new DataModel.TableMeta(
+ tableMeta.TableName,
+ schema
+ );
+
+ return ret;
+ }
+
+ private DataModel.ColumnValueType ParseColumnValueType(PB.PrimaryKeyType type)
+ {
+ switch (type)
+ {
+ case PB.PrimaryKeyType.BINARY:
+ return DataModel.ColumnValueType.Binary;
+
+ case PB.PrimaryKeyType.INTEGER:
+ return DataModel.ColumnValueType.Integer;
+ case PB.PrimaryKeyType.STRING:
+ return DataModel.ColumnValueType.String;
+
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid column type {0}", type)
+ );
+ }
+ }
+
+ private DataModel.ReservedThroughputDetails ParseReservedThroughputDetails(PB.ReservedThroughputDetails details)
+ {
+ var ret = new DataModel.ReservedThroughputDetails(
+ ParseCapacityUnit(details.CapacityUnit),
+ details.LastIncreaseTime,
+ details.LastDecreaseTime
+ );
+
+ return ret;
+ }
+
+ private DataModel.CapacityUnit ParseCapacityUnit(PB.CapacityUnit capacityUnit)
+ {
+ return new DataModel.CapacityUnit(capacityUnit.Read, capacityUnit.Write);
+ }
+
+ private DataModel.StreamDetails ParseStreamDetails(PB.StreamDetails streamDetails)
+ {
+ return new DataModel.StreamDetails(streamDetails.EnableStream)
+ {
+ StreamId = streamDetails.StreamId,
+ LastEnableTime = streamDetails.LastEnableTime,
+ ExpirationTime = streamDetails.ExpirationTime
+ };
+ }
+
+ private DataModel.TableOptions ParseTableOptions(PB.TableOptions tableOptions)
+ {
+ DataModel.TableOptions options = new DataModel.TableOptions()
+ {
+ TimeToLive = tableOptions.TimeToLive,
+ MaxVersions = tableOptions.MaxVersions,
+ DeviationCellVersionInSec = tableOptions.DeviationCellVersionInSec,
+ BlockSize = tableOptions.BlockSize,
+ BloomFilterType = ParseBloomFilterType(tableOptions.BloomFilterType)
+ };
+
+ return options;
+ }
+
+ private DataModel.BloomFilterType ParseBloomFilterType(PB.BloomFilterType bloomFilterType)
+ {
+ switch (bloomFilterType)
+ {
+ case PB.BloomFilterType.CELL:
+ return DataModel.BloomFilterType.CELL;
+ case PB.BloomFilterType.ROW:
+ return DataModel.BloomFilterType.ROW;
+ case PB.BloomFilterType.NONE:
+ return DataModel.BloomFilterType.NONE;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid bloomFilterType {0}", bloomFilterType)
+ );
+ }
+ }
+
+ private Response.BatchWriteRowResponseForOneTable ParseTableInBatchWriteRowResponse(PB.TableInBatchWriteRowResponse table)
+ {
+
+ var ret = new Response.BatchWriteRowResponseForOneTable
+ {
+ Responses = ParseBatchWriteRowResponseItems(table.TableName, table.RowsList)
+ };
+
+ return ret;
+ }
+
+ private IList ParseBatchWriteRowResponseItems(string tableName, IList responseItems)
+ {
+ var ret = new List();
+ int index = 0;
+ foreach (var responseItem in responseItems)
+ {
+ DataModel.IRow row = null;
+ if (responseItem.IsOk)
+ {
+ if (responseItem.HasRow && !responseItem.Row.IsEmpty)
+ {
+ try
+ {
+ var inputStream = new PB.PlainBufferCodedInputStream(responseItem.Row.CreateCodedInput());
+ List rows = inputStream.ReadRowsWithHeader();
+ if (rows.Count != 1)
+ {
+ throw new IOException("Expect only returns one row. Row count: " + rows.Count);
+ }
+
+ row = PB.PlainBufferConversion.ToRow(rows[0]);
+ }
+ catch (Exception e)
+ {
+ throw new OTSException("Failed to parse row data." + e.Message);
+ }
+ }
+
+ ret.Add(new Response.BatchWriteRowResponseItem(
+ ParseCapacityUnit(responseItem.Consumed.CapacityUnit), tableName, index++, row));
+ }
+ else
+ {
+ ret.Add(new Response.BatchWriteRowResponseItem(
+ responseItem.Error.Code, responseItem.Error.Message, tableName, index++));
+ }
+ }
+
+ return ret;
+ }
+
+ private Response.CreateGlobalIndexResponse DecodeCreateGlobalIndex(byte[] body, out IMessage _message)
+ {
+ var response = new Response.CreateGlobalIndexResponse();
+ var builder = PB.CreateIndexResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ _message = message;
+ return response;
+ }
+
+ private Response.DeleteGlobalIndexResponse DecodeDeleteGlobalIndex(byte[] body, out IMessage _message)
+ {
+ var response = new Response.DeleteGlobalIndexResponse();
+ var builder = PB.DropIndexResponse.CreateBuilder();
+ builder.MergeFrom(body);
+ var message = builder.Build();
+ _message = message;
+ return response;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferEncoder.cs b/netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferEncoder.cs
new file mode 100644
index 0000000..2419329
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/ProtocolBufferEncoder.cs
@@ -0,0 +1,1221 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+using System.Collections.Generic;
+using PB = com.alicloud.openservices.tablestore.core.protocol;
+using Google.ProtocolBuffers;
+using Aliyun.OTS.DataModel.Filter;
+using Aliyun.OTS.DataModel.ConditionalUpdate;
+using com.alicloud.openservices.tablestore.core.protocol;
+using Aliyun.OTS.ProtoBuffer;
+
+namespace Aliyun.OTS.Handler
+{
+ public class ProtocolBufferEncoder : PipelineHandler
+ {
+ private delegate IMessage RequestEncoder(Request.OTSRequest request);
+ private readonly Dictionary EncoderMap;
+ private readonly int DEFAULT_NUMBER_OF_SHARDS = 1;
+
+ public ProtocolBufferEncoder(PipelineHandler innerHandler) : base(innerHandler)
+ {
+ EncoderMap = new Dictionary {
+ { "/CreateTable", EncodeCreateTable },
+ { "/DeleteTable", EncodeDeleteTable },
+ { "/UpdateTable", EncodeUpdateTable },
+ { "/DescribeTable", EncodeDescribeTable },
+ { "/ListTable", EncodeListTable },
+
+ { "/PutRow", EncodePutRow },
+ { "/GetRow", EncodeGetRow },
+ { "/UpdateRow", EncodeUpdateRow },
+ { "/DeleteRow", EncodeDeleteRow },
+
+ { "/BatchWriteRow", EncodeBatchWriteRow },
+ { "/BatchGetRow", EncodeBatchGetRow },
+ { "/GetRange", EncodeGetRange },
+
+ { "/ListSearchIndex", EncodeListSearchIndex },
+ { "/CreateSearchIndex", EncodeCreateSearchIndex },
+ { "/DescribeSearchIndex", EncodeDescribeSearchIndex },
+ { "/DeleteSearchIndex", EncodeDeleteSearchIndex },
+ { "/Search", EncodeSearch },
+
+ { "/CreateIndex", EncodeCreateGlobalIndex },
+ { "/DropIndex", EncodeDeleteGlobalIndex },
+ };
+ }
+
+ public override void HandleBefore(Context context)
+ {
+ var encoder = EncoderMap[context.APIName];
+ var message = encoder(context.OTSRequest);
+ LogEncodedMessage(context, message);
+ context.HttpRequestBody = message.ToByteArray();
+ InnerHandler.HandleBefore(context);
+ }
+
+ public override void HandleAfter(Context context)
+ {
+ InnerHandler.HandleAfter(context);
+ }
+
+ #region Encode Request
+ private IMessage EncodeCreateTable(Request.OTSRequest request)
+ {
+ var requestReal = (Request.CreateTableRequest)request;
+ var builder = PB.CreateTableRequest.CreateBuilder();
+ builder.SetTableMeta(EncodeTableMeta(requestReal.TableMeta));
+ builder.SetReservedThroughput(EncodeReservedThroughput(requestReal.ReservedThroughput));
+
+ builder.SetTableOptions(EncodeTableOptions(requestReal.TableOptions));
+
+ if (requestReal.StreamSpecification != null)
+ {
+ builder.SetStreamSpec(EncodeStreamSpecification(requestReal.StreamSpecification));
+ }
+
+ if (requestReal.PartitionRange != null)
+ {
+ for (var i = 0; i < requestReal.PartitionRange.Count; i++)
+ {
+ builder.SetPartitions(i, EncodePartitionRange(requestReal.PartitionRange[i]));
+ }
+ }
+
+ if (requestReal.IndexMetas != null)
+ {
+ for (int i = 0; i < requestReal.IndexMetas.Count; i++)
+ {
+ builder.AddIndexMetas(EncodeIndexMeta(requestReal.IndexMetas[i]));
+ }
+ }
+
+ var message = builder.Build();
+ return message;
+ }
+
+ private IMessage EncodeDeleteTable(Request.OTSRequest request)
+ {
+ var requestReal = (Request.DeleteTableRequest)request;
+ var builder = PB.DeleteTableRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+ return builder.Build();
+ }
+
+ private IMessage EncodeUpdateTable(Request.OTSRequest request)
+ {
+ var requestReal = (Request.UpdateTableRequest)request;
+ var builder = PB.UpdateTableRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+
+ if (requestReal.ReservedThroughput != null)
+ {
+ builder.SetReservedThroughput(EncodeReservedThroughput(requestReal.ReservedThroughput));
+ }
+
+ if (requestReal.TableOptions != null)
+ {
+ builder.SetTableOptions(EncodeTableOptions(requestReal.TableOptions));
+ }
+
+ if (requestReal.StreamSpecification != null)
+ {
+ builder.SetStreamSpec(EncodeStreamSpecification(requestReal.StreamSpecification));
+ }
+
+ return builder.Build();
+ }
+
+ private IMessage EncodeDescribeTable(Request.OTSRequest request)
+ {
+ var requestReal = (Request.DescribeTableRequest)request;
+ var builder = PB.DescribeTableRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+ return builder.Build();
+ }
+
+ private IMessage EncodeListTable(Request.OTSRequest request)
+ {
+ var builder = PB.ListTableRequest.CreateBuilder();
+ return builder.Build();
+ }
+
+ private IMessage EncodePutRow(Request.OTSRequest request)
+ {
+ var requestReal = (Request.PutRowRequest)request;
+ var builder = PB.PutRowRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+ builder.SetCondition(EncodeCondition(requestReal.Condition));
+ builder.SetRow(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildRowPutChangeWithHeader(requestReal.RowPutChange)));
+ builder.SetReturnContent(EncodeReturnContent(requestReal.RowPutChange.ReturnType, requestReal.RowPutChange.ReturnColumnNames));
+ return builder.Build();
+ }
+
+ private IMessage EncodeGetRow(Request.OTSRequest request)
+ {
+ var requestReal = (Request.GetRowRequest)request;
+ var queryCriteria = requestReal.QueryCriteria;
+
+ var builder = PB.GetRowRequest.CreateBuilder();
+ builder.SetTableName(queryCriteria.TableName);
+ builder.SetPrimaryKey(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildPrimaryKeyWithHeader(queryCriteria.RowPrimaryKey)));
+
+ builder.AddRangeColumnsToGet(queryCriteria.GetColumnsToGet());
+
+ // if timeRange and maxVersions are both not set, set maxVersions to 1 default
+ if (!CheckQueryCondition(queryCriteria.TableName, queryCriteria.MaxVersions, queryCriteria.TimeRange))
+ {
+ queryCriteria.MaxVersions = 1;
+ }
+
+ if (queryCriteria.TimeRange != null)
+ {
+ builder.SetTimeRange(EncodeTimeRange(queryCriteria.TimeRange));
+ }
+
+ if (queryCriteria.MaxVersions.HasValue)
+ {
+ builder.SetMaxVersions(queryCriteria.MaxVersions.Value);
+ }
+
+ if (queryCriteria.CacheBlocks != null && queryCriteria.CacheBlocks.HasValue)
+ {
+ builder.SetCacheBlocks(queryCriteria.CacheBlocks.Value);
+ }
+
+ if (queryCriteria.Filter != null)
+ {
+ builder.SetFilter(BuildFilter(queryCriteria.Filter));
+ }
+
+ if (queryCriteria.StartColumn != null)
+ {
+ builder.SetStartColumn(queryCriteria.StartColumn);
+ }
+
+ if (queryCriteria.EndColumn != null)
+ {
+ builder.SetEndColumn(queryCriteria.EndColumn);
+ }
+
+ if (queryCriteria.Token != null)
+ {
+ builder.SetToken(ByteString.CopyFrom(queryCriteria.Token));
+ }
+
+
+ return builder.Build();
+ }
+
+ private IMessage EncodeUpdateRow(Request.OTSRequest request)
+ {
+ var requestReal = (Request.UpdateRowRequest)request;
+ var builder = PB.UpdateRowRequest.CreateBuilder();
+
+ var rowChange = requestReal.RowUpdateChange;
+
+ // required string table_name = 1;
+ builder.SetTableName(rowChange.TableName);
+ // required bytes row_change = 2;
+ builder.SetRowChange(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildRowUpdateChangeWithHeader(rowChange)));
+ // required Condition condition = 3;
+ builder.SetCondition(EncodeCondition(rowChange.Condition));
+ // option ReturnType = 4;
+ builder.SetReturnContent(EncodeReturnContent(rowChange.ReturnType, rowChange.ReturnColumnNames));
+
+ return builder.Build();
+ }
+
+ private IMessage EncodeDeleteRow(Request.OTSRequest request)
+ {
+ var requestReal = (Request.DeleteRowRequest)request;
+ var rowChange = requestReal.RowDeleteChange;
+ var builder = PB.DeleteRowRequest.CreateBuilder();
+
+ // required string table_name = 1;
+ builder.SetTableName(rowChange.TableName);
+ // required bytes primary_key = 2;
+ builder.SetPrimaryKey(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildRowDeleteChangeWithHeader(rowChange)));
+ // required Condition condition = 3;
+ builder.SetCondition(EncodeCondition(rowChange.Condition));
+ // option ReturnType = 4;
+ builder.SetReturnContent(EncodeReturnContent(rowChange.ReturnType, rowChange.ReturnColumnNames));
+ return builder.Build();
+ }
+
+ private IMessage EncodeBatchWriteRow(Request.OTSRequest request)
+ {
+ var requestReal = (Request.BatchWriteRowRequest)request;
+ var builder = PB.BatchWriteRowRequest.CreateBuilder();
+
+ foreach (var item in requestReal.RowChangesGroupByTable)
+ {
+ builder.AddTables(EncodeTableInBatchWriteRowRequest(item.Key, item.Value));
+ }
+
+ return builder.Build();
+ }
+
+ private IMessage EncodeBatchGetRow(Request.OTSRequest request)
+ {
+ var requestReal = (Request.BatchGetRowRequest)request;
+ var builder = PB.BatchGetRowRequest.CreateBuilder();
+
+ foreach (var criterias in requestReal.GetCriterias())
+ {
+ builder.AddTables(EncodeTableInBatchGetRowRequest(criterias));
+ }
+
+ return builder.Build();
+ }
+
+ private IMessage EncodeGetRange(Request.OTSRequest request)
+ {
+ var requestReal = (Request.GetRangeRequest)request;
+ var builder = PB.GetRangeRequest.CreateBuilder();
+
+ var queryCriteria = requestReal.QueryCriteria;
+
+ // required string table_name = 1;
+ builder.SetTableName(queryCriteria.TableName);
+
+ // required Direction direction = 2;
+ builder.SetDirection(ToPBDirection(queryCriteria.Direction));
+
+ // repeated string columns_to_get = 3;
+ if (queryCriteria.GetColumnsToGet() != null)
+ {
+ builder.AddRangeColumnsToGet(queryCriteria.GetColumnsToGet());
+ }
+
+ // if timeRange and maxVersions are both not set, set maxVersions to 1 default
+ if (!CheckQueryCondition(queryCriteria.TableName, queryCriteria.MaxVersions, queryCriteria.TimeRange))
+ {
+ queryCriteria.MaxVersions = 1;
+ }
+
+ // optional TimeRange time_range = 4;
+ if (queryCriteria.TimeRange != null)
+ {
+ builder.SetTimeRange(EncodeTimeRange(queryCriteria.TimeRange));
+ }
+
+ // optional int32 max_versions = 5;
+ if (queryCriteria.MaxVersions.HasValue)
+ {
+ builder.SetMaxVersions(queryCriteria.MaxVersions.Value);
+ }
+
+ // optional int32 limit = 6;
+ if (queryCriteria.Limit != null && queryCriteria.Limit > 0)
+ {
+ builder.SetLimit((int)queryCriteria.Limit);
+ }
+
+ // required bytes inclusive_start_primary_key = 7;
+ builder.SetInclusiveStartPrimaryKey(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildPrimaryKeyWithHeader(queryCriteria.InclusiveStartPrimaryKey)));
+ // required bytes exclusive_end_primary_key = 8;
+ builder.SetExclusiveEndPrimaryKey(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildPrimaryKeyWithHeader(queryCriteria.ExclusiveEndPrimaryKey)));
+
+ // optional bool cache_blocks = 9 [default = true];
+ if (queryCriteria.CacheBlocks.HasValue)
+ {
+ builder.SetCacheBlocks(queryCriteria.CacheBlocks.Value);
+ }
+
+ // optional bytes filter = 10;
+ if (queryCriteria.Filter != null)
+ {
+ builder.SetFilter(BuildFilter(queryCriteria.Filter));
+ }
+
+ // optional string start_column = 11;
+ if (queryCriteria.StartColumn != null)
+ {
+ builder.SetStartColumn(queryCriteria.StartColumn);
+ }
+
+ // optional string end_column = 12;
+ if (queryCriteria.EndColumn != null)
+ {
+ builder.SetEndColumn(queryCriteria.EndColumn);
+ }
+
+ // optional bytes token = 13;
+ if (queryCriteria.HasSetToken())
+ {
+ builder.SetToken(ByteString.CopyFrom(queryCriteria.Token));
+ }
+
+ return builder.Build();
+ }
+
+
+ private IMessage EncodeListSearchIndex(Request.OTSRequest request)
+ {
+ var requestReal = (Request.ListSearchIndexRequest)request;
+ var builder = PB.ListSearchIndexRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+ return builder.Build();
+ }
+
+ private IMessage EncodeCreateSearchIndex(Request.OTSRequest request)
+ {
+ var requestReal = (Request.CreateSearchIndexRequest)request;
+ var builder = PB.CreateSearchIndexRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+ builder.SetIndexName(requestReal.IndexName);
+ builder.SetSchema(EncodeIndexSchema(requestReal.IndexSchame));
+ return builder.Build();
+ }
+
+ private IMessage EncodeSearch(Request.OTSRequest request)
+ {
+ var requestReal = (Request.SearchRequest)request;
+ var builder = PB.SearchRequest.CreateBuilder();
+
+ builder.SetTableName(requestReal.TableName);
+ builder.SetIndexName(requestReal.IndexName);
+ builder.SetSearchQuery(EncodeSearchQuery(requestReal.SearchQuery).ToByteString());
+ if (requestReal.ColumnsToGet != null)
+ {
+ builder.SetColumnsToGet(EncodeColumsToGet(requestReal.ColumnsToGet));
+ }
+ if (requestReal.RoutingValues != null)
+ {
+ List routingValues = new List();
+ foreach (var pk in requestReal.RoutingValues)
+ {
+ try
+ {
+ routingValues.Add(ByteString.CopyFrom(PlainBufferBuilder.BuildPrimaryKeyWithHeader(pk)));
+ }
+ catch (Exception e)
+ {
+ throw new OTSClientException("build plain buffer fail,msg:" + e.Message);
+ }
+ }
+ builder.AddRangeRoutingValues(routingValues);
+ }
+
+ return builder.Build();
+ }
+
+ private PB.ColumnsToGet EncodeColumsToGet(DataModel.Search.ColumnsToGet columnsToGet)
+ {
+ var builder = PB.ColumnsToGet.CreateBuilder();
+ if (columnsToGet.ReturnAll)
+ {
+ builder.SetReturnType(ColumnReturnType.RETURN_ALL);
+ }
+ else if (columnsToGet.Columns.Count > 0)
+ {
+ builder.SetReturnType(ColumnReturnType.RETURN_SPECIFIED);
+ builder.AddRangeColumnNames(columnsToGet.Columns);
+ }
+ else
+ {
+ builder.SetReturnType(ColumnReturnType.RETURN_NONE);
+ }
+ return builder.Build();
+ }
+
+ private PB.SearchQuery EncodeSearchQuery(DataModel.Search.SearchQuery searchQuery)
+ {
+ var builder = PB.SearchQuery.CreateBuilder();
+ if (searchQuery.Limit.HasValue)
+ {
+ builder.SetLimit(searchQuery.Limit.Value);
+ }
+ if (searchQuery.Offset.HasValue)
+ {
+ builder.SetOffset(searchQuery.Offset.Value);
+ }
+
+ if (searchQuery.Collapse != null)
+ {
+ builder.SetCollapse(EncodeCollapse(searchQuery.Collapse));
+ }
+
+ if (searchQuery.Query != null)
+ {
+ builder.SetQuery(SearchQueryBuilder.BuildQuery(searchQuery.Query));
+ }
+
+ if (searchQuery.Sort != null)
+ {
+ builder.SetSort(SearchSortBuilder.BuildSort(searchQuery.Sort));
+ }
+
+ builder.SetGetTotalCount(searchQuery.GetTotalCount);
+ if (searchQuery.Token != null)
+ {
+ builder.SetToken(ByteString.CopyFrom(searchQuery.Token));
+ }
+
+ return builder.Build();
+ }
+
+ private PB.Collapse EncodeCollapse(DataModel.Search.Collapse collapse)
+ {
+ var builder = PB.Collapse.CreateBuilder();
+ if (collapse.FieldName != null)
+ {
+ builder.SetFieldName(collapse.FieldName);
+ }
+ return builder.Build();
+ }
+
+ private PB.IndexSchema EncodeIndexSchema(DataModel.Search.IndexSchema schema)
+ {
+ var builder = PB.IndexSchema.CreateBuilder();
+
+ if (schema.IndexSetting != null)
+ {
+ builder.SetIndexSetting(EncodeIndexSetting(schema.IndexSetting));
+ }
+ else
+ {
+ builder.SetIndexSetting(EncodeIndexSetting(new DataModel.Search.IndexSetting()));
+ }
+ if (schema.FieldSchemas != null)
+ {
+ for (var i = 0; i < schema.FieldSchemas.Count; i++)
+ {
+ builder.FieldSchemasList.Add(EncodingFieldSchema(schema.FieldSchemas[i]));
+ }
+ }
+ if (schema.IndexSort != null)
+ {
+ builder.SetIndexSort(SearchSortBuilder.BuildSort(schema.IndexSort));
+ }
+ return builder.Build();
+ }
+
+ private PB.FieldSchema EncodingFieldSchema(DataModel.Search.FieldSchema fieldSchema)
+ {
+ var builder = PB.FieldSchema.CreateBuilder();
+ builder.SetFieldName(fieldSchema.FieldName);
+ builder.SetFieldType(EncodingFieldType(fieldSchema.FieldType));
+ if (fieldSchema.FieldType != DataModel.Search.FieldType.NESTED)
+ {
+ builder.Index = fieldSchema.index;
+ builder.DocValues = fieldSchema.EnableSortAndAgg;
+ builder.Store = fieldSchema.Store;
+ builder.IsArray = fieldSchema.IsArray;
+ }
+
+ if (fieldSchema.IndexOptions != DataModel.Search.IndexOptions.NULL)
+ {
+ builder.IndexOptions = EncodingIndexOptions(fieldSchema.IndexOptions);
+ }
+ if (fieldSchema.Analyzer != DataModel.Search.Analyzer.NotAnalyzed)
+ {
+ builder.Analyzer = EncodingAnalyzer(fieldSchema.Analyzer);
+ }
+
+ if (fieldSchema.SubFieldSchemas != null)
+ {
+ for (var i = 0; i < fieldSchema.SubFieldSchemas.Count; i++)
+ {
+ builder.AddFieldSchemas(EncodingFieldSchema(fieldSchema.SubFieldSchemas[i]));
+ }
+ }
+
+ return builder.Build();
+ }
+
+ private string EncodingAnalyzer(DataModel.Search.Analyzer analyzer)
+ {
+ switch (analyzer)
+ {
+ case DataModel.Search.Analyzer.MaxWord:
+ return "max_word";
+ case DataModel.Search.Analyzer.SingleWord:
+ return "single_word";
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid Analyzer {0}", analyzer)
+ );
+ }
+ }
+
+ private PB.IndexOptions EncodingIndexOptions(DataModel.Search.IndexOptions indexOptions)
+ {
+ switch (indexOptions)
+ {
+ case DataModel.Search.IndexOptions.DOCS:
+ return PB.IndexOptions.DOCS;
+ case DataModel.Search.IndexOptions.FREQS:
+ return PB.IndexOptions.FREQS;
+ case DataModel.Search.IndexOptions.OFFSETS:
+ return PB.IndexOptions.OFFSETS;
+ case DataModel.Search.IndexOptions.POSITIONS:
+ return PB.IndexOptions.POSITIONS;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid IndexOptions {0}", indexOptions)
+ );
+ }
+ }
+
+ private PB.FieldType EncodingFieldType(DataModel.Search.FieldType fieldType)
+ {
+ switch (fieldType)
+ {
+ case DataModel.Search.FieldType.BOOLEAN:
+ return PB.FieldType.BOOLEAN;
+ case DataModel.Search.FieldType.DOUBLE:
+ return PB.FieldType.DOUBLE;
+ case DataModel.Search.FieldType.GEO_POINT:
+ return PB.FieldType.GEO_POINT;
+ case DataModel.Search.FieldType.KEYWORD:
+ return PB.FieldType.KEYWORD;
+ case DataModel.Search.FieldType.LONG:
+ return PB.FieldType.LONG;
+ case DataModel.Search.FieldType.NESTED:
+ return PB.FieldType.NESTED;
+ case DataModel.Search.FieldType.TEXT:
+ return PB.FieldType.TEXT;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid FieldType {0}", fieldType)
+ );
+ }
+ }
+
+ private PB.IndexSetting EncodeIndexSetting(DataModel.Search.IndexSetting indexSetting)
+ {
+ var builder = PB.IndexSetting.CreateBuilder();
+ if (indexSetting != null)
+ {
+ if (indexSetting.RoutingFields != null)
+ {
+ for (var i = 0; i < indexSetting.RoutingFields.Count; i++)
+ {
+ builder.SetRoutingFields(i, indexSetting.RoutingFields[i]);
+ }
+ }
+ builder.SetNumberOfShards(DEFAULT_NUMBER_OF_SHARDS);
+ }
+ return builder.Build();
+ }
+
+
+ private IMessage EncodeDescribeSearchIndex(Request.OTSRequest request)
+ {
+ var requestReal = (Request.DescribeSearchIndexRequest)request;
+ var builder = PB.DescribeSearchIndexRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+ builder.SetIndexName(requestReal.IndexName);
+ return builder.Build();
+ }
+
+ private IMessage EncodeDeleteSearchIndex(Request.OTSRequest request)
+ {
+ var requestReal = (Request.DeleteSearchIndexRequest)request;
+ var builder = PB.DeleteSearchIndexRequest.CreateBuilder();
+ builder.SetTableName(requestReal.TableName);
+ builder.SetIndexName(requestReal.IndexName);
+ return builder.Build();
+ }
+
+ private IMessage EncodeCreateGlobalIndex(Request.OTSRequest request)
+ {
+ var requestReal = (Request.CreateGlobalIndexRequest)request;
+ var builder = PB.CreateIndexRequest.CreateBuilder();
+ builder.SetMainTableName(requestReal.MainTableName);
+ builder.SetIncludeBaseData(requestReal.IncludeBaseData);
+ builder.SetIndexMeta(EncodeIndexMeta(requestReal.IndexMeta));
+
+ return builder.Build();
+ }
+
+ public IMessage EncodeDeleteGlobalIndex(Request.OTSRequest request)
+ {
+ var requestReal = (Request.DeleteGlobalIndexRequest)request;
+ var builder = PB.DropIndexRequest.CreateBuilder();
+ builder.SetMainTableName(requestReal.MainTableName);
+ builder.SetIndexName(requestReal.IndexName);
+
+ return builder.Build();
+ }
+
+ #endregion
+
+ #region Encode Others
+ private PB.TableOptions EncodeTableOptions(DataModel.TableOptions tableOptions)
+ {
+ var builder = PB.TableOptions.CreateBuilder();
+
+ if (tableOptions.TimeToLive.HasValue)
+ {
+ builder.SetTimeToLive(tableOptions.TimeToLive.Value);
+ }
+ else
+ {
+ Console.WriteLine("Time to live is set to -1 in default.");
+ builder.SetTimeToLive(-1);
+ }
+
+ if (tableOptions.MaxVersions.HasValue)
+ {
+ builder.SetMaxVersions(tableOptions.MaxVersions.Value);
+ }
+ else
+ {
+ Console.WriteLine("Max Versions is set to 1 in default.");
+ builder.SetMaxVersions(1);
+ }
+
+ if (tableOptions.DeviationCellVersionInSec.HasValue)
+ {
+ builder.SetDeviationCellVersionInSec(tableOptions.DeviationCellVersionInSec.Value);
+ }
+
+ if (tableOptions.BlockSize.HasValue)
+ {
+ builder.SetBlockSize(tableOptions.BlockSize.Value);
+ }
+
+ if (tableOptions.BloomFilterType.HasValue)
+ {
+ builder.SetBloomFilterType(EncodeBloomFilterType(tableOptions.BloomFilterType.Value));
+ }
+
+
+ return builder.Build();
+ }
+
+ private PB.BloomFilterType EncodeBloomFilterType(DataModel.BloomFilterType bloomFilterType)
+ {
+
+ switch (bloomFilterType)
+ {
+ case DataModel.BloomFilterType.CELL:
+ return PB.BloomFilterType.CELL;
+ case DataModel.BloomFilterType.NONE:
+ return PB.BloomFilterType.NONE;
+ case DataModel.BloomFilterType.ROW:
+ return PB.BloomFilterType.ROW;
+ default:
+ throw new OTSClientException(
+ String.Format("Invalid bloomFilterType {0}", bloomFilterType)
+ );
+ }
+ }
+
+ private PB.StreamSpecification EncodeStreamSpecification(DataModel.StreamSpecification streamSpecification)
+ {
+ var builder = new PB.StreamSpecification.Builder();
+ builder.SetEnableStream(streamSpecification.EnableStream);
+ builder.SetExpirationTime(streamSpecification.ExpirationTime);
+ return builder.Build();
+ }
+
+ private PB.PartitionRange EncodePartitionRange(DataModel.PartitionRange partitionRange)
+ {
+ var builder = PB.PartitionRange.CreateBuilder();
+ builder.SetBegin(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildPrimaryKeyValueWithoutLengthPrefix(partitionRange.Begin)));
+ builder.SetEnd(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildPrimaryKeyValueWithoutLengthPrefix(partitionRange.End)));
+ return builder.Build();
+ }
+
+ private PB.IndexMeta EncodeIndexMeta(DataModel.IndexMeta indexMeta)
+ {
+ var builder = PB.IndexMeta.CreateBuilder();
+ builder.Name = indexMeta.IndexName;
+ builder.IndexType = EncodeIndexType(indexMeta.IndexType);
+ builder.IndexUpdateMode = EncodeIndexUpdateMode(indexMeta.IndexUpdateModel);
+ if (indexMeta.PrimaryKey != null)
+ {
+ for (int i = 0; i < indexMeta.PrimaryKey.Count; i++)
+ {
+ builder.AddPrimaryKey(indexMeta.PrimaryKey[i]);
+ }
+ }
+
+ if (indexMeta.DefinedColumns != null)
+ {
+ for (int i = 0; i < indexMeta.DefinedColumns.Count; i++)
+ {
+ builder.AddDefinedColumn(indexMeta.DefinedColumns[i]);
+ }
+ }
+
+ return builder.Build();
+ }
+
+ private PB.IndexType EncodeIndexType(DataModel.IndexType indexType)
+ {
+ switch (indexType)
+ {
+ case DataModel.IndexType.IT_GLOBAL_INDEX:
+ return PB.IndexType.IT_GLOBAL_INDEX;
+ default:
+ throw new OTSClientException(String.Format(
+ "Invalid indexType {0}", indexType
+ ));
+ }
+ }
+
+ private PB.IndexUpdateMode EncodeIndexUpdateMode(DataModel.IndexUpdateMode indexUpdateModel)
+ {
+ switch (indexUpdateModel)
+ {
+ case DataModel.IndexUpdateMode.IUM_ASYNC_INDEX:
+ return PB.IndexUpdateMode.IUM_ASYNC_INDEX;
+ default:
+ throw new OTSClientException(String.Format(
+ "Invalid indexUpdateModel {0}", indexUpdateModel
+ ));
+ }
+ }
+
+ private PB.TableMeta EncodeTableMeta(DataModel.TableMeta tableMeta)
+ {
+ var builder = PB.TableMeta.CreateBuilder();
+ builder.SetTableName(tableMeta.TableName);
+ builder.AddRangePrimaryKey(EncodePrimaryKeySchema(tableMeta.PrimaryKeySchema));
+ if (tableMeta.DefinedColumnSchema != null)
+ {
+ builder.AddRangeDefinedColumn(EncodeDefinedColumnSchema(tableMeta.DefinedColumnSchema));
+ }
+ return builder.Build();
+ }
+
+ private IEnumerable EncodeDefinedColumnSchema(DataModel.DefinedColumnSchema schema)
+ {
+ foreach (var item in schema)
+ {
+ yield return EncodeDefinedColumnSchemaItem(item);
+ }
+ }
+
+ private PB.DefinedColumnSchema EncodeDefinedColumnSchemaItem(Tuple schema)
+ {
+ var builder = PB.DefinedColumnSchema.CreateBuilder();
+ builder.SetName(schema.Item1);
+ builder.SetType(EncodeDeinedColumnType(schema.Item2));
+
+ return builder.Build();
+ }
+
+ private PB.DefinedColumnType EncodeDeinedColumnType(DataModel.DefinedColumnType type)
+ {
+ switch (type)
+ {
+ case DataModel.DefinedColumnType.BINARY:
+ return DefinedColumnType.DCT_BLOB;
+ case DataModel.DefinedColumnType.INTEGER:
+ return DefinedColumnType.DCT_INTEGER;
+ case DataModel.DefinedColumnType.STRING:
+ return DefinedColumnType.DCT_STRING;
+ case DataModel.DefinedColumnType.DOUBLE:
+ return DefinedColumnType.DCT_STRING;
+ case DataModel.DefinedColumnType.BOOLEAN:
+ return DefinedColumnType.DCT_BOOLEAN;
+
+ default:
+ throw new OTSClientException(String.Format(
+ "Invalid definedColumn value type: {0}", type
+ ));
+ }
+ }
+
+ private IEnumerable EncodePrimaryKeySchema(DataModel.PrimaryKeySchema schema)
+ {
+ foreach (var item in schema)
+ {
+ yield return EncodeColumnSchema(item);
+ }
+ }
+
+ private PB.PrimaryKeySchema EncodeColumnSchema(Tuple schema)
+ {
+ var builder = PB.PrimaryKeySchema.CreateBuilder();
+ builder.SetName(schema.Item1);
+ builder.SetType(EncodeColumnType(schema.Item2));
+
+ if (schema.Item3 != DataModel.PrimaryKeyOption.NONE)
+ {
+ builder.SetOption(EncodePrimaryKeyOption(schema.Item3));
+ }
+
+ return builder.Build();
+ }
+
+ private PB.PrimaryKeyType EncodeColumnType(DataModel.ColumnValueType type)
+ {
+ switch (type)
+ {
+ case DataModel.ColumnValueType.Integer:
+ return PB.PrimaryKeyType.INTEGER;
+ case DataModel.ColumnValueType.String:
+ return PB.PrimaryKeyType.STRING;
+ case DataModel.ColumnValueType.Binary:
+ return PB.PrimaryKeyType.BINARY;
+ default:
+ throw new OTSClientException(String.Format(
+ "Invalid column value type: {0}", type
+ ));
+ }
+ }
+
+ private PB.PrimaryKeyOption EncodePrimaryKeyOption(DataModel.PrimaryKeyOption option)
+ {
+ switch (option)
+ {
+ case DataModel.PrimaryKeyOption.AUTO_INCREMENT:
+ return PB.PrimaryKeyOption.AUTO_INCREMENT;
+ default:
+ throw new OTSClientException(String.Format(
+ "Invalid primary key option: {0}", option
+ ));
+ }
+ }
+
+ private PB.ReservedThroughput EncodeReservedThroughput(DataModel.CapacityUnit capacityUnit)
+ {
+ var builder = PB.ReservedThroughput.CreateBuilder();
+ builder.SetCapacityUnit(EncodeCapacityUnit(capacityUnit));
+ return builder.Build();
+ }
+
+ private PB.CapacityUnit EncodeCapacityUnit(DataModel.CapacityUnit capacityUnit)
+ {
+ var builder = PB.CapacityUnit.CreateBuilder();
+
+ if (capacityUnit.Read.HasValue)
+ {
+ builder.SetRead(capacityUnit.Read.Value);
+ }
+
+ if (capacityUnit.Write.HasValue)
+ {
+ builder.SetWrite(capacityUnit.Write.Value);
+ }
+
+ return builder.Build();
+ }
+
+ private PB.Condition EncodeCondition(DataModel.Condition condition)
+ {
+ PB.Condition.Builder builder = PB.Condition.CreateBuilder();
+ switch (condition.RowExistenceExpect)
+ {
+ case DataModel.RowExistenceExpectation.EXPECT_EXIST:
+ builder.SetRowExistence(PB.RowExistenceExpectation.EXPECT_EXIST);
+ break;
+ case DataModel.RowExistenceExpectation.EXPECT_NOT_EXIST:
+ builder.SetRowExistence(PB.RowExistenceExpectation.EXPECT_NOT_EXIST);
+ break;
+ case DataModel.RowExistenceExpectation.IGNORE:
+ builder.SetRowExistence(PB.RowExistenceExpectation.IGNORE);
+ break;
+ default:
+ throw new OTSClientException(String.Format("Invalid RowExistenceExpectation: {0}", condition.RowExistenceExpect));
+ }
+
+ if (condition.ColumnCondition != null)
+ {
+ builder.SetColumnCondition(BuildFilter(condition.ColumnCondition));
+ }
+
+ return builder.Build();
+ }
+
+ private static ByteString BuildFilter(IColumnCondition filter)
+ {
+ PB.Filter.Builder builder = PB.Filter.CreateBuilder();
+
+ builder.SetType(EncodeFilterType(filter.GetConditionType()));
+ builder.SetFilter_(filter.Serialize());
+ return builder.Build().ToByteString();
+ }
+
+ private static ByteString BuildFilter(IFilter filter)
+ {
+ PB.Filter.Builder builder = PB.Filter.CreateBuilder();
+
+ builder.SetType(ToPBFilterType(filter.GetFilterType()));
+ builder.SetFilter_(filter.Serialize());
+ return builder.Build().ToByteString();
+ }
+
+ private static PB.FilterType EncodeFilterType(ColumnConditionType type)
+ {
+ switch (type)
+ {
+ case ColumnConditionType.COMPOSITE_CONDITION:
+ return PB.FilterType.FT_COMPOSITE_COLUMN_VALUE;
+ case ColumnConditionType.RELATIONAL_CONDITION:
+ return PB.FilterType.FT_SINGLE_COLUMN_VALUE;
+ default:
+ throw new ArgumentException("Unknown filter type: " + type);
+ }
+ }
+
+ private static PB.ReturnContent EncodeReturnContent(DataModel.ReturnType returnType, List returnColumnNames)
+ {
+ PB.ReturnContent.Builder builder = PB.ReturnContent.CreateBuilder();
+ builder.SetReturnType(ToPBReturnType(returnType));
+
+ if (returnColumnNames != null)
+ {
+ foreach (var item in returnColumnNames)
+ {
+ builder.AddReturnColumnNames(item);
+ }
+ }
+
+ return builder.Build();
+ }
+
+ private static PB.TimeRange EncodeTimeRange(DataModel.TimeRange timeRange)
+ {
+ PB.TimeRange.Builder builder = PB.TimeRange.CreateBuilder();
+ if (timeRange.SpecificTime.HasValue)
+ {
+ builder.SetSpecificTime(timeRange.SpecificTime.Value);
+ }
+ else
+ {
+ builder.SetStartTime(timeRange.StartTime.Value);
+ builder.SetEndTime(timeRange.EndTime.Value);
+ }
+
+ return builder.Build();
+ }
+
+ private PB.TableInBatchWriteRowRequest EncodeTableInBatchWriteRowRequest(string tableName, DataModel.RowChanges rowChanges)
+ {
+ var tableBuilder = PB.TableInBatchWriteRowRequest.CreateBuilder();
+
+ tableBuilder.SetTableName(tableName);
+
+ if (rowChanges == null || rowChanges.IsEmpty())
+ {
+ return tableBuilder.Build();
+ }
+
+ foreach (var rowChange in rowChanges.RowPutChanges)
+ {
+ tableBuilder.AddRows(EncodeWriteRowRequest(rowChange));
+ }
+
+ foreach (var rowChange in rowChanges.RowUpdateChanges)
+ {
+ tableBuilder.AddRows(EncodeWriteRowRequest(rowChange));
+ }
+
+ foreach (var rowChange in rowChanges.RowDeleteChanges)
+ {
+ tableBuilder.AddRows(EncodeWriteRowRequest(rowChange));
+ }
+
+ return tableBuilder.Build();
+ }
+
+ private PB.RowInBatchWriteRowRequest EncodeWriteRowRequest(DataModel.RowChange rowChange)
+ {
+ var rowBuilder = PB.RowInBatchWriteRowRequest.CreateBuilder();
+
+ if (rowChange is DataModel.RowPutChange)
+ {
+ rowBuilder.SetType(PB.OperationType.PUT);
+ rowBuilder.SetRowChange(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildRowPutChangeWithHeader(rowChange as DataModel.RowPutChange)));
+ }
+ else if (rowChange is DataModel.RowUpdateChange)
+ {
+ rowBuilder.SetType(PB.OperationType.UPDATE);
+ rowBuilder.SetRowChange(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildRowUpdateChangeWithHeader(rowChange as DataModel.RowUpdateChange)));
+ }
+ else if (rowChange is DataModel.RowDeleteChange)
+ {
+ rowBuilder.SetType(PB.OperationType.DELETE);
+ rowBuilder.SetRowChange(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildRowDeleteChangeWithHeader(rowChange as DataModel.RowDeleteChange)));
+ }
+ else
+ {
+ throw new OTSException("unkown row change " + rowChange.GetType());
+ }
+
+ rowBuilder.SetCondition(EncodeCondition(rowChange.Condition));
+ rowBuilder.SetReturnContent(EncodeReturnContent(rowChange.ReturnType, rowChange.ReturnColumnNames));
+ return rowBuilder.Build();
+ }
+
+ private PB.TableInBatchGetRowRequest EncodeTableInBatchGetRowRequest(DataModel.MultiRowQueryCriteria criteria)
+ {
+ var tableBuilder = PB.TableInBatchGetRowRequest.CreateBuilder();
+ tableBuilder.SetTableName(criteria.TableName);
+
+
+ if (criteria.GetRowKeys().Count != criteria.GetTokens().Count)
+ {
+ throw new OTSException("The number of primaryKeys and tokens must be the same. Table name:" + criteria.TableName);
+ }
+
+ // if timeRange and maxVersions are both not set, set maxVersions to 1 default
+ if (!CheckQueryCondition(criteria.TableName, criteria.MaxVersions, criteria.TimeRange))
+ {
+ criteria.MaxVersions = 1;
+ }
+
+ // repeated bytes primary_key = 2;
+ // repeated bytes tokens = 3;
+ for (int i = 0; i < criteria.Size(); i++)
+ {
+ tableBuilder.AddPrimaryKey(ByteString.CopyFrom(PB.PlainBufferBuilder.BuildPrimaryKeyWithHeader(criteria.Get(i))));
+ tableBuilder.AddToken(ByteString.CopyFrom(criteria.GetTokens()[i]));
+ }
+
+ // repeated string columns_to_get = 4;
+ if (criteria.GetColumnsToGet() != null)
+ {
+ tableBuilder.AddRangeColumnsToGet(criteria.GetColumnsToGet());
+ }
+
+ // optional TimeRange time_range = 5;
+ if (criteria.TimeRange != null)
+ {
+ tableBuilder.SetTimeRange(EncodeTimeRange(criteria.TimeRange));
+ }
+
+ // optional int32 max_versions = 6;
+ if (criteria.MaxVersions.HasValue)
+ {
+ tableBuilder.SetMaxVersions(criteria.MaxVersions.Value);
+ }
+
+ // optional bool cache_blocks = 7;
+ if (criteria.CacheBlocks.HasValue)
+ {
+ tableBuilder.SetCacheBlocks(criteria.CacheBlocks.Value);
+ }
+
+ // optional bytes filter = 8;
+ if (criteria.Filter != null)
+ {
+ tableBuilder.SetFilter(BuildFilter(criteria.Filter));
+ }
+
+ // optional string startColumn = 9;
+ if (criteria.StartColumn != null)
+ {
+ tableBuilder.SetStartColumn(criteria.StartColumn);
+ }
+
+ // optional string endColumn = 10;
+ if (criteria.EndColumn != null)
+ {
+ tableBuilder.SetEndColumn(criteria.EndColumn);
+ }
+
+ return tableBuilder.Build();
+ }
+
+ #endregion
+
+ private void LogEncodedMessage(Context context, IMessage message)
+ {
+ if (context.ClientConfig.OTSDebugLogHandler != null)
+ {
+ var msgString = String.Format("OTS Request API: {0} Protobuf: {1}\n",
+ context.APIName,
+ TextFormat.PrintToString(message));
+ context.ClientConfig.OTSDebugLogHandler(msgString);
+ }
+ }
+
+ private static PB.ComparatorType ToPBComparatorType(DataModel.CompareOperator compareOperator)
+ {
+ switch (compareOperator)
+ {
+ case DataModel.CompareOperator.EQUAL:
+ return PB.ComparatorType.CT_EQUAL;
+ case DataModel.CompareOperator.NOT_EQUAL:
+ return PB.ComparatorType.CT_NOT_EQUAL;
+ case DataModel.CompareOperator.GREATER_THAN:
+ return PB.ComparatorType.CT_GREATER_THAN;
+ case DataModel.CompareOperator.GREATER_EQUAL:
+ return PB.ComparatorType.CT_GREATER_EQUAL;
+ case DataModel.CompareOperator.LESS_THAN:
+ return PB.ComparatorType.CT_LESS_THAN;
+ case DataModel.CompareOperator.LESS_EQUAL:
+ return PB.ComparatorType.CT_LESS_EQUAL;
+ default:
+ throw new ArgumentException("Unknown compare operator: " + compareOperator);
+ }
+ }
+
+ private static PB.ReturnType ToPBReturnType(DataModel.ReturnType returnType)
+ {
+ switch (returnType)
+ {
+ case DataModel.ReturnType.RT_NONE:
+ return PB.ReturnType.RT_NONE;
+ case DataModel.ReturnType.RT_PK:
+ return PB.ReturnType.RT_PK;
+ case DataModel.ReturnType.RT_AFTER_MODIFY:
+ return PB.ReturnType.RT_AFTER_MODIFY;
+ default:
+ throw new ArgumentException("Invalid return type: " + returnType);
+ }
+ }
+
+ private static PB.Direction ToPBDirection(Request.GetRangeDirection direction)
+ {
+ switch (direction)
+ {
+ case Request.GetRangeDirection.Forward:
+ return PB.Direction.FORWARD;
+ case Request.GetRangeDirection.Backward:
+ return PB.Direction.BACKWARD;
+ default:
+ throw new ArgumentException("unknown direction type:" + direction);
+ }
+ }
+
+ private static PB.FilterType ToPBFilterType(DataModel.Filter.FilterType filterType)
+ {
+ switch (filterType)
+ {
+ case DataModel.Filter.FilterType.SINGLE_COLUMN_VALUE_FILTER:
+ return PB.FilterType.FT_SINGLE_COLUMN_VALUE;
+ case DataModel.Filter.FilterType.COMPOSITE_COLUMN_VALUE_FILTER:
+ return PB.FilterType.FT_COMPOSITE_COLUMN_VALUE;
+ case DataModel.Filter.FilterType.COLUMN_PAGINATION_FILTER:
+ return PB.FilterType.FT_COLUMN_PAGINATION;
+ default:
+ throw new ArgumentException("Unknown filter type: " + filterType);
+ }
+ }
+
+ private bool CheckQueryCondition(string tableName, int? maxVersions, DataModel.TimeRange timeRange)
+ {
+ if (maxVersions.HasValue && timeRange != null)
+ {
+ throw new OTSException("Error, MaxVersions and TimeRange can NOT be specified at the same time. Table name:" + tableName);
+ }
+
+ if (!maxVersions.HasValue && timeRange == null)
+ {
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/Handler/RetryHandler.cs b/netstandard-sdk/Aliyun/OTS/Handler/RetryHandler.cs
new file mode 100644
index 0000000..79538ba
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/Handler/RetryHandler.cs
@@ -0,0 +1,99 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Linq;
+using System.Threading;
+using Aliyun.OTS.Retry;
+
+namespace Aliyun.OTS.Handler
+{
+ public class RetryHandler : PipelineHandler
+ {
+ public RetryHandler(PipelineHandler innerHandler) : base(innerHandler) { }
+
+ public override void HandleBefore(Context context)
+ {
+ InnerHandler.HandleBefore(context);
+ }
+
+ private bool ShouldRetry(RetryPolicy retryPolicy, Context context, OTSException exception)
+ {
+ if (retryPolicy.MaxRetryTimeReached(context, exception))
+ {
+ return false;
+ }
+
+ if (retryPolicy.CanRetry(context, exception))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ private void ResetRetry(Context context)
+ {
+ InnerHandler.HandleBefore(context);
+ context.HttpTask.Wait();
+ }
+
+ public override void HandleAfter(Context context)
+ {
+ var retryPolicy = context.ClientConfig.RetryPolicy;
+
+ while (true)
+ {
+ OTSException exceptionForRetry = null;
+
+ try
+ {
+ InnerHandler.HandleAfter(context);
+ }
+ catch (OTSClientException exception)
+ {
+ exceptionForRetry = exception;
+ }
+ catch (OTSServerException exception)
+ {
+ exceptionForRetry = exception;
+ }
+
+ if (OTSClientTestHelper.RetryTimesAndBackOffRecordSwith) {
+ if (OTSClientTestHelper.RetryExceptions.Count() > OTSClientTestHelper.RetryTimes) {
+ exceptionForRetry = OTSClientTestHelper.RetryExceptions[OTSClientTestHelper.RetryTimes];
+ }
+ }
+
+ if (ShouldRetry(retryPolicy, context, exceptionForRetry)) {
+ int retryDelay = retryPolicy.DelayBeforeNextRetry(context, exceptionForRetry);
+ Thread.Sleep(retryDelay);
+ ResetRetry(context);
+ context.RetryTimes += 1;
+
+ if (OTSClientTestHelper.RetryTimesAndBackOffRecordSwith) {
+ OTSClientTestHelper.RetryTimes += 1;
+ OTSClientTestHelper.RetryDelays.Add(retryDelay);
+ }
+
+ continue;
+ }
+
+ if (exceptionForRetry != null) {
+ throw exceptionForRetry;
+ }
+
+ // TODO handle retry in BatchWriteRow & BatchGetRow
+ return;
+ }
+
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/OTSClient.cs b/netstandard-sdk/Aliyun/OTS/OTSClient.cs
new file mode 100644
index 0000000..06ee930
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/OTSClient.cs
@@ -0,0 +1,832 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Collections.Generic;
+using System.Threading.Tasks;
+
+using Aliyun.OTS.DataModel;
+using Aliyun.OTS.Request;
+using Aliyun.OTS.Response;
+using Aliyun.OTS.Handler;
+using Aliyun.OTS.DataModel.ConditionalUpdate;
+using System;
+using System.Net;
+using System.Net.Http;
+
+namespace Aliyun.OTS
+{
+ ///
+ /// OTSClient实现,用来访问OTS。
+ ///
+ /// OTSClient实现了OTS服务的所有接口,包括同步形式和异步形式。用户可以通过创建OTSClient的实例,并调用它的
+ /// 方法来访问OTS服务的所有功能。
+ ///
+ ///
+ /// 除了外,OTSClient提供的其他API都存在2种形式:同步和异步;并且
+ /// 这些接口都接受一个特定的request实例,这个实例分别封装了请求的不同参数;同样,这些接口都返回一个
+ /// response实例,这个实例封装了API的返回数据。
+ ///
+ ///
+ /// 例如接口,它接受的实例作为参数,在这里实例里
+ /// 你可以指定表名、主键名以及其他参数;这个接口返回的实例,包含本次
+ /// GetRow请求消耗的CapacityUnit。
+ ///
+ ///
+ /// 而 的异步形式 同样接受
+ /// 作为参数,但它返回一个Task实例,用来代表异步操作。这个异步操作的结果(Task.Result)即
+ /// 。
+ ///
+ ///
+ public class OTSClient
+ {
+ #region Fields & Properties
+
+ private HttpClient client;
+
+ private OTSHandler OTSHandler;
+ private readonly OTSClientConfig ClientConfig;
+
+ #endregion
+
+ #region Construct
+
+ ///
+ /// OTSClient的构造函数。
+ ///
+ /// OTS服务的地址(例如 'http://instance.cn-hangzhou.ots.aliyun.com:80'),必须以'http://'或者'https://'开头。
+ /// OTS的Access Key ID,通过官方网站申请。
+ /// OTS的Access Key Secret,通过官方网站申请。
+ /// OTS实例名,通过官方网站控制台创建。
+ ///
+ public OTSClient(string endPoint, string accessKeyID, string accessKeySecret, string instanceName)
+ : this(new OTSClientConfig(endPoint, accessKeyID, accessKeySecret, instanceName)) { }
+
+ // public OTSClient(string configFileName) { }
+ // TODO enable client config file later
+
+ ///
+ /// 通过客户端配置的实例来创建实例。
+ ///
+ /// 客户端配置实例
+ public OTSClient(OTSClientConfig config)
+ {
+ ClientConfig = config;
+ OTSHandler = new OTSHandler();
+
+ client = new HttpClient
+ {
+ BaseAddress = new Uri(ClientConfig.EndPoint)
+ };
+
+ ServicePointManager.DefaultConnectionLimit = config.ConnectionLimit;
+ OTSClientTestHelper.Reset();
+ }
+
+ #endregion
+
+ #region Table Operations
+ // ListTable
+ ///
+ /// 获取当前实例下已创建的所有表的表名。
+ ///
+ /// 请求参数
+ /// ListTable的返回,用来获取表名列表。
+ ///
+ /// 获取一个实例下所有表名并循环读取
+ ///
+ /// var request = new ListTableRequest();
+ /// var response = otsClient.ListTable(request);
+ /// foreach (var tableName in response.TableNames) {
+ /// // Do something
+ /// }
+ ///
+ ///
+ public ListTableResponse ListTable(ListTableRequest request)
+ {
+ return GetResponseFromAsyncTask(ListTableAsync(request));
+ }
+
+ ///
+ /// ListTable的异步形式。
+ ///
+ ///
+ ///
+ public Task ListTableAsync(ListTableRequest request)
+ {
+ return CallAsync("/ListTable", request);
+ }
+
+ ///
+ /// 根据表信息(包含表名、主键的设计和预留读写吞吐量)创建表。
+ ///
+ /// 请求参数
+ /// CreateTable的返回,这个返回实例是空的,不包含具体信息。
+ ///
+ ///
+ /// 创建一个有2个主键列,预留读吞吐量为0,预留写吞吐量为0的表。CU的详细使用规则请参考OTS文档
+ ///
+ /// var primaryKeySchema = new PrimaryKeySchema();
+ /// primaryKeySchema.Add("PK0", ColumnValueType.Integer);
+ /// primaryKeySchema.Add("PK1", ColumnValueType.String);
+ ///
+ /// var tableMeta = new TableMeta("SampleTable", primaryKeySchema);
+ /// var reservedThroughput = new CapacityUnit(0, 0);
+ /// var request = new CreateTableRequest(tableMeta, reservedThroughput);
+ /// var response = otsClient.CreateTable(request);
+ ///
+ ///
+ public CreateTableResponse CreateTable(CreateTableRequest request)
+ {
+ return GetResponseFromAsyncTask(CreateTableAsync(request));
+ }
+
+ ///
+ /// CreateTable的异步形式。
+ ///
+ ///
+ ///
+ public Task CreateTableAsync(CreateTableRequest request)
+ {
+ return CallAsync("/CreateTable", request);
+ }
+
+ ///
+ /// 根据表名删除表。
+ ///
+ /// 请求参数
+ /// DeleteTable的返回,这个返回实例是空的,不包含具体信息。
+ ///
+ public DeleteTableResponse DeleteTable(DeleteTableRequest request)
+ {
+ return GetResponseFromAsyncTask(DeleteTableAsync(request));
+ }
+
+ ///
+ /// DeleteTable的异步形式。
+ ///
+ ///
+ ///
+ public Task DeleteTableAsync(DeleteTableRequest request)
+ {
+ return CallAsync("/DeleteTable", request);
+ }
+
+ // UpdateTable
+ ///
+ /// 更新指定表的预留读吞吐量或预留写吞吐量设置,新设定将于更新成功一分钟内生效。
+ ///
+ /// 请求参数,包含表名以及预留读写吞吐量
+ /// UpdateTable的返回,包含更新后的预留读写吞吐量等信息
+ ///
+ /// 将表的预留读吞吐量调整为1,预留写吞吐量调整为1。
+ ///
+ /// var reservedThroughput = new CapacityUnit(1, 1);
+ /// var request = new UpdateTableRequest("SampleTable", reservedThroughput);
+ /// var response = otsClient.UpdateTable(request);
+ ///
+ ///
+ public UpdateTableResponse UpdateTable(UpdateTableRequest request)
+ {
+ return GetResponseFromAsyncTask(UpdateTableAsync(request));
+ }
+
+ ///
+ /// UpdateTable的异步形式。
+ ///
+ ///
+ ///
+ public Task UpdateTableAsync(UpdateTableRequest request)
+ {
+ return CallAsync("/UpdateTable", request);
+ }
+
+ // DescribeTable
+ ///
+ /// 查询指定表的结构信息和预留读写吞吐量设置信息。
+ ///
+ /// 请求参数,包含表名
+ /// DescribeTable的返回,包含表的结构信息和预留读写吞吐量等信息。
+ public DescribeTableResponse DescribeTable(DescribeTableRequest request)
+ {
+ return GetResponseFromAsyncTask(DescribeTableAsync(request));
+ }
+
+ ///
+ /// DescribeTable的异步形式。
+ ///
+ ///
+ ///
+ public Task DescribeTableAsync(DescribeTableRequest request)
+ {
+ return CallAsync("/DescribeTable", request);
+ }
+
+ #endregion
+
+ #region Single Row Operations
+ ///
+ /// 根据给定的主键读取单行数据。
+ ///
+ /// 请求参数
+ /// GetRow的返回
+ ///
+ ///
+ /// var primaryKey = new PrimaryKey();
+ /// primaryKey.Add("PK0", new ColumnValue("ABC"));
+ /// primaryKey.Add("PK1", new ColumnValue(123));
+ /// var getRowRequest = new GetRowRequest(
+ /// "SampleTableName",
+ /// primaryKey
+ /// );
+ /// var getRowResponse = otsClient.GetRow(getRowRequest);
+ ///
+ /// System.Console.WriteLine("GetRow CU Consumed: Read {0} Write {0}",
+ /// getRowResponse.ConsumedCapacityUnit.Read,
+ /// getRowResponse.ConsumedCapacityUnit.Write);
+ ///
+ /// var pk0 = getRowResponse.PrimaryKey["PK0"];
+ /// System.Console.WriteLine("PrimaryKey PK0 Value {0}", pk0.StringValue);
+ /// var pk1 = getRowResponse.PrimaryKey["PK1"];
+ /// System.Console.WriteLine("PrimaryKey PK1 Value {0}", pk1.IntegerValue);
+ /// var attr0 = getRowResponse.Attribute["IntAttr0"];
+ /// System.Console.WriteLine("Attribute IntAttr0 Value {0}", attr0.IntegerValue);
+ /// var attr1 = getRowResponse.Attribute["StringAttr1"];
+ /// System.Console.WriteLine("Attribute StringAttr1 Value {0}", attr1.StringValue);
+ /// var attr2 = getRowResponse.Attribute["DoubleAttr2"];
+ /// System.Console.WriteLine("Attribute DoubleAttr2 Value {0}", attr2.DoubleValue);
+ /// var attr3 = getRowResponse.Attribute["BooleanAttr3"];
+ /// System.Console.WriteLine("Attribute BooleanAttr3 Value {0}", attr2.BooleanValue);
+ ///
+ ///
+ public GetRowResponse GetRow(GetRowRequest request)
+ {
+ return GetResponseFromAsyncTask(GetRowAsync(request));
+ }
+
+ ///
+ /// GetRow的异步形式。
+ ///
+ ///
+ ///
+ public Task GetRowAsync(GetRowRequest request)
+ {
+ return CallAsync("/GetRow", request);
+ }
+
+ ///
+ /// 插入数据到指定的行,如果该行不存在,则新增一行;若该行存在,则覆盖原有行。
+ /// 指定表名、主键和属性,写入一行数据。返回本次操作消耗的CapacityUnit。
+ ///
+ /// 请求实例
+ /// 响应实例
+ ///
+ /// 写入1行数据,并打印出返回的读写能力消耗。
+ ///
+ /// var primaryKey = new PrimaryKey();
+ /// primaryKey.Add("PK0", new ColumnValue("ABC"));
+ /// primaryKey.Add("PK1", new ColumnValue(123));
+ ///
+ /// var attribute = new AttributeColumns();
+ /// attribute.Add("IntAttr0", new ColumnValue(12345));
+ /// attribute.Add("StringAttr1", new ColumnValue("ABC"));
+ /// attribute.Add("DoubleAttr2", new ColumnValue(3.14));
+ /// attribute.Add("BooleanAttr3", new ColumnValue(true));
+ ///
+ /// var putRowRequest = new PutRowRequest(
+ /// "SampleTableName",
+ /// new Condition(RowExistenceExpectation.IGNORE),
+ /// primaryKey,
+ /// attribute
+ /// );
+ ///
+ /// var putRowResponse = otsClient.PutRow(putRowRequest);
+ /// System.Console.WriteLine("PutRow CU Consumed: Read {0} Write {0}",
+ /// putRowResponse.ConsumedCapacityUnit.Read,
+ /// putRowResponse.ConsumedCapacityUnit.Write);
+ ///
+ ///
+ public PutRowResponse PutRow(PutRowRequest request)
+ {
+ return GetResponseFromAsyncTask(PutRowAsync(request));
+ }
+
+ ///
+ /// PutRow的异步形式。
+ ///
+ ///
+ ///
+ public Task PutRowAsync(PutRowRequest request)
+ {
+ return CallAsync("/PutRow", request);
+ }
+
+ ///
+ /// 更新指定行的数据,如果该行不存在,则新增一行;若该行存在,则根据请求的内容在这一行中新增、修改或者删除指定列的值。
+ ///
+ /// 请求实例
+ /// 响应实例
+ ///
+ /// 更新一行,新增一列"NewColumn",并删除一列"IntAttr0"。
+ ///
+ /// var primaryKey = new PrimaryKey();
+ /// primaryKey.Add("PK0", new ColumnValue("ABC"));
+ /// primaryKey.Add("PK1", new ColumnValue(123));
+ /// var updateOfAttribute = new UpdateOfAttribute();
+ /// updateOfAttribute.AddAttributeColumnToPut("NewColumn", new ColumnValue(123));
+ /// updateOfAttribute.AddAttributeColumnToDelete("IntAttr0");
+ ///
+ /// var updateRowRequest = new UpdateRowRequest(
+ /// "SampleTableName",
+ /// new Condition(RowExistenceExpectation.EXPECT_EXIST),
+ /// primaryKey,
+ /// updateOfAttribute);
+ /// var updateRowResponse = otsClient.UpdateRow(updateRowRequest);
+ ///
+ /// System.Console.WriteLine("UpdateRow CU Consumed: Read {0} Write {0}",
+ /// updateRowResponse.ConsumedCapacityUnit.Read,
+ /// updateRowResponse.ConsumedCapacityUnit.Write);
+ ///
+ ///
+ public UpdateRowResponse UpdateRow(UpdateRowRequest request)
+ {
+ return GetResponseFromAsyncTask(UpdateRowAsync(request));
+ }
+
+ ///
+ /// UpdateRow的异步形式。
+ ///
+ ///
+ ///
+ public Task UpdateRowAsync(UpdateRowRequest request)
+ {
+ return CallAsync("/UpdateRow", request);
+ }
+
+ ///
+ /// 指定表名和主键,删除一行数据。
+ ///
+ /// 请求实例
+ /// 响应实例
+ ///
+ /// 删除一行
+ ///
+ /// var primaryKey = new PrimaryKey();
+ /// primaryKey.Add("PK0", new ColumnValue("ABC"));
+ /// primaryKey.Add("PK1", new ColumnValue(123));
+ ///
+ /// var deleteRowRequest = new DeleteRowRequest(
+ /// "SampleTableName",
+ /// Condition.EXPECT_EXIST,
+ /// primaryKey);
+ ///
+ /// var deleteRowResponse = otsClient.DeleteRow(deleteRowRequest);
+ /// System.Console.WriteLine("DeleteRow CU Consumed: Read {0} Write {0}",
+ /// deleteRowResponse.ConsumedCapacityUnit.Read,
+ /// deleteRowResponse.ConsumedCapacityUnit.Write);
+ ///
+ ///
+ public DeleteRowResponse DeleteRow(DeleteRowRequest request)
+ {
+ return GetResponseFromAsyncTask(DeleteRowAsync(request));
+ }
+
+ ///
+ /// DeleteRow的异步形式。
+ ///
+ ///
+ ///
+ ///
+ public Task DeleteRowAsync(DeleteRowRequest request)
+ {
+ return CallAsync("/DeleteRow", request);
+ }
+
+ #endregion
+
+ #region Multiple Row Operations
+ ///
+ /// 批量读取一个或多个表中的若干行数据。
+ /// BatchGetRow操作可视为多个GetRow操作的集合,各个操作独立执行,
+ /// 独立返回结果,独立计算服务能力单元。
+ /// 与执行大量的GetRow操作相比,使用BatchGetRow操作可以有效减少请求的响应时间,提高数据的读取速率。
+ ///
+ /// 请求实例
+ /// 响应实例
+ ///
+ /// 用BatchWriteRow读取2行数据
+ ///
+ /// var primaryKey1 = new PrimaryKey();
+ /// primaryKey1.Add("PK0", new ColumnValue("TestData"));
+ /// primaryKey1.Add("PK1", new ColumnValue(0));
+ ///
+ /// var primaryKey2 = new PrimaryKey();
+ /// primaryKey2.Add("PK0", new ColumnValue("TestData"));
+ /// primaryKey2.Add("PK1", new ColumnValue(1));
+ ///
+ /// var batchGetRowRequest = new BatchGetRowRequest();
+ /// var primaryKeys = new List<PrimaryKey>() {
+ /// primaryKey1,
+ /// primaryKey2
+ /// };
+ /// batchGetRowRequest.Add("SampleTableName", primaryKeys);
+ /// var batchGetRowRespnse = otsClient.BatchGetRow(batchGetRowRequest);
+ ///
+ /// foreach (var responseForOneTable in batchGetRowRespnse.RowDataGroupByTable) {
+ /// foreach (var row in responseForOneTable.Value) {
+ /// // 处理每一行的返回
+ /// }
+ /// }
+ ///
+ ///
+ public BatchGetRowResponse BatchGetRow(BatchGetRowRequest request)
+ {
+ return GetResponseFromAsyncTask(BatchGetRowAsync(request));
+ }
+
+ ///
+ /// BatchGetRow的异步形式。
+ ///
+ ///
+ ///
+ public Task BatchGetRowAsync(BatchGetRowRequest request)
+ {
+ return CallAsync("/BatchGetRow", request);
+ }
+
+ ///
+ /// 批量插入,修改或删除一个或多个表中的若干行数据。
+ /// BatchWriteRow操作可视为多个PutRow、UpdateRow、DeleteRow操作的集合,各个操作独立执行,独立返回结果,独立计算服务能力单元。
+ /// 与执行大量的单行写操作相比,使用BatchWriteRow操作可以有效减少请求的响应时间,提高数据的写入速率。
+ ///
+ /// 请求实例
+ /// 响应实例
+ ///
+ /// 用BatchWriteRow写入2行并解析返回
+ ///
+ /// var primaryKey1 = new PrimaryKey();
+ /// primaryKey1.Add("PK0", new ColumnValue("TestData"));
+ /// primaryKey1.Add("PK1", new ColumnValue(0));
+ ///
+ /// var attribute1 = new AttributeColumns();
+ /// attribute1.Add("Col0", new ColumnValue("Hangzhou"));
+ ///
+ /// var primaryKey2 = new PrimaryKey();
+ /// primaryKey2.Add("PK0", new ColumnValue("TestData"));
+ /// primaryKey2.Add("PK1", new ColumnValue(1));
+ ///
+ /// var attribute2 = new AttributeColumns();
+ /// attribute2.Add("Col0", new ColumnValue("Shanghai"));
+ ///
+ /// var rowChanges = new RowChanges();
+ /// rowChanges.AddPut(new Condition(RowExistenceExpectation.IGNORE), primaryKey1, attribute1);
+ /// rowChanges.AddPut(new Condition(RowExistenceExpectation.IGNORE), primaryKey2, attribute2);
+ /// var batchWriteRowRequest = new BatchWriteRowRequest();
+ /// batchWriteRowRequest.Add("SampleTableName", rowChanges);
+ ///
+ /// var batchWriteRowResponse = otsClient.BatchWriteRow(batchWriteRowRequest);
+ /// foreach (var responseForOneTable in batchWriteRowResponse.TableRespones) {
+ /// foreach (var row in responseForOneTable.Value.PutResponses) {
+ /// // 处理每一行的返回
+ /// }
+ /// }
+ ///
+ ///
+ public BatchWriteRowResponse BatchWriteRow(BatchWriteRowRequest request)
+ {
+ return GetResponseFromAsyncTask(BatchWriteRowAsync(request));
+ }
+
+ ///
+ /// BatchWriteRow的异步形式。
+ ///
+ ///
+ ///
+ public Task BatchWriteRowAsync(BatchWriteRowRequest request)
+ {
+ return CallAsync("/BatchWriteRow", request);
+ }
+
+ ///
+ /// 根据范围条件获取多行数据,返回用来迭代每一行数据的迭代器。
+ ///
+ ///
+ /// 返回的迭代器。
+ public IEnumerable GetRangeIterator(GetIteratorRequest request)
+ {
+ int? leftCount = request.QueryCriteria.Limit;
+
+ if (leftCount != null && leftCount < 0)
+ {
+ throw new OTSClientException("the value of count must be larger than 0");
+ }
+
+ var nextStartPrimaryKey = request.QueryCriteria.InclusiveStartPrimaryKey;
+
+ while (nextStartPrimaryKey != null)
+ {
+ request.QueryCriteria.InclusiveStartPrimaryKey = nextStartPrimaryKey;
+ request.QueryCriteria.Limit = leftCount;
+
+ var response = GetRange(request);
+ request.ConsumedCapacityUnitCounter.Read += response.ConsumedCapacityUnit.Read;
+ nextStartPrimaryKey = response.NextPrimaryKey;
+
+ foreach (var rowData in response.RowDataList)
+ {
+ yield return rowData;
+ }
+
+ if (leftCount != null)
+ {
+ leftCount -= response.RowDataList.Count;
+ if (leftCount <= 0)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 根据范围条件获取多行数据,返回用来迭代每一行数据的迭代器。
+ ///
+ /// 表名
+ /// 范围的方向,可以是或者
+ /// 范围的开始主键,包含。
+ /// 范围的结束主键,不包含。
+ /// 用户传入的CapacityUnit消耗计数器。
+ /// 可选参数,表示要获取的列的名称列表;默认获取所有列。
+ /// 可选参数,表示最多获取多少行;默认获取范围内的所有行。
+ /// 返回的迭代器。
+ ///
+ ///
+ /// var startPrimaryKey = new PrimaryKey();
+ /// startPrimaryKey.Add("PK0", new ColumnValue("TestData"));
+ /// startPrimaryKey.Add("PK1", ColumnValue.INF_MIN);
+ ///
+ /// var endPrimaryKey = new PrimaryKey();
+ /// endPrimaryKey.Add("PK0", new ColumnValue("TestData"));
+ /// endPrimaryKey.Add("PK1", ColumnValue.INF_MAX);
+ ///
+ /// var consumed = new CapacityUnit(0, 0);
+ ///
+ /// var iterator = otsClient.GetRangeIterator(
+ /// "SampleTableName",
+ /// GetRangeDirection.Forward,
+ /// startPrimaryKey,
+ /// endPrimaryKey,
+ /// consumed);
+ ///
+ /// foreach (var rowData in iterator) {
+ /// // 处理每一行数据
+ /// }
+ ///
+ ///
+ [Obsolete("GetRangeIterator(string ...) is deprecated, please use GetRangeIterator(GetIteratorRequest request) instead.")]
+ public IEnumerable GetRangeIterator(
+ string tableName,
+ GetRangeDirection direction,
+ PrimaryKey inclusiveStartPrimaryKey,
+ PrimaryKey exclusiveEndPrimaryKey,
+ CapacityUnit consumedCapacityUnitCounter,
+ HashSet columnsToGet = null,
+ int? count = null,
+ IColumnCondition condition = null)
+ {
+ int? leftCount = count;
+
+ if (leftCount != null && leftCount < 0)
+ {
+ throw new OTSClientException("the value of count must be larger than 0");
+ }
+
+ PrimaryKey nextStartPrimaryKey = inclusiveStartPrimaryKey;
+
+ while (nextStartPrimaryKey != null)
+ {
+ var request = new GetRangeRequest(
+ tableName, direction, nextStartPrimaryKey, exclusiveEndPrimaryKey,
+ columnsToGet, leftCount, condition);
+
+ var response = GetRange(request);
+ consumedCapacityUnitCounter.Read += response.ConsumedCapacityUnit.Read;
+ nextStartPrimaryKey = response.NextPrimaryKey;
+
+ foreach (var rowData in response.RowDataList)
+ {
+ yield return rowData;
+ }
+
+ if (leftCount != null)
+ {
+ leftCount -= response.RowDataList.Count;
+ if (leftCount <= 0)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ ///
+ /// 根据范围条件获取多行数据。
+ ///
+ /// 请求实例
+ /// 响应实例
+ public GetRangeResponse GetRange(GetRangeRequest request)
+ {
+ return GetResponseFromAsyncTask(GetRangeAsync(request));
+ }
+
+ ///
+ /// GetRange的异步版本。
+ ///
+ ///
+ ///
+ public Task GetRangeAsync(GetRangeRequest request)
+ {
+ return CallAsync("/GetRange", request);
+ }
+
+ #endregion
+
+ #region Search Operations
+ public ListSearchIndexResponse ListSearchIndex(ListSearchIndexRequest request)
+ {
+ return GetResponseFromAsyncTask(ListSearchIndexAsync(request));
+ }
+
+ ///
+ /// ListSearchIndex的异步形式。
+ ///
+ ///
+ ///
+ public Task ListSearchIndexAsync(ListSearchIndexRequest request)
+ {
+ return CallAsync("/ListSearchIndex", request);
+ }
+
+ public CreateSearchIndexResponse CreateSearchIndex(CreateSearchIndexRequest request)
+ {
+ return GetResponseFromAsyncTask(CreateSearchIndexAsync(request));
+ }
+
+ ///
+ /// CreateSearchIndex的异步形式。
+ ///
+ ///
+ ///
+ public Task CreateSearchIndexAsync(CreateSearchIndexRequest request)
+ {
+ return CallAsync("/CreateSearchIndex", request);
+ }
+
+ public DeleteSearchIndexResponse DeleteSearchIndex(DeleteSearchIndexRequest request)
+ {
+ return GetResponseFromAsyncTask(DeleteSearchIndexAsync(request));
+ }
+
+ ///
+ /// DeleteSearchIndex的异步形式。
+ ///
+ ///
+ ///
+ public Task DeleteSearchIndexAsync(DeleteSearchIndexRequest request)
+ {
+ return CallAsync("/DeleteSearchIndex", request);
+ }
+
+ public DescribeSearchIndexResponse DescribeSearchIndex(DescribeSearchIndexRequest request)
+ {
+ return GetResponseFromAsyncTask(DescribeSearchIndexAsync(request));
+ }
+
+ ///
+ /// DescribeSearchIndex的异步形式。
+ ///
+ ///
+ ///
+ public Task DescribeSearchIndexAsync(DescribeSearchIndexRequest request)
+ {
+ return CallAsync("/DescribeSearchIndex", request);
+ }
+
+ public SearchResponse Search(SearchRequest request)
+ {
+ return GetResponseFromAsyncTask(SearchAsync(request));
+ }
+
+ ///
+ /// Search的异步形式。
+ ///
+ ///
+ ///
+ public Task SearchAsync(SearchRequest request)
+ {
+ return CallAsync("/Search", request);
+ }
+ #endregion
+
+
+ #region Search Operations
+
+
+ public CreateGlobalIndexResponse CreateGlobalIndex(CreateGlobalIndexRequest request)
+ {
+ return GetResponseFromAsyncTask(CreateGlobalIndexAsync(request));
+ }
+
+ ///
+ /// CreateGlobalIndex的异步形式。
+ ///
+ ///
+ ///
+ public Task CreateGlobalIndexAsync(CreateGlobalIndexRequest request)
+ {
+ return CallAsync("/CreateIndex", request);
+ }
+
+ public DeleteGlobalIndexResponse DeleteGlobalIndex(DeleteGlobalIndexRequest request)
+ {
+ return GetResponseFromAsyncTask(DeleteGlobalIndexAsync(request));
+ }
+
+ ///
+ /// CreateGlobalIndex的异步形式。
+ ///
+ ///
+ ///
+ public Task DeleteGlobalIndexAsync(DeleteGlobalIndexRequest request)
+ {
+ return CallAsync("/DropIndex", request);
+ }
+
+ #endregion
+
+
+ #region Private Function
+
+ private void ThrowIfNullRequest(TRequestType request)
+ {
+ if (request == null)
+ {
+ throw new ArgumentNullException("request");
+ }
+ }
+
+
+ private Task CallAsync(string apiName, TRequest request)
+ where TResponse : OTSResponse, new()
+ where TRequest : OTSRequest
+ {
+ ThrowIfNullRequest(request);
+
+ Context otsContext = new Context
+ {
+ ClientConfig = ClientConfig,
+ APIName = apiName,
+ OTSRequest = request,
+ OTSReponse = new TResponse(),
+ HttpClient = client
+ };
+
+ OTSHandler.HandleBefore(otsContext);
+
+ return otsContext.HttpTask.ContinueWith((t) =>
+ {
+ // ConnectionPool.ReturnHttpClient(otsContext.HttpClient);
+ OTSHandler.HandleAfter(otsContext);
+ return (TResponse)otsContext.OTSReponse;
+ });
+ }
+
+ private TResponse GetResponseFromAsyncTask(Task task)
+ {
+ try
+ {
+ task.Wait();
+ }
+ catch (AggregateException e)
+ {
+ if (ClientConfig.OTSErrorLogHandler != null)
+ {
+ ClientConfig.OTSErrorLogHandler.Invoke("Exception:\n" + e.GetBaseException().StackTrace + "\n");
+ }
+
+ throw e.GetBaseException();
+ }
+
+ return task.Result;
+ }
+
+ #endregion
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/OTSClientConfig.cs b/netstandard-sdk/Aliyun/OTS/OTSClientConfig.cs
new file mode 100644
index 0000000..cc7fa1b
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/OTSClientConfig.cs
@@ -0,0 +1,144 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using Aliyun.OTS.Util;
+using Aliyun.OTS.Retry;
+using System;
+
+namespace Aliyun.OTS
+{
+ ///
+ /// OTS客户端配置,用来设置用户的权限信息等。
+ ///
+ public class OTSClientConfig
+ {
+ private static int DefaultConnectionLimit = 300;
+ private static readonly string DefaultAPIVersion = "2015-12-31";
+ private const string UserAgentPrefix = "aliyun-tablestore-sdk-dotnet/";
+ private static readonly string _userAgent = GetDefaultUserAgent();
+
+ ///
+ /// OTS服务的地址(例如 'http://instance.cn-hangzhou.ots.aliyun.com:80'),必须以'http://'或'https://'开头。
+ ///
+ public string EndPoint { get; set; }
+
+ ///
+ /// OTS的Access Key ID,通过官方网站申请。
+ ///
+ public string AccessKeyID { get; set; }
+
+ ///
+ /// OTS的Access Key Secret,通过官方网站申请。
+ ///
+ public string AccessKeySecret { get; set; }
+
+ ///
+ /// OTS实例名,通过官方网站控制台创建。
+ ///
+ public string InstanceName { get; set; }
+
+ ///
+ /// OTS协议的版本,默认为"2015-12-31"。无需改动。
+ ///
+ public string APIVersion { get; set; }
+
+ ///
+ /// 连接池的最大连接数,默认为300。
+ ///
+ public int ConnectionLimit { get; set; }
+
+ ///
+ /// 重试策略,默认为。
+ ///
+ public RetryPolicy RetryPolicy { get; set; }
+
+ public string UserAgent
+ {
+ get { return _userAgent; }
+ }
+
+ ///
+ /// OTSClient的Log回调函数类型。如果要改变OTSClient默认的日志行为,需要定义这个类型的函数并
+ /// 设置到OTSClientConfig中。
+ ///
+ /// 回调函数被传入的日志信息。
+ public delegate void OTSLogHandler(string message);
+
+ ///
+ /// 错误日志的处理函数。默认行为是将日志输出到标准输出文件。
+ ///
+ public OTSLogHandler OTSErrorLogHandler { get; set; }
+
+ ///
+ /// 调试日志的处理函数。默认行为是将日志输出到标准输出文件。
+ ///
+ public OTSLogHandler OTSDebugLogHandler { get; set; }
+
+ ///
+ /// 跳过返回校验
+ ///
+ public bool SkipResponseValidation { get; set; }
+
+ ///
+ /// OTSClientConfig的构造函数。
+ ///
+ /// OTS服务的地址
+ /// OTS的Access Key ID
+ /// OTS的Access Key Secret
+ /// OTS实例名
+ public OTSClientConfig(string endPoint, string accessKeyID, string accessKeySecret, string instanceName)
+ {
+ if (string.IsNullOrEmpty(endPoint))
+ {
+ throw new ArgumentNullException("endPoint");
+ }
+
+ if (string.IsNullOrEmpty(accessKeyID))
+ {
+ throw new ArgumentNullException("accessKeyID");
+ }
+
+ if (string.IsNullOrEmpty(accessKeySecret))
+ {
+ throw new ArgumentNullException("AccessKeySecret");
+ }
+
+ if (string.IsNullOrEmpty(instanceName))
+ {
+ throw new ArgumentNullException("instanceName");
+ }
+
+ EndPoint = endPoint.Trim();
+ AccessKeyID = accessKeyID.Trim();
+ AccessKeySecret = accessKeySecret.Trim();
+ InstanceName = instanceName.Trim();
+ ConnectionLimit = DefaultConnectionLimit;
+ APIVersion = DefaultAPIVersion;
+ RetryPolicy = RetryPolicy.DefaultRetryPolicy;
+
+ OTSErrorLogHandler = OTSDefaultLogHandler.DefaultErrorLogHandler;
+ OTSDebugLogHandler = OTSDefaultLogHandler.DefaultDebugLogHandler;
+ }
+
+ ///
+ /// 获取User-Agent信息。
+ ///
+ private static string GetDefaultUserAgent()
+ {
+ return UserAgentPrefix +
+ typeof(OTSClientConfig).Assembly.GetName().Version + "(" +
+ OtsUtils.DetermineOsVersion() + "/" +
+ Environment.OSVersion.Version + "/" +
+ OtsUtils.DetermineSystemArchitecture() + ";" +
+ Environment.Version + ")";
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/OTSClientException.cs b/netstandard-sdk/Aliyun/OTS/OTSClientException.cs
new file mode 100644
index 0000000..84c32ab
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/OTSClientException.cs
@@ -0,0 +1,43 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Net;
+
+namespace Aliyun.OTS
+{
+ ///
+ /// OTS客户端错误,用来表示OTS SDK运行时遇到的错误。
+ ///
+ public class OTSClientException : OTSException
+ {
+ ///
+ /// 错误信息。
+ ///
+ public string ErrorMessage;
+
+ ///
+ /// HTTP返回码(如果有)。
+ ///
+ public HttpStatusCode HttpStatusCode { get; private set; }
+
+ public OTSClientException(string errorMessage)
+ : base(errorMessage)
+ {
+ ErrorMessage = errorMessage;
+ }
+
+ public OTSClientException(string errorMessage, HttpStatusCode httpCode)
+ : this(errorMessage)
+ {
+ HttpStatusCode = httpCode;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/OTSClientTestHelper.cs b/netstandard-sdk/Aliyun/OTS/OTSClientTestHelper.cs
new file mode 100644
index 0000000..c61a1b5
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/OTSClientTestHelper.cs
@@ -0,0 +1,67 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System.Net;
+using System.Collections.Generic;
+
+namespace Aliyun.OTS
+{
+ public static class OTSClientTestHelper
+ {
+ public static bool HTTPResponseBodyIsSet { get; private set; }
+ public static byte[] HTTPResponseBody { get; private set; }
+
+ public static bool HttpStatusCodeIsSet { get; private set; }
+ public static HttpStatusCode HttpStatusCode { get; private set; }
+
+ public static bool HttpResponseHeadersIsSet { get; private set; }
+ public static Dictionary HttpRequestHeaders { get; private set; }
+
+ public static bool RetryTimesAndBackOffRecordSwith { get; private set; }
+ public static int RetryTimes;
+ public static List RetryDelays { get; private set; }
+ public static List RetryExceptions { get; private set; }
+
+ public static void Reset()
+ {
+ HTTPResponseBodyIsSet = false;
+ HttpStatusCodeIsSet = false;
+ HttpResponseHeadersIsSet = false;
+ RetryTimesAndBackOffRecordSwith = false;
+ }
+
+ public static void SetHTTPResponseBody(byte[] body)
+ {
+ HTTPResponseBodyIsSet = true;
+ HTTPResponseBody = body;
+ }
+
+ public static void SetHttpStatusCode(HttpStatusCode code)
+ {
+ HttpStatusCodeIsSet = true;
+ HttpStatusCode = code;
+ }
+
+ public static void SetHttpRequestHeaders(Dictionary headers)
+ {
+ HttpResponseHeadersIsSet = true;
+ HttpRequestHeaders = headers;
+ }
+
+ public static void TurnOnRetryTimesAndBackOffRecording()
+ {
+ RetryTimesAndBackOffRecordSwith = true;
+ RetryTimes = 0;
+ RetryDelays = new List();
+ RetryExceptions = new List();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/OTSDefaultLogHandler.cs b/netstandard-sdk/Aliyun/OTS/OTSDefaultLogHandler.cs
new file mode 100644
index 0000000..0a991ca
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/OTSDefaultLogHandler.cs
@@ -0,0 +1,37 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+using System;
+
+namespace Aliyun.OTS
+{
+ ///
+ /// 默认的日志处理,行为是将错误日志和调试日志打印到标准输出文件。
+ ///
+ public class OTSDefaultLogHandler
+ {
+ protected static string GetDateTimeString()
+ {
+ return DateTime.Now.ToString("o");
+ }
+
+ public static void DefaultErrorLogHandler(string message)
+ {
+ var dateString = GetDateTimeString();
+ System.Console.WriteLine("OTSClient ERROR {0} {1}", dateString, message);
+ }
+
+ public static void DefaultDebugLogHandler(string message)
+ {
+ var dateString = GetDateTimeString();
+ System.Console.WriteLine("OTSClient DEBUG {0} {1}", dateString, message);
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/OTSException.cs b/netstandard-sdk/Aliyun/OTS/OTSException.cs
new file mode 100644
index 0000000..ee7d80a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/OTSException.cs
@@ -0,0 +1,28 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+
+namespace Aliyun.OTS
+{
+ ///
+ /// OTS错误类型的基类,它有两个子类和。
+ ///
+ public class OTSException : Exception
+ {
+ public OTSException() { }
+
+ public OTSException(string message)
+ : base(message)
+ {
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/OTSServerException.cs b/netstandard-sdk/Aliyun/OTS/OTSServerException.cs
new file mode 100644
index 0000000..5f74c9a
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/OTSServerException.cs
@@ -0,0 +1,101 @@
+/*
+ * Trade secret of Alibaba Group R&D.
+ * Copyright (c) 2015 Alibaba Group R&D.
+ *
+ * All rights reserved. This notice is intended as a precaution against
+ * inadvertent publication and does not imply publication or any waiver
+ * of confidentiality. The year included in the foregoing notice is the
+ * year of creation of the work.
+ *
+ */
+
+using System;
+using System.Net;
+
+namespace Aliyun.OTS
+{
+ ///
+ /// OTS服务端错误类型,用来表示OTS返回的错误。
+ ///
+ /// 完整的OTS出错信息请见阿里云官网关于OTS错误信息的定义。
+ ///
+ ///
+ public class OTSServerException : OTSException
+ {
+ ///
+ /// API名称,例如 "/GetRow","/CeateTable"。
+ ///
+ public string APIName { get; private set; }
+
+ ///
+ /// HTTP返回码。
+ ///
+ public HttpStatusCode HttpStatusCode { get; private set; }
+
+ ///
+ /// 错误类型字符串。
+ ///
+ public string ErrorCode { get; private set; }
+
+ ///
+ /// 错误消息字符串。
+ ///
+ public string ErrorMessage { get; private set; }
+
+ ///
+ /// 本次请求的ID,用于OTS工程师定位错误使用。
+ ///
+ public string RequestID { get; private set; }
+
+ private static string GetMessageString(string apiName, HttpStatusCode httpStatusCode, string errorCode, string errorMessage, string requestID)
+ {
+ string ret = String.Format(
+ "OTS request failed, API: {0}, HTTPStatus: {1} {2}",
+ apiName, (int)httpStatusCode, httpStatusCode
+ );
+
+ if (errorCode != null)
+ {
+ ret += String.Format(", ErrorCode: {0}", errorCode);
+ }
+
+ if (errorMessage != null)
+ {
+ ret += String.Format(", ErrorMessage: {0}", errorMessage);
+ }
+
+ if (requestID != null)
+ {
+ ret += String.Format(", Request ID: {0}", requestID);
+ }
+
+ return ret;
+ }
+
+ public OTSServerException(string apiName, HttpStatusCode httpStatusCode)
+ : base(GetMessageString(apiName, httpStatusCode, null, null, null))
+ {
+ APIName = apiName;
+ HttpStatusCode = httpStatusCode;
+ }
+
+ public OTSServerException(string apiName, HttpStatusCode httpStatusCode, string errorCode, string errorMessage)
+ : base(GetMessageString(apiName, httpStatusCode, errorCode, errorMessage, null))
+ {
+ APIName = apiName;
+ HttpStatusCode = httpStatusCode;
+ ErrorCode = errorCode;
+ ErrorMessage = errorMessage;
+ }
+
+ public OTSServerException(string apiName, HttpStatusCode httpStatusCode, string errorCode, string errorMessage, string requestID)
+ : base(GetMessageString(apiName, httpStatusCode, errorCode, errorMessage, requestID))
+ {
+ APIName = apiName;
+ HttpStatusCode = httpStatusCode;
+ ErrorCode = errorCode;
+ ErrorMessage = errorMessage;
+ RequestID = requestID;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/IResultParser.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/IResultParser.cs
new file mode 100644
index 0000000..f3c8ab2
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/IResultParser.cs
@@ -0,0 +1,8 @@
+using System;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public interface IResultParser
+ {
+ Object getObject(GetRowRequest response);
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferBuilder.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferBuilder.cs
new file mode 100644
index 0000000..5e804b5
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferBuilder.cs
@@ -0,0 +1,488 @@
+using System.IO;
+using Aliyun.OTS.DataModel;
+using System.Collections.Generic;
+using System;
+
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public static class PlainBufferBuilder
+ {
+ public static int ComputePrimaryKeyValue(ColumnValue value)
+ {
+ int size = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE;
+ size += ComputePrimaryKeyValueWithoutLengthPrefix(value);
+ return size;
+ }
+
+
+ // Bytes Data: value_type + type
+ public static int ComputePrimaryKeyValueWithoutLengthPrefix(ColumnValue value)
+ {
+ int size = 1; // length + type + value
+ if (value.IsInfMin() || value.IsInfMax() || value.IsPlaceHolderForAutoIncr())
+ {
+ return size; // inf value and AutoIncr only has a type.
+ }
+
+ switch (value.Type)
+ {
+ case ColumnValueType.String:
+ {
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE;
+ size += value.AsStringInBytes().Length;
+ break;
+ }
+ case ColumnValueType.Integer:
+ {
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE;
+ break;
+ }
+ case ColumnValueType.Binary:
+ {
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE;
+ size += value.BinaryValue.Length;
+ break;
+ }
+ default:
+ throw new IOException("Bug: unsupported primary key type: " + value.Type);
+
+ }
+ return size;
+ }
+
+ public static int ComputeColumnValue(ColumnValue value)
+ {
+ int size = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE;
+ size += ComputeColumnValueWithoutLengthPrefix(value);
+ return size;
+ }
+
+ // Bytes Data: value_type + type
+ public static int ComputeColumnValueWithoutLengthPrefix(ColumnValue value)
+ {
+ int size = 1; // length + type + value
+
+ if (value.IsInfMin() || value.IsInfMax() || value.IsPlaceHolderForAutoIncr())
+ {
+ return size; // inf value and AutoIncr only has a type.
+ }
+
+ switch (value.Type)
+ {
+ case ColumnValueType.String:
+ {
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE;
+ size += value.AsStringInBytes().Length;
+ break;
+ }
+ case ColumnValueType.Integer:
+ {
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE;
+ break;
+ }
+ case ColumnValueType.Binary:
+ {
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE;
+ size += value.BinaryValue.Length;
+ break;
+ }
+ case ColumnValueType.Double:
+ {
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE;
+ break;
+ }
+ case ColumnValueType.Boolean:
+ {
+ size += 1;
+ break;
+ }
+ default:
+ throw new IOException("Bug: unsupported column type: " + value.Type);
+
+ }
+
+ return size;
+ }
+
+ public static int ComputePlainBufferExtension(PlainBufferExtension extension)
+ {
+ int size = 1; //TAG_EXTENSION
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // Length
+ if (extension.HasSeq())
+ {
+ size += ComputePlainBufferSequenceInfo();
+ }
+
+ return size;
+ }
+
+ public static int ComputePlainBufferSequenceInfo()
+ {
+ int size = 1;//TAG_SEQ_INFO
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // Length
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // TAG_SEQ_INFO_EPOCH + epoch
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE; // TAG_SEQ_INFO_TS + timestamp
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // TAG_SEQ_INFO_ROW_INDEX + rowIndex
+ return size;
+ }
+
+ public static int ComputePlainBufferCell(PlainBufferCell cell)
+ {
+ int size = 1; // TAG_CELL
+ if (cell.HasCellName())
+ {
+ size += 1; // TAG_CELL_NAME
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // length
+ size += cell.GetNameRawData().Length;
+ }
+ if (cell.HasCellValue())
+ {
+ size += 1; // TAG_CELL_VALUE
+ if (cell.IsPk())
+ {
+ size += ComputePrimaryKeyValue(cell.GetPkCellValue());
+ }
+ else
+ {
+ size += ComputeColumnValue(cell.GetCellValue());
+ }
+ }
+ if (cell.HasCellType())
+ {
+ size += 2; // TAG_CELL_OP_TYPE + type
+ }
+ if (cell.HasCellTimestamp())
+ {
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE; // TAG_CELL_TIMESTAMP + timestamp
+ }
+ size += 2; // TAG_CELL_CHECKSUM + checksum
+ return size;
+ }
+
+ public static int ComputePlainBufferRow(PlainBufferRow row)
+ {
+ int size = 0;
+ size += 1; // TAG_ROW_PK
+ foreach (PlainBufferCell cell in row.GetPrimaryKey())
+ {
+ size += ComputePlainBufferCell(cell);
+ }
+ if (row.GetCells().Count > 0)
+ {
+ size += 1; // TAG_ROW_DATA
+ foreach (PlainBufferCell cell in row.GetCells())
+ {
+ size += ComputePlainBufferCell(cell);
+ }
+ }
+ if (row.HasDeleteMarker())
+ {
+ size += 1; // TAG_DELETE_MARKER
+ }
+ if (row.HasExtension())
+ {
+ size += ComputePlainBufferExtension(row.GetExtension());
+ }
+ size += 2; // TAG_ROW_CHECKSUM + checksum
+ return size;
+ }
+
+ public static int ComputePlainBufferRowWithHeader(PlainBufferRow row)
+ {
+ int size = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // header
+ size += ComputePlainBufferRow(row);
+ return size;
+ }
+
+
+ public static int ComputeSkipLengthForExtensionTag(PlainBufferExtension extension)
+ {
+ int size = 0;
+ if (extension.HasSeq())
+ {
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; //TAG_SEQ_ING + length
+ size += ComputeSkipLengthForSequenceInfo();
+ }
+
+ return size;
+ }
+
+ public static int ComputeSkipLengthForSequenceInfo()
+ {
+ int size = 0;
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // TAG_SEQ_INFO_EPOCH + epoch
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE; // TAG_SEQ_INFO_TS + timestamp
+ size += 1 + PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // TAG_SEQ_INFO_ROW_INDEX + rowIndex
+ return size;
+ }
+
+ public static byte[] BuildPrimaryKeyValueWithoutLengthPrefix(ColumnValue value)
+ {
+ int size = ComputePrimaryKeyValueWithoutLengthPrefix(value);
+ PlainBufferOutputStream output = new PlainBufferOutputStream(size);
+ PlainBufferCodedOutputStream codedOutput = new PlainBufferCodedOutputStream(output);
+ codedOutput.WritePrimaryKeyValueWithoutLengthPrefix(value);
+
+ if (!output.IsFull())
+ {
+ throw new IOException("Bug: serialize primary key value failed. Buffer remains " + output.Remain());
+ }
+
+ return output.GetBuffer();
+ }
+
+ public static byte[] BuildColumnValueWithoutLengthPrefix(ColumnValue value)
+ {
+ int size = ComputeColumnValueWithoutLengthPrefix(value);
+ PlainBufferOutputStream output = new PlainBufferOutputStream(size);
+ PlainBufferCodedOutputStream codedOutput = new PlainBufferCodedOutputStream(output);
+ codedOutput.WriteColumnValueWithoutLengthPrefix(value);
+
+ if (!output.IsFull())
+ {
+ throw new IOException("Bug: serialize column value failed. Buffer remains " + output.Remain());
+ }
+
+ return output.GetBuffer();
+ }
+
+ public static int ComputePrimaryKeyColumn(Column column)
+ {
+ int size = 2; // TAG_CELL + TAG_CELL_NAME;
+ size += PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE;
+ size += column.GetNameRawData().Length;
+ size += 1; // TAG_CELL_VALUE
+ size += ComputePrimaryKeyValue(column.Value);
+ size += 2; // TAG_CELL_CHECKSUM + checksum
+ return size;
+ }
+
+ // Bytes Data: TAG_ROW_PK + [primary key columns]
+ public static int ComputePrimaryKey(PrimaryKey primaryKey)
+ {
+ int size = 1; // TAG_ROW_PK
+ foreach (var key in primaryKey)
+ {
+ var column = new Column(key.Key, key.Value);
+ size += ComputePrimaryKeyColumn(column);
+ }
+
+ return size;
+ }
+
+ public static int ComputePrimaryKeyWithHeader(PrimaryKey primaryKey)
+ {
+ int size = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE; // Header
+ size += ComputePrimaryKey(primaryKey);
+ size += 2; // TAG_ROW_CHECKSUM + checksum
+ return size;
+ }
+
+ public static void WritePrimaryKeyValue(ColumnValue value, PlainBufferOutputStream output)
+ {
+ if (value.IsInfMin())
+ {
+ output.WriteRawLittleEndian32(1);
+ output.WriteRawByte(PlainBufferConsts.VT_INF_MIN);
+ return;
+ }
+
+ if (value.IsInfMax())
+ {
+ output.WriteRawLittleEndian32(1);
+ output.WriteRawByte(PlainBufferConsts.VT_INF_MAX);
+ return;
+ }
+
+ if (value.IsPlaceHolderForAutoIncr())
+ {
+ output.WriteRawLittleEndian32(1);
+ output.WriteRawByte(PlainBufferConsts.VT_AUTO_INCREMENT);
+ return;
+ }
+
+ switch (value.Type)
+ {
+ case ColumnValueType.String:
+ {
+ byte[] rawData = value.AsStringInBytes();
+ int prefixLength = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE + 1; // length + type + length
+ output.WriteRawLittleEndian32(prefixLength + rawData.Length); // length + type + value
+ output.WriteRawByte(PlainBufferConsts.VT_STRING);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+ }
+ case ColumnValueType.Integer:
+ {
+ output.WriteRawLittleEndian32(1 + PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE);
+ output.WriteRawByte(PlainBufferConsts.VT_INTEGER);
+ output.WriteRawLittleEndian64(value.IntegerValue);
+ break;
+ }
+ case ColumnValueType.Binary:
+ {
+ byte[] rawData = value.BinaryValue;
+ int prefixLength = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE + 1; // length + type + length
+ output.WriteRawLittleEndian32(prefixLength + rawData.Length); // length + type + value
+ output.WriteRawByte(PlainBufferConsts.VT_BLOB);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+ }
+ default:
+ throw new IOException("Bug: unsupported primary key type: " + value.GetType());
+ }
+ }
+
+ public static void WritePrimaryKeyColumn(Column column, PlainBufferOutputStream output, byte checksum)
+ {
+ output.WriteRawByte(PlainBufferConsts.TAG_CELL);
+ output.WriteRawByte(PlainBufferConsts.TAG_CELL_NAME);
+ byte[] rawData = column.GetNameRawData();
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ output.WriteRawByte(PlainBufferConsts.TAG_CELL_VALUE);
+ WritePrimaryKeyValue(column.Value, output);
+ output.WriteRawByte(PlainBufferConsts.TAG_CELL_CHECKSUM);
+ output.WriteRawByte(checksum);
+ }
+
+ public static byte[] BuildPrimaryKeyWithHeader(PrimaryKey primaryKey)
+ {
+ int size = ComputePrimaryKeyWithHeader(primaryKey);
+ PlainBufferOutputStream output = new PlainBufferOutputStream(size);
+ output.WriteRawLittleEndian32(PlainBufferConsts.HEADER);
+ output.WriteRawByte(PlainBufferConsts.TAG_ROW_PK);
+
+ byte rowChecksum = (byte)0x0, cellChecksum;
+
+ foreach (var key in primaryKey)
+ {
+ var column = new Column(key.Key, key.Value);
+ cellChecksum = PlainBufferCrc8.crc8((byte)0x0, column.GetNameRawData());
+ cellChecksum = column.Value.GetChecksum(cellChecksum);
+ WritePrimaryKeyColumn(column, output, cellChecksum);
+ rowChecksum = PlainBufferCrc8.crc8(rowChecksum, cellChecksum);
+ }
+
+ // 没有deleteMarker, 要与0x0做crc.
+ rowChecksum = PlainBufferCrc8.crc8(rowChecksum, (byte)0x0);
+
+ output.WriteRawByte(PlainBufferConsts.TAG_ROW_CHECKSUM);
+ output.WriteRawByte(rowChecksum);
+
+ if (!output.IsFull())
+ {
+ throw new IOException("Bug: serialize primary key failed.");
+ }
+
+ return output.GetBuffer();
+ }
+
+ public static byte[] BuildRowPutChangeWithHeader(RowPutChange rowChange)
+ {
+
+ List pkCells = new List();
+
+ if (rowChange.GetPrimaryKey() == null)
+ {
+ throw new ArgumentException("Primary Key is NULL");
+ }
+
+ foreach (PrimaryKeyColumn column in rowChange.GetPrimaryKey().GetPrimaryKeyColumns())
+ {
+ pkCells.Add(PlainBufferConversion.ToPlainBufferCell(column));
+ }
+
+ List cells = new List();
+ foreach (Column column in rowChange.GetColumnsToPut())
+ {
+ cells.Add(PlainBufferConversion.ToPlainBufferCell(column, false, false, false, (byte)0x0));
+ }
+
+ PlainBufferRow row = new PlainBufferRow(pkCells, cells, false);
+
+ int size = ComputePlainBufferRowWithHeader(row);
+ PlainBufferOutputStream output = new PlainBufferOutputStream(size);
+ PlainBufferCodedOutputStream codedOutput = new PlainBufferCodedOutputStream(output);
+ codedOutput.WriteRowWithHeader(row);
+ if (!output.IsFull())
+ {
+ throw new IOException("Bug: serialize row put change failed. Buffer remains " + output.Remain());
+ }
+
+ return output.GetBuffer();
+ }
+
+ public static byte[] BuildRowUpdateChangeWithHeader(RowUpdateChange rowChange)
+ {
+ List pkCells = new List();
+ foreach (var column in rowChange.GetPrimaryKey().GetPrimaryKeyColumns())
+ {
+ pkCells.Add(PlainBufferConversion.ToPlainBufferCell(column));
+ }
+
+ List cells = new List();
+ if (rowChange.GetColumnsToUpdate().Count > 0)
+ {
+ foreach (Tuple column in rowChange.GetColumnsToUpdate())
+ {
+ switch (column.Item2)
+ {
+ case RowChangeType.PUT:
+ cells.Add(PlainBufferConversion.ToPlainBufferCell(column.Item1, false, false, false, (byte)0x0));
+ break;
+ case RowChangeType.DELETE:
+ cells.Add(PlainBufferConversion.ToPlainBufferCell(column.Item1, true, false, true, PlainBufferConsts.DELETE_ONE_VERSION));
+ break;
+ case RowChangeType.DELETE_ALL:
+ cells.Add(PlainBufferConversion.ToPlainBufferCell(column.Item1, true, true, true, PlainBufferConsts.DELETE_ALL_VERSION));
+ break;
+ case RowChangeType.INCREMENT:
+ cells.Add(PlainBufferConversion.ToPlainBufferCell(column.Item1, false, true, true, PlainBufferConsts.INCREMENT));
+ break;
+ }
+ }
+ }
+
+ PlainBufferRow row = new PlainBufferRow(pkCells, cells, false);
+
+ int size = ComputePlainBufferRowWithHeader(row);
+ PlainBufferOutputStream output = new PlainBufferOutputStream(size);
+ PlainBufferCodedOutputStream codedOutput = new PlainBufferCodedOutputStream(output);
+ codedOutput.WriteRowWithHeader(row);
+
+ if (!output.IsFull())
+ {
+ throw new IOException("Bug: serialize row update change failed.");
+ }
+
+ return output.GetBuffer();
+ }
+
+ public static byte[] BuildRowDeleteChangeWithHeader(RowDeleteChange rowChange)
+ {
+ List pkCells = new List();
+ foreach (var primaryKeyColumn in rowChange.GetPrimaryKey().GetPrimaryKeyColumns())
+ {
+ pkCells.Add(PlainBufferConversion.ToPlainBufferCell(primaryKeyColumn));
+ }
+
+ List cells = new List();
+ PlainBufferRow row = new PlainBufferRow(pkCells, cells, true);
+
+ int size = ComputePlainBufferRowWithHeader(row);
+ PlainBufferOutputStream output = new PlainBufferOutputStream(size);
+ PlainBufferCodedOutputStream codedOutput = new PlainBufferCodedOutputStream(output);
+ codedOutput.WriteRowWithHeader(row);
+
+ if (!output.IsFull())
+ {
+ throw new IOException("Bug: serialize row delete change failed.");
+ }
+
+ return output.GetBuffer();
+ }
+ }
+}
\ No newline at end of file
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCell.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCell.cs
new file mode 100644
index 0000000..b15405e
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCell.cs
@@ -0,0 +1,218 @@
+using System;
+using Aliyun.OTS.DataModel;
+using System.IO;
+using Aliyun.OTS;
+using System.Text;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferCell
+ {
+
+ private String cellName;
+ private byte[] nameRawData;
+ private bool hasCellName;
+
+ private ColumnValue cellValue;
+ private bool hasCellValue;
+
+ private bool isPk;
+ private ColumnValue pkCellValue;
+
+ private byte cellType;
+ private bool hasCellType;
+
+ private long cellTimestamp;
+ private bool hasCellTimestamp;
+
+ private byte checksum;
+ private bool hasChecksum;
+
+ public String GetCellName()
+ {
+ return cellName;
+ }
+
+ public byte[] GetNameRawData()
+ {
+ if (nameRawData == null)
+ {
+ this.nameRawData = Encoding.UTF8.GetBytes(cellName);
+ }
+
+ return nameRawData;
+ }
+
+ public void SetCellName(String cellName)
+ {
+ this.cellName = cellName;
+ this.hasCellName = true;
+ this.nameRawData = null;
+ this.hasChecksum = false;
+ }
+
+ public bool HasCellName()
+ {
+ return this.hasCellName;
+ }
+
+ public ColumnValue GetCellValue()
+ {
+ return this.cellValue;
+ }
+
+ public void SetCellValue(ColumnValue cellValue)
+ {
+ this.cellValue = cellValue;
+ this.hasCellValue = true;
+ this.hasChecksum = false;
+ }
+
+ public bool HasCellValue()
+ {
+ return this.hasCellValue;
+ }
+
+ public byte GetCellType()
+ {
+ return this.cellType;
+ }
+
+ public void SetCellType(byte cellType)
+ {
+ this.cellType = cellType;
+ this.hasCellType = true;
+ this.hasChecksum = false;
+ }
+
+ public bool HasCellType()
+ {
+ return this.hasCellType;
+ }
+
+ public long GetCellTimestamp()
+ {
+ return this.cellTimestamp;
+ }
+
+ public void SetCellTimestamp(long cellTimestamp)
+ {
+ this.cellTimestamp = cellTimestamp;
+ this.hasCellTimestamp = true;
+ this.hasChecksum = false;
+ }
+
+ public bool HasCellTimestamp()
+ {
+ return hasCellTimestamp;
+ }
+
+ ///
+ /// 会自动计算当前的checksum并返回,当没有数据变化时,checksum会缓存在对象中,以减少不必要的计算。
+ ///
+ /// The checksum.
+ public byte GetChecksum()
+ {
+ if (!this.hasChecksum)
+ {
+ GenerateChecksum();
+ }
+
+ return this.checksum;
+ }
+
+ private void GenerateChecksum()
+ {
+ this.checksum = PlainBufferCrc8.GetChecksum((byte)0x0, this);
+ this.hasChecksum = true;
+ }
+
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+
+ public override bool Equals(Object obj)
+ {
+ if (obj == null || !(obj is PlainBufferCell))
+ {
+ return false;
+ }
+
+ try
+ {
+ if (GetChecksum() != ((PlainBufferCell)obj).GetChecksum())
+ {
+ return false;
+ }
+ }
+ catch (IOException e)
+ {
+ throw new OTSException("Error when getChecksum." + e.Message);
+ }
+
+ if ((HasCellName() != ((PlainBufferCell)obj).HasCellName())
+ || (HasCellName() && !GetCellName().Equals(((PlainBufferCell)obj).GetCellName())))
+ {
+ return false;
+ }
+
+ if ((HasCellValue() != ((PlainBufferCell)obj).HasCellValue())
+ || (HasCellValue() && !GetCellValue().Equals(((PlainBufferCell)obj).GetCellValue())))
+ {
+ return false;
+ }
+
+ if ((IsPk() != ((PlainBufferCell)obj).IsPk())
+ || (IsPk() && !GetPkCellValue().Equals(((PlainBufferCell)obj).GetPkCellValue())))
+ {
+ return false;
+ }
+
+ if ((HasCellType() != ((PlainBufferCell)obj).HasCellType())
+ || (HasCellType() && (GetCellType() != ((PlainBufferCell)obj).GetCellType())))
+ {
+ return false;
+ }
+
+ if ((HasCellTimestamp() != ((PlainBufferCell)obj).HasCellTimestamp())
+ || (HasCellTimestamp() && (GetCellTimestamp() != ((PlainBufferCell)obj).GetCellTimestamp())))
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ public override String ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("CellName: " + HasCellName() + "|" + cellName);
+ sb.Append(", CellValue: " + HasCellValue() + "|" + cellValue);
+ sb.Append(", CellType: " + HasCellType() + "|" + cellType);
+ sb.Append(", IsPk: " + IsPk() + "|" + GetPkCellValue());
+ sb.Append(", CellTimestamp: " + HasCellTimestamp() + "|" + cellTimestamp);
+ sb.Append(", Checksum: " + this.hasChecksum + "|" + checksum);
+ return sb.ToString();
+ }
+
+ public bool IsPk()
+ {
+ return isPk;
+ }
+
+ public ColumnValue GetPkCellValue()
+ {
+ return pkCellValue;
+ }
+
+ public void SetPkCellValue(ColumnValue pkCellValue)
+ {
+ this.pkCellValue = pkCellValue;
+ this.hasCellValue = true;
+ this.hasChecksum = false;
+ this.isPk = true;
+ }
+ }
+
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedInputStream.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedInputStream.cs
new file mode 100644
index 0000000..6ed584f
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedInputStream.cs
@@ -0,0 +1,352 @@
+using System.IO;
+using System.Collections.Generic;
+using Google.ProtocolBuffers;
+using Aliyun.OTS.DataModel;
+
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferCodedInputStream
+ {
+ private readonly CodedInputStream inputStream;
+ private uint lastTag = 0;
+
+ public PlainBufferCodedInputStream(CodedInputStream inputStream)
+ {
+ this.inputStream = inputStream;
+ }
+
+
+ public List ReadRowsWithHeader()
+ {
+ List rows = new List();
+ if (ReadHeader() != PlainBufferConsts.HEADER)
+ {
+ throw new IOException("Invalid header from plain buffer: " + this.inputStream);
+ }
+
+ ReadTag();
+ while (!this.inputStream.IsAtEnd)
+ {
+ PlainBufferRow row = ReadRow();
+ rows.Add(row);
+ }
+
+ if (!this.inputStream.IsAtEnd)
+ {
+ throw new IOException("");
+ }
+
+ return rows;
+ }
+
+ public uint ReadHeader()
+ {
+ return ReadUInt32();
+ }
+
+ public uint ReadTag()
+ {
+ if (this.inputStream.IsAtEnd)
+ {
+ lastTag = 0;
+ return 0;
+ }
+
+ lastTag = this.inputStream.ReadRawByte();
+ return lastTag;
+ }
+
+ public uint GetLastTag()
+ {
+ return this.lastTag;
+ }
+
+
+ public PlainBufferRow ReadRow()
+ {
+ List columns = new List();
+ List primaryKey = new List();
+ bool hasDeleteMarker = false;
+
+ if (CheckLastTagWas(PlainBufferConsts.TAG_ROW_PK))
+ {
+ primaryKey = ReadRowPK();
+ if (primaryKey.Count <= 0)
+ {
+ throw new IOException("The primary key of row is empty.");
+ }
+ }
+
+ if (CheckLastTagWas(PlainBufferConsts.TAG_ROW_DATA))
+ {
+ columns = ReadRowData();
+ }
+
+ if (CheckLastTagWas(PlainBufferConsts.TAG_DELETE_ROW_MARKER))
+ {
+ hasDeleteMarker = true;
+ ReadTag();
+ }
+
+ PlainBufferRow row = new PlainBufferRow(primaryKey, columns, hasDeleteMarker);
+
+ row.SetExtension(ReadExtension());
+
+ if (CheckLastTagWas(PlainBufferConsts.TAG_ROW_CHECKSUM))
+ {
+ byte checksum = this.inputStream.ReadRawByte();
+ ReadTag();
+ if (row.GetChecksum() != checksum)
+ {
+ throw new IOException("Checksum is mismatch.Row: " + row + ". Checksum: " + checksum + ". PlainBuffer: " + this.inputStream);
+ }
+ }
+ else
+ {
+ throw new IOException("Expect TAG_ROW_CHECKSUM but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ return row;
+ }
+
+ public bool CheckLastTagWas(uint tag)
+ {
+ return this.lastTag == tag;
+ }
+
+ public List ReadRowPK()
+ {
+ if (!CheckLastTagWas(PlainBufferConsts.TAG_ROW_PK))
+ {
+ throw new IOException("Expect TAG_ROW_PK but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ List primaryKeyColumns = new List();
+ ReadTag();
+ while (CheckLastTagWas(PlainBufferConsts.TAG_CELL))
+ {
+ PlainBufferCell cell = ReadCell();
+ primaryKeyColumns.Add(cell);
+ }
+
+ return primaryKeyColumns;
+ }
+
+ public PlainBufferCell ReadCell()
+ {
+ if (!CheckLastTagWas(PlainBufferConsts.TAG_CELL))
+ {
+ throw new IOException("Expect TAG_CELL but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ PlainBufferCell cell = new PlainBufferCell();
+
+ ReadTag();
+ if (GetLastTag() == PlainBufferConsts.TAG_CELL_NAME)
+ {
+ cell.SetCellName(ReadUTFString(ReadUInt32()));
+ ReadTag();
+ }
+
+ if (GetLastTag() == PlainBufferConsts.TAG_CELL_VALUE)
+ {
+ cell.SetCellValue(ReadCellValue());
+ }
+
+ if (GetLastTag() == PlainBufferConsts.TAG_CELL_TYPE)
+ {
+ cell.SetCellType(this.inputStream.ReadRawByte());
+ ReadTag();
+ }
+
+ if (GetLastTag() == PlainBufferConsts.TAG_CELL_TIMESTAMP)
+ {
+ long timestamp = (long)ReadInt64();
+ if (timestamp < 0)
+ {
+ throw new IOException("The timestamp is negative.");
+ }
+
+ cell.SetCellTimestamp(timestamp);
+ ReadTag(); // consume next tag as all read function should consume next tag
+ }
+
+ if (GetLastTag() == PlainBufferConsts.TAG_CELL_CHECKSUM)
+ {
+ byte checksum = this.inputStream.ReadRawByte();
+ ReadTag();
+ if (cell.GetChecksum() != checksum)
+ {
+ throw new IOException("Checksum is mismatch. Cell: " + cell + ". Checksum: " + checksum + ". PlainBuffer: " + this.inputStream);
+ }
+ }
+ else
+ {
+ throw new IOException("Expect TAG_CELL_CHECKSUM but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ return cell;
+ }
+
+ public List ReadRowData()
+ {
+ if (!CheckLastTagWas(PlainBufferConsts.TAG_ROW_DATA))
+ {
+ throw new IOException("Expect TAG_ROW_DATA but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ List columns = new List();
+ ReadTag();
+ while (CheckLastTagWas(PlainBufferConsts.TAG_CELL))
+ {
+ columns.Add(ReadCell());
+ }
+
+ return columns;
+ }
+
+ public PlainBufferExtension ReadExtension()
+ {
+ PlainBufferExtension extension = new PlainBufferExtension();
+ if (CheckLastTagWas(PlainBufferConsts.TAG_EXTENSION))
+ {
+ ReadUInt32(); // length
+ ReadTag();
+ while (PlainBufferConsts.IsTagInExtension(GetLastTag()))
+ {
+ if (CheckLastTagWas(PlainBufferConsts.TAG_SEQ_INFO))
+ {
+ extension.setSequenceInfo(ReadSequenceInfo());
+ }
+ else
+ {
+ int length = (int)this.inputStream.ReadRawLittleEndian32();
+ SkipRawSize(length);
+ ReadTag();
+ }
+ }
+ }
+
+ return extension;
+ }
+
+ public PlainBufferSequenceInfo ReadSequenceInfo()
+ {
+ if (!CheckLastTagWas(PlainBufferConsts.TAG_SEQ_INFO))
+ {
+ throw new IOException("Expect TAG_SEQ_INFO but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ this.inputStream.ReadRawLittleEndian32();// length
+ ReadTag();
+ PlainBufferSequenceInfo seq = new PlainBufferSequenceInfo();
+
+ if (CheckLastTagWas(PlainBufferConsts.TAG_SEQ_INFO_EPOCH))
+ {
+ seq.SetEpoch(ReadUInt32());
+ ReadTag();
+ }
+ else
+ {
+ throw new IOException("Expect TAG_SEQ_INFO_EPOCH but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ if (CheckLastTagWas(PlainBufferConsts.TAG_SEQ_INFO_TS))
+ {
+ seq.SetTimestamp((long)ReadInt64());
+ ReadTag();
+ }
+ else
+ {
+ throw new IOException("Expect TAG_SEQ_INFO_TS but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ if (CheckLastTagWas(PlainBufferConsts.TAG_SEQ_INFO_ROW_INDEX))
+ {
+ seq.SetRowIndex(ReadUInt32());
+ ReadTag();
+ }
+ else
+ {
+ throw new IOException("Expect TAG_SEQ_INFO_ROW_INDEX but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+
+ return seq;
+ }
+
+ public uint ReadUInt32()
+ {
+ return this.inputStream.ReadRawLittleEndian32();
+ }
+
+ public ulong ReadInt64()
+ {
+ return this.inputStream.ReadRawLittleEndian64();
+ }
+
+ public byte[] ReadBytes(uint size)
+ {
+ return this.inputStream.ReadRawBytes((int)size);
+ }
+
+
+ public string ReadUTFString(uint size)
+ {
+ return System.Text.Encoding.UTF8.GetString(ReadBytes(size));
+ }
+
+ public bool ReadBoolean()
+ {
+ bool result = false;
+ this.inputStream.ReadBool(ref result);
+ return result;
+ }
+
+ public double ReadDouble()
+ {
+ double result = 0;
+ this.inputStream.ReadDouble(ref result);
+ return result;
+ }
+
+ public void SkipRawSize(int length)
+ {
+ this.inputStream.SkipRawBytes(length);
+ }
+
+
+ public ColumnValue ReadCellValue()
+ {
+ if (!CheckLastTagWas(PlainBufferConsts.TAG_CELL_VALUE))
+ {
+ throw new IOException("Expect TAG_CELL_VALUE but it was " + PlainBufferConsts.PrintTag(GetLastTag()));
+ }
+ uint length = this.inputStream.ReadRawLittleEndian32();
+ byte type = this.inputStream.ReadRawByte();
+ ColumnValue columnValue = null;
+ switch (type)
+ {
+ case PlainBufferConsts.VT_INTEGER:
+ columnValue = new ColumnValue(ReadInt64());
+ break;
+ case PlainBufferConsts.VT_BLOB:
+ columnValue = new ColumnValue(ReadBytes(ReadUInt32()));
+ break;
+ case PlainBufferConsts.VT_STRING:
+ columnValue = new ColumnValue(ReadUTFString(ReadUInt32()));
+ break;
+ case PlainBufferConsts.VT_BOOLEAN:
+ columnValue = new ColumnValue(ReadBoolean());
+ break;
+ case PlainBufferConsts.VT_DOUBLE:
+ columnValue = new ColumnValue(ReadDouble());
+ break;
+ default:
+ throw new IOException("Unsupported column type: " + type);
+ }
+
+ ReadTag();
+ return columnValue;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedOutputStream.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedOutputStream.cs
new file mode 100644
index 0000000..541bc6f
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCodedOutputStream.cs
@@ -0,0 +1,287 @@
+using System.IO;
+using Aliyun.OTS.DataModel;
+
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferCodedOutputStream
+ {
+ private readonly PlainBufferOutputStream output;
+
+ public PlainBufferCodedOutputStream(PlainBufferOutputStream output)
+ {
+ this.output = output;
+ }
+
+ public void WriteHeader()
+ {
+ output.WriteRawLittleEndian32(PlainBufferConsts.HEADER);
+ }
+
+ public void WriteTag(byte tag)
+ {
+ output.WriteRawByte(tag);
+ }
+
+ public void WriteCellName(byte[] name)
+ {
+ WriteTag(PlainBufferConsts.TAG_CELL_NAME);
+ output.WriteRawLittleEndian32(name.Length);
+ output.WriteBytes(name);
+ }
+
+ public void WritePrimaryKeyValue(ColumnValue value)
+ {
+ if (value.CanBePrimaryKeyValue())
+ {
+ WriteCellValue(value);
+ }
+ else
+ {
+ throw new IOException("Bug: unsupported primary key type: " + value.GetType());
+ }
+ }
+
+ public void WriteCellValue(ColumnValue value)
+ {
+ WriteTag(PlainBufferConsts.TAG_CELL_VALUE);
+ if (value.IsInfMin())
+ {
+ output.WriteRawLittleEndian32(1);
+ output.WriteRawByte(PlainBufferConsts.VT_INF_MIN);
+ return;
+ }
+
+ if (value.IsInfMax())
+ {
+ output.WriteRawLittleEndian32(1);
+ output.WriteRawByte(PlainBufferConsts.VT_INF_MAX);
+ return;
+ }
+
+ if (value.IsPlaceHolderForAutoIncr())
+ {
+ output.WriteRawLittleEndian32(1);
+ output.WriteRawByte(PlainBufferConsts.VT_AUTO_INCREMENT);
+ return;
+ }
+
+ byte[] rawData;
+ int prefixLength;
+
+ switch (value.Type)
+ {
+ case ColumnValueType.String:
+ rawData = value.AsStringInBytes();
+ prefixLength = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE + 1; // length + type + length
+ output.WriteRawLittleEndian32(prefixLength + rawData.Length); // length + type + value
+ output.WriteRawByte(PlainBufferConsts.VT_STRING);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+ case ColumnValueType.Integer:
+ output.WriteRawLittleEndian32(1 + PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE);
+ output.WriteRawByte(PlainBufferConsts.VT_INTEGER);
+ output.WriteRawLittleEndian64(value.IntegerValue);
+ break;
+ case ColumnValueType.Binary:
+ rawData = value.BinaryValue;
+ prefixLength = PlainBufferOutputStream.LITTLE_ENDIAN_32_SIZE + 1; // length + type + length
+ output.WriteRawLittleEndian32(prefixLength + rawData.Length); // length + type + value
+ output.WriteRawByte(PlainBufferConsts.VT_BLOB);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+ case ColumnValueType.Boolean:
+ output.WriteRawLittleEndian32(2);
+ output.WriteRawByte(PlainBufferConsts.VT_BOOLEAN);
+ output.WriteBool(value.BooleanValue);
+ break;
+ case ColumnValueType.Double:
+ output.WriteRawLittleEndian32(1 + PlainBufferOutputStream.LITTLE_ENDIAN_64_SIZE);
+ output.WriteRawByte(PlainBufferConsts.VT_DOUBLE);
+ output.WriteDouble(value.DoubleValue);
+ break;
+ default:
+ throw new IOException("Bug: unsupported column type: " + value.Type);
+ }
+ }
+
+ public void WriteCell(PlainBufferCell cell)
+ {
+ WriteTag(PlainBufferConsts.TAG_CELL);
+
+ if (cell.HasCellName())
+ {
+ WriteCellName(cell.GetNameRawData());
+ }
+
+ if (cell.HasCellValue())
+ {
+ var columnValue = cell.IsPk() ? cell.GetPkCellValue() : cell.GetCellValue();
+ WriteCellValue(columnValue);
+ }
+
+ if (cell.HasCellType())
+ {
+ WriteTag(PlainBufferConsts.TAG_CELL_TYPE);
+ output.WriteRawByte(cell.GetCellType());
+ }
+
+ if (cell.HasCellTimestamp())
+ {
+ WriteTag(PlainBufferConsts.TAG_CELL_TIMESTAMP);
+ output.WriteRawLittleEndian64(cell.GetCellTimestamp());
+ }
+
+ WriteTag(PlainBufferConsts.TAG_CELL_CHECKSUM);
+ output.WriteRawByte(cell.GetChecksum());
+ }
+
+ public void WriteExtension(PlainBufferExtension extension)
+ {
+ WriteTag(PlainBufferConsts.TAG_EXTENSION);
+ output.WriteRawLittleEndian32(PlainBufferBuilder.ComputeSkipLengthForExtensionTag(extension));
+ int extensionCount = 0;
+ if (extension.HasSeq())
+ {
+ WriteSequenceInfo(extension.GetSequenceInfo());
+ extensionCount++;
+ }
+
+ if (extensionCount == 0)
+ {
+ throw new IOException("no extension tag is Writen.");
+ }
+ }
+
+ public void WriteSequenceInfo(PlainBufferSequenceInfo sequenceInfo)
+ {
+ WriteTag(PlainBufferConsts.TAG_SEQ_INFO);
+ output.WriteRawLittleEndian32(PlainBufferBuilder.ComputeSkipLengthForSequenceInfo());
+ WriteTag(PlainBufferConsts.TAG_SEQ_INFO_EPOCH);
+ output.WriteRawLittleEndian32((int)sequenceInfo.GetEpoch());
+ WriteTag(PlainBufferConsts.TAG_SEQ_INFO_TS);
+ output.WriteRawLittleEndian64(sequenceInfo.GetTimestamp());
+ WriteTag(PlainBufferConsts.TAG_SEQ_INFO_ROW_INDEX);
+ output.WriteRawLittleEndian32((int)sequenceInfo.GetRowIndex());
+ }
+
+ public void WriteRow(PlainBufferRow row)
+ {
+ WriteTag(PlainBufferConsts.TAG_ROW_PK);
+ foreach (PlainBufferCell cell in row.GetPrimaryKey())
+ {
+ WriteCell(cell);
+ }
+
+ if (row.GetCells().Count > 0)
+ {
+ WriteTag(PlainBufferConsts.TAG_ROW_DATA);
+ foreach (PlainBufferCell cell in row.GetCells())
+ {
+ WriteCell(cell);
+ }
+ }
+ if (row.HasDeleteMarker())
+ {
+ WriteTag(PlainBufferConsts.TAG_DELETE_ROW_MARKER);
+ }
+
+ if (row.HasExtension())
+ {
+ WriteExtension(row.GetExtension());
+ }
+
+ WriteTag(PlainBufferConsts.TAG_ROW_CHECKSUM);
+ output.WriteRawByte(row.GetChecksum());
+ }
+
+ public void WriteRowWithHeader(PlainBufferRow row)
+ {
+ WriteHeader();
+ WriteRow(row);
+ }
+
+ public void WritePrimaryKeyValueWithoutLengthPrefix(ColumnValue value)
+ {
+ if (value.IsInfMin())
+ {
+ output.WriteRawByte(PlainBufferConsts.VT_INF_MIN);
+ return;
+ }
+
+ if (value.IsInfMax())
+ {
+ output.WriteRawByte(PlainBufferConsts.VT_INF_MAX);
+ return;
+ }
+
+ if (value.IsPlaceHolderForAutoIncr())
+ {
+ output.WriteRawByte(PlainBufferConsts.VT_AUTO_INCREMENT);
+ return;
+ }
+
+ byte[] rawData;
+
+ switch (value.Type)
+ {
+ case ColumnValueType.String:
+ rawData = value.AsStringInBytes();
+ output.WriteRawByte(PlainBufferConsts.VT_STRING);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+ case ColumnValueType.Integer:
+ output.WriteRawByte(PlainBufferConsts.VT_INTEGER);
+ output.WriteRawLittleEndian64(value.IntegerValue);
+ break;
+ case ColumnValueType.Binary:
+ rawData = value.BinaryValue;
+ output.WriteRawByte(PlainBufferConsts.VT_BLOB);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+
+ default:
+ throw new IOException("Bug: unsupported primary key type: " + value.Type);
+ }
+ }
+
+
+ public void WriteColumnValueWithoutLengthPrefix(ColumnValue value)
+ {
+ byte[] rawData;
+ switch (value.Type)
+ {
+ case ColumnValueType.String:
+ rawData = value.AsStringInBytes();
+ output.WriteRawByte(PlainBufferConsts.VT_STRING);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+ case ColumnValueType.Integer:
+ output.WriteRawByte(PlainBufferConsts.VT_INTEGER);
+ output.WriteRawLittleEndian64(value.IntegerValue);
+ break;
+ case ColumnValueType.Binary:
+ rawData = value.BinaryValue;
+ output.WriteRawByte(PlainBufferConsts.VT_BLOB);
+ output.WriteRawLittleEndian32(rawData.Length);
+ output.WriteBytes(rawData);
+ break;
+
+ case ColumnValueType.Double:
+ output.WriteRawByte(PlainBufferConsts.VT_DOUBLE);
+ output.WriteDouble(value.DoubleValue);
+ break;
+ case ColumnValueType.Boolean:
+ output.WriteRawByte(PlainBufferConsts.VT_BOOLEAN);
+ output.WriteBool(value.BooleanValue);
+ break;
+ default:
+ throw new IOException("Bug: unsupported column type: " + value.Type);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConsts.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConsts.cs
new file mode 100644
index 0000000..1e54b52
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConsts.cs
@@ -0,0 +1,109 @@
+ namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public static class PlainBufferConsts
+ {
+ public const int HEADER = 0x75;
+
+ // tag type
+ public const byte TAG_ROW_PK = 0x1;
+ public const byte TAG_ROW_DATA = 0x2;
+ public const byte TAG_CELL = 0x3;
+ public const byte TAG_CELL_NAME = 0x4;
+ public const byte TAG_CELL_VALUE = 0x5;
+ public const byte TAG_CELL_TYPE = 0x6;
+ public const byte TAG_CELL_TIMESTAMP = 0x7;
+ public const byte TAG_DELETE_ROW_MARKER = 0x8;
+ public const byte TAG_ROW_CHECKSUM = 0x9;
+ public const byte TAG_CELL_CHECKSUM = 0x0A;
+ public const byte TAG_EXTENSION = 0x0B;
+ public const byte TAG_SEQ_INFO = 0x0C;
+ public const byte TAG_SEQ_INFO_EPOCH = 0x0D;
+ public const byte TAG_SEQ_INFO_TS = 0x0E;
+ public const byte TAG_SEQ_INFO_ROW_INDEX = 0x0F;
+
+ // cell op type
+ public const byte DELETE_ALL_VERSION = 0x1;
+ public const byte DELETE_ONE_VERSION = 0x3;
+ public const byte INCREMENT = 0x4;
+
+ // variant type
+ public const byte VT_INTEGER = 0x0;
+ public const byte VT_DOUBLE = 0x1;
+ public const byte VT_BOOLEAN = 0x2;
+ public const byte VT_STRING = 0x3;
+ //public const byte VT_NULL = 0x6;
+ public const byte VT_BLOB = 0x7;
+ public const byte VT_INF_MIN = 0x9;
+ public const byte VT_INF_MAX = 0xa;
+ public const byte VT_AUTO_INCREMENT = 0xb;
+
+ public static string PrintTag(uint tag)
+ {
+ switch (tag)
+ {
+ case TAG_ROW_PK:
+ return "TAG_ROW_PK";
+ case TAG_ROW_DATA:
+ return "TAG_ROW_DATA";
+ case TAG_CELL:
+ return "TAG_CELL";
+ case TAG_CELL_NAME:
+ return "TAG_CELL_NAME";
+ case TAG_CELL_VALUE:
+ return "TAG_CELL_VALUE";
+ case TAG_CELL_TYPE:
+ return "TAG_CELL_TYPE";
+ case TAG_CELL_TIMESTAMP:
+ return "TAG_CELL_TIMESTAMP";
+ case TAG_DELETE_ROW_MARKER:
+ return "TAG_DELETE_ROW_MARKER";
+ case TAG_ROW_CHECKSUM:
+ return "TAG_ROW_CHECKSUM";
+ case TAG_CELL_CHECKSUM:
+ return "TAG_CELL_CHECKSUM";
+ case TAG_SEQ_INFO:
+ return "TAG_SEQ_INFO";
+ case TAG_SEQ_INFO_EPOCH:
+ return "TAG_SEQ_INFO_EPOCH";
+ case TAG_SEQ_INFO_TS:
+ return "TAG_SEQ_INFO_TS";
+ case TAG_SEQ_INFO_ROW_INDEX:
+ return "TAG_SEQ_INFO_ROW_INDEX";
+ case TAG_EXTENSION:
+ return "TAG_EXTENSION";
+ default:
+ return "UNKNOWN_TAG(" + tag + ")";
+ }
+ }
+
+ public static bool IsUnknownTag(uint tag)
+ {
+ switch (tag)
+ {
+ case TAG_ROW_PK:
+ case TAG_ROW_DATA:
+ case TAG_CELL:
+ case TAG_CELL_NAME:
+ case TAG_CELL_VALUE:
+ case TAG_CELL_TYPE:
+ case TAG_CELL_TIMESTAMP:
+ case TAG_DELETE_ROW_MARKER:
+ case TAG_ROW_CHECKSUM:
+ case TAG_CELL_CHECKSUM:
+ case TAG_SEQ_INFO:
+ case TAG_SEQ_INFO_EPOCH:
+ case TAG_SEQ_INFO_TS:
+ case TAG_SEQ_INFO_ROW_INDEX:
+ case TAG_EXTENSION:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ public static bool IsTagInExtension(uint tag)
+ {
+ return tag == TAG_SEQ_INFO || IsUnknownTag(tag);
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConversion.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConversion.cs
new file mode 100644
index 0000000..17b65c9
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferConversion.cs
@@ -0,0 +1,95 @@
+using System.Collections.Generic;
+using System.IO;
+using Aliyun.OTS.DataModel;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public static class PlainBufferConversion
+ {
+ public static IRow ToRow(PlainBufferRow plainBufferRow)
+ {
+ if (plainBufferRow.HasDeleteMarker())
+ {
+ throw new IOException("Row could not has delete marker: " + plainBufferRow);
+ }
+
+ if (plainBufferRow.GetPrimaryKey() == null)
+ {
+ throw new IOException("Row has no primary key: " + plainBufferRow);
+ }
+
+ List columns = new List(plainBufferRow.GetCells().Count);
+
+ foreach (PlainBufferCell cell in plainBufferRow.GetCells())
+ {
+ columns.Add(ToColumn(cell));
+ }
+
+ return new Row(ToPrimaryKey(plainBufferRow.GetPrimaryKey()), columns);
+ }
+
+ public static Column ToColumn(PlainBufferCell cell)
+ {
+ if (!cell.HasCellName() || !cell.HasCellValue())
+ {
+ throw new IOException("The cell has no name or value: " + cell);
+ }
+
+ if (cell.HasCellType() && cell.GetCellType() != PlainBufferConsts.INCREMENT)
+ {
+ throw new IOException("The cell should not has type: " + cell);
+ }
+
+ if (cell.HasCellTimestamp())
+ {
+ return new Column(cell.GetCellName(), cell.GetCellValue(), cell.GetCellTimestamp());
+ }
+ else
+ {
+ return new Column(cell.GetCellName(), cell.GetCellValue());
+ }
+ }
+
+ public static PrimaryKey ToPrimaryKey(List pkCells)
+ {
+ var primaryKey = new PrimaryKey();
+ foreach (PlainBufferCell cell in pkCells)
+ {
+ primaryKey.Add(cell.GetCellName(), cell.GetCellValue());
+ }
+
+ return primaryKey;
+ }
+
+ public static PlainBufferCell ToPlainBufferCell(PrimaryKeyColumn primaryKeyColumn)
+ {
+ PlainBufferCell cell = new PlainBufferCell();
+ cell.SetCellName(primaryKeyColumn.Name);
+ cell.SetPkCellValue(primaryKeyColumn.Value);
+ return cell;
+ }
+
+ public static PlainBufferCell ToPlainBufferCell(Column column, bool ignoreValue, bool ignoreTs,
+ bool setType, byte type)
+ {
+ PlainBufferCell cell = new PlainBufferCell();
+ cell.SetCellName(column.Name);
+ if (!ignoreValue)
+ {
+ cell.SetCellValue(column.Value);
+ }
+ if (!ignoreTs)
+ {
+ if (column.Timestamp.HasValue)
+ {
+ cell.SetCellTimestamp(column.Timestamp.Value);
+ }
+ }
+ if (setType)
+ {
+ cell.SetCellType(type);
+ }
+
+ return cell;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCrc8.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCrc8.cs
new file mode 100644
index 0000000..e5f8013
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferCrc8.cs
@@ -0,0 +1,113 @@
+using System;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public static class PlainBufferCrc8
+ {
+ private const int spaceSize = 256;
+ private static byte[] crc8Table = new byte[spaceSize];
+
+ static PlainBufferCrc8()
+ {
+ for (int i = 0; i < crc8Table.Length; ++i)
+ {
+ byte x = (byte)i;
+ for (int j = 8; j > 0; --j)
+ {
+ x = (byte)((x << 1) ^ (((x & 0x80) != 0) ? 0x07 : 0));
+ }
+ crc8Table[i] = x;
+ }
+ }
+
+ public static byte crc8(byte crc, byte data)
+ {
+ crc = crc8Table[(crc ^ data) & 0xff];
+ return crc;
+ }
+
+ public static byte crc8(byte crc, int data)
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ crc = crc8(crc, (byte)(data & 0xff));
+ data >>= 8;
+ }
+
+ return crc;
+ }
+
+ public static byte crc8(byte crc, long data)
+ {
+ for (int i = 0; i < 8; i++)
+ {
+ crc = crc8(crc, (byte)(data & 0xff));
+ data >>= 8;
+ }
+ return crc;
+ }
+
+ public static byte crc8(byte crc, byte[] data)
+ {
+ for (int i = 0; i < data.Length; i++)
+ {
+ crc = crc8(crc, data[i]);
+ }
+ return crc;
+ }
+
+ public static byte GetChecksum(byte crc, PlainBufferCell cell)
+ {
+
+ if (cell.HasCellName())
+ {
+ crc = crc8(crc, cell.GetNameRawData());
+ }
+
+ if (cell.HasCellValue())
+ {
+ if (cell.IsPk())
+ {
+ crc = cell.GetPkCellValue().GetChecksum(crc);
+ }
+ else
+ {
+ crc = cell.GetCellValue().GetChecksum(crc);
+ }
+ }
+
+ if (cell.HasCellTimestamp())
+ {
+ crc = crc8(crc, cell.GetCellTimestamp());
+ }
+
+ if (cell.HasCellType())
+ {
+ crc = crc8(crc, cell.GetCellType());
+ }
+
+ return crc;
+ }
+
+ public static byte GetChecksum(byte crc, PlainBufferRow row)
+ {
+ foreach (PlainBufferCell cell in row.GetPrimaryKey())
+ {
+ crc = crc8(crc, cell.GetChecksum());
+ }
+
+ foreach (PlainBufferCell cell in row.GetCells())
+ {
+ crc = crc8(crc, cell.GetChecksum());
+ }
+
+ byte del = 0;
+ if (row.HasDeleteMarker())
+ {
+ del = (byte)0x1;
+ }
+ crc = crc8(crc, del);
+
+ return crc;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferExtension.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferExtension.cs
new file mode 100644
index 0000000..a7ffc74
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferExtension.cs
@@ -0,0 +1,40 @@
+using System;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferExtension
+ {
+ private PlainBufferSequenceInfo sequenceInfo;
+
+
+ public PlainBufferExtension()
+ {
+ this.sequenceInfo = new PlainBufferSequenceInfo();
+ }
+ public void setSequenceInfo(PlainBufferSequenceInfo sequenceInfo)
+ {
+ this.sequenceInfo = sequenceInfo;
+ }
+
+ public PlainBufferSequenceInfo GetSequenceInfo()
+ {
+ return sequenceInfo;
+ }
+
+ public bool HasSeq()
+ {
+ return sequenceInfo.GetHasSeq();
+ }
+
+ public override String ToString()
+ {
+
+ String str = "";
+ if (HasSeq())
+ {
+ str += " SequenceInfo: {" + GetSequenceInfo() + "}";
+ }
+
+ return str;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferInputStream.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferInputStream.cs
new file mode 100644
index 0000000..6749d88
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferInputStream.cs
@@ -0,0 +1,138 @@
+using System;
+using System.IO;
+using Aliyun.OTS.Util;
+
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferInputStream
+ {
+ private readonly MemoryStream buffer;
+ private int lastTag;
+
+ public PlainBufferInputStream(MemoryStream buffer)
+ {
+ this.buffer = buffer;
+ this.lastTag = 0;
+ }
+
+ public PlainBufferInputStream(byte[] byteBuffer)
+ {
+ var ms = new MemoryStream();
+ ms.SetLength(byteBuffer.Length);
+ ms.Write(byteBuffer, 0, byteBuffer.Length);
+ this.buffer = ms;
+ this.lastTag = 0;
+ }
+
+ public bool IsAtEnd()
+ {
+ return buffer.Position == buffer.Length;
+ }
+
+ public int ReadTag()
+ {
+ if (IsAtEnd())
+ {
+ lastTag = 0;
+ return 0;
+ }
+
+ lastTag = ReadRawByte();
+ return lastTag;
+ }
+
+ public bool CheckLastTagWas(int tag)
+ {
+ return lastTag == tag;
+ }
+
+ public int GetLastTag()
+ {
+ return lastTag;
+ }
+
+ public byte ReadRawByte()
+ {
+ if (IsAtEnd())
+ {
+ throw new IOException("Read raw byte encountered EOF.");
+ }
+
+ return (byte)buffer.ReadByte();
+ }
+
+ public long ReadRawLittleEndian64()
+ {
+ byte b1 = ReadRawByte();
+ byte b2 = ReadRawByte();
+ byte b3 = ReadRawByte();
+ byte b4 = ReadRawByte();
+ byte b5 = ReadRawByte();
+ byte b6 = ReadRawByte();
+ byte b7 = ReadRawByte();
+ byte b8 = ReadRawByte();
+ return (((long)b1 & 0xff)) |
+ (((long)b2 & 0xff) << 8) |
+ (((long)b3 & 0xff) << 16) |
+ (((long)b4 & 0xff) << 24) |
+ (((long)b5 & 0xff) << 32) |
+ (((long)b6 & 0xff) << 40) |
+ (((long)b7 & 0xff) << 48) |
+ (((long)b8 & 0xff) << 56);
+ }
+
+ public int ReadRawLittleEndian32()
+ {
+ byte b1 = ReadRawByte();
+ byte b2 = ReadRawByte();
+ byte b3 = ReadRawByte();
+ byte b4 = ReadRawByte();
+ return (((int)b1 & 0xff)) |
+ (((int)b2 & 0xff) << 8) |
+ (((int)b3 & 0xff) << 16) |
+ (((int)b4 & 0xff) << 24);
+ }
+
+ public bool ReadBoolean()
+ {
+ return ReadRawByte() != 0;
+ }
+
+ public double ReadDouble()
+ {
+ return BitConverter.Int64BitsToDouble(ReadRawLittleEndian64());
+ }
+
+ public int ReadUInt32()
+ {
+ return ReadRawLittleEndian32();
+ }
+
+ public long ReadInt64()
+ {
+ return ReadRawLittleEndian64();
+ }
+
+ public byte[] ReadBytes(int size)
+ {
+ if (buffer.Length - buffer.Position < size)
+ {
+ throw new IOException("Read bytes encountered EOF.");
+ }
+
+ byte[] result = new byte[size];
+ buffer.Read(result, 0, size);
+ return result;
+ }
+
+ public string ReadUTFString(int size)
+ {
+ return OtsUtils.Bytes2UTF8String(ReadBytes(size));
+ }
+
+ public override string ToString()
+ {
+ return OtsUtils.Bytes2UTF8String(this.buffer.GetBuffer());
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferOutputStream.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferOutputStream.cs
new file mode 100644
index 0000000..f4a82c9
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferOutputStream.cs
@@ -0,0 +1,110 @@
+using System.Diagnostics.Contracts;
+using System.IO;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferOutputStream
+ {
+ private readonly byte[] buffer;
+ private readonly int capacity;
+ private int pos;
+
+ public PlainBufferOutputStream(int capacity)
+ {
+ Contract.Requires(capacity > 0);
+ buffer = new byte[capacity];
+ this.capacity = capacity;
+ }
+
+ public byte[] GetBuffer()
+ {
+ return buffer;
+ }
+
+ public bool IsFull()
+ {
+ return pos == capacity;
+ }
+
+ public int Count()
+ {
+ return pos;
+ }
+
+ public int Remain()
+ {
+ return capacity - pos;
+ }
+
+ public void Clear()
+ {
+ this.pos = 0;
+ }
+
+ public void WriteRawByte(byte value)
+ {
+ if (pos == capacity)
+ {
+ throw new IOException("The buffer is full.");
+ }
+
+ buffer[pos++] = value;
+ }
+
+ public void WriteRawByte(int value)
+ {
+ WriteRawByte((byte)value);
+ }
+
+ ///
+ /// Write a little-endian 32-bit integer.
+ ///
+ /// Value.
+ public void WriteRawLittleEndian32(int value)
+ {
+ WriteRawByte((value) & 0xFF);
+ WriteRawByte((value >> 8) & 0xFF);
+ WriteRawByte((value >> 16) & 0xFF);
+ WriteRawByte((value >> 24) & 0xFF);
+ }
+
+ ///
+ /// Write a little-endian 64-bit integer.
+ ///
+ /// Value.
+ public void WriteRawLittleEndian64(long value)
+ {
+ WriteRawByte((int)(value) & 0xFF);
+ WriteRawByte((int)(value >> 8) & 0xFF);
+ WriteRawByte((int)(value >> 16) & 0xFF);
+ WriteRawByte((int)(value >> 24) & 0xFF);
+ WriteRawByte((int)(value >> 32) & 0xFF);
+ WriteRawByte((int)(value >> 40) & 0xFF);
+ WriteRawByte((int)(value >> 48) & 0xFF);
+ WriteRawByte((int)(value >> 56) & 0xFF);
+ }
+
+ public void WriteDouble(double value)
+ {
+ WriteRawLittleEndian64(System.BitConverter.DoubleToInt64Bits(value));
+ }
+
+ public void WriteBool(bool value)
+ {
+ WriteRawByte(value ? 1 : 0);
+ }
+
+ public void WriteBytes(byte[] bytes)
+ {
+ if (this.pos + bytes.Length > this.capacity)
+ {
+ throw new IOException("The buffer is full.");
+ }
+
+ System.Array.Copy(bytes, 0, this.buffer, this.pos, bytes.Length);
+ this.pos += bytes.Length;
+ }
+
+ public const int LITTLE_ENDIAN_32_SIZE = 4;
+ public const int LITTLE_ENDIAN_64_SIZE = 8;
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferRow.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferRow.cs
new file mode 100644
index 0000000..9a38d45
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferRow.cs
@@ -0,0 +1,121 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferRow
+ {
+ private List primaryKey;
+
+ private readonly List cells;
+
+ private bool hasDeleteMarker = false;
+
+ private byte checksum;
+ private bool hasChecksum = false;
+ private PlainBufferExtension extension;
+
+ public PlainBufferRow(List primaryKey, List cells, bool hasDeleteMarker)
+ {
+ this.primaryKey = primaryKey;
+ this.cells = cells;
+ this.hasDeleteMarker = hasDeleteMarker;
+ this.extension = new PlainBufferExtension();
+ }
+
+ public List GetPrimaryKey()
+ {
+ return primaryKey;
+ }
+
+ public void SetPrimaryKey(List primaryKey)
+ {
+ this.primaryKey = primaryKey;
+ this.hasChecksum = false;
+ }
+
+ public List GetCells()
+ {
+ return cells;
+ }
+
+ public void AddCell(PlainBufferCell cell)
+ {
+ this.cells.Add(cell);
+ this.hasChecksum = false;
+ }
+
+ public bool HasCells()
+ {
+ return this.cells.Count > 0;
+ }
+
+ public bool HasDeleteMarker()
+ {
+ return hasDeleteMarker;
+ }
+
+ public void SetHasDeleteMarker(bool hasDeleteMarker)
+ {
+ this.hasDeleteMarker = hasDeleteMarker;
+ this.hasChecksum = false;
+ }
+
+ public PlainBufferExtension GetExtension()
+ {
+ return extension;
+ }
+
+ public void SetExtension(PlainBufferExtension extension)
+ {
+ this.extension = extension;
+ }
+
+ public bool HasExtension()
+ {
+ return extension.HasSeq();
+ }
+
+ ///
+ /// 会自动计算当前的checksum并返回,当没有数据变化时,checksum会缓存在对象中,以减少不必要的计算。
+ ///
+ /// The checksum.
+ public byte GetChecksum()
+ {
+ if (!this.hasChecksum)
+ {
+ GenerateChecksum();
+ }
+ return this.checksum;
+ }
+
+ private void GenerateChecksum()
+ {
+ this.checksum = PlainBufferCrc8.GetChecksum((byte)0x0, this);
+ this.hasChecksum = true;
+ }
+
+
+ public override string ToString()
+ {
+ StringBuilder sb = new StringBuilder();
+ sb.Append("PrimaryKey: ").Append(primaryKey);
+ sb.Append("Cells: ");
+ foreach (PlainBufferCell cell in cells)
+ {
+ sb.Append("[").Append(cell).Append("]");
+ }
+
+ sb.Append(" HasDeleteMarker: " + HasDeleteMarker());
+
+ if (HasExtension())
+ {
+ sb.Append(" Extension: {");
+ sb.Append(GetExtension());
+ sb.Append("}");
+ }
+ return sb.ToString();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferSequenceInfo.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferSequenceInfo.cs
new file mode 100644
index 0000000..c2fdc66
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/PlainBufferSequenceInfo.cs
@@ -0,0 +1,53 @@
+using System;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class PlainBufferSequenceInfo
+ {
+ private uint epoch = 0;
+ private long timestamp = 0;
+ private uint rowIndex = 0;
+ private bool hasSeq = false;
+
+ public uint GetEpoch()
+ {
+ return epoch;
+ }
+
+ public void SetEpoch(uint epoch)
+ {
+ this.epoch = epoch;
+ this.hasSeq = true;
+ }
+ public long GetTimestamp()
+ {
+ return timestamp;
+ }
+
+ public void SetTimestamp(long timestamp)
+ {
+ this.timestamp = timestamp;
+ this.hasSeq = true;
+ }
+
+ public uint GetRowIndex()
+ {
+ return rowIndex;
+ }
+
+ public void SetRowIndex(uint rowIndex)
+ {
+ this.rowIndex = rowIndex;
+ this.hasSeq = true;
+ }
+
+ public bool GetHasSeq()
+ {
+ return hasSeq;
+ }
+
+ public override String ToString()
+ {
+ return "Epoch: " + epoch + ", Timestamp: " + timestamp + ", RowIndex: " + rowIndex;
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/ProtocolBufferParser.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/ProtocolBufferParser.cs
new file mode 100644
index 0000000..b6b8930
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/ProtocolBufferParser.cs
@@ -0,0 +1,11 @@
+using System;
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class ProtocolBufferParse: IResultParser
+ {
+ public object getObject(GetRowRequest response)
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchQueryBuilder.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchQueryBuilder.cs
new file mode 100644
index 0000000..ae920df
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchQueryBuilder.cs
@@ -0,0 +1,268 @@
+using System;
+using Aliyun.OTS.DataModel.Search.Query;
+using Aliyun.OTS.ProtoBuffer;
+using Google.ProtocolBuffers;
+
+namespace com.alicloud.openservices.tablestore.core.protocol
+{
+ public class SearchQueryBuilder
+ {
+ public static QueryType BuildQueryType(Aliyun.OTS.DataModel.Search.Query.QueryType type)
+ {
+ switch (type)
+ {
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_MatchQuery:
+ return QueryType.MATCH_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_MatchPhraseQuery:
+ return QueryType.MATCH_PHRASE_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_TermQuery:
+ return QueryType.TERM_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_TermsQuery:
+ return QueryType.TERMS_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_RangeQuery:
+ return QueryType.RANGE_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_PrefixQuery:
+ return QueryType.PREFIX_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_BoolQuery:
+ return QueryType.BOOL_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_ConstScoreQuery:
+ return QueryType.CONST_SCORE_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_FunctionScoreQuery:
+ return QueryType.FUNCTION_SCORE_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_NestedQuery:
+ return QueryType.NESTED_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_WildcardQuery:
+ return QueryType.WILDCARD_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_MatchAllQuery:
+ return QueryType.MATCH_ALL_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_GeoBoundingBoxQuery:
+ return QueryType.GEO_BOUNDING_BOX_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_GeoDistanceQuery:
+ return QueryType.GEO_DISTANCE_QUERY;
+ case Aliyun.OTS.DataModel.Search.Query.QueryType.QueryType_GeoPolygonQuery:
+ return QueryType.GEO_POLYGON_QUERY;
+ default:
+ throw new ArgumentException("unknown queryType: " + type.ToString());
+ }
+ }
+
+ public static Query BuildQuery(IQuery query)
+ {
+ Query.Builder builder = Query.CreateBuilder();
+ builder.SetType(BuildQueryType(query.GetQueryType()));
+ builder.SetQuery_(query.Serialize());
+ return builder.Build();
+ }
+
+ public static MatchAllQuery BuildMatchAllQuery()
+ {
+ MatchAllQuery.Builder builder = MatchAllQuery.CreateBuilder();
+ return builder.Build();
+ }
+
+ public static MatchQuery BuildMatchQuery(Aliyun.OTS.DataModel.Search.Query.MatchQuery query)
+ {
+ MatchQuery.Builder builder = MatchQuery.CreateBuilder();
+
+ builder.SetFieldName(query.FieldName);
+ builder.SetText(query.Text);
+ if (query.MinimumShouldMatch != null)
+ {
+ builder.SetMinimumShouldMatch(query.MinimumShouldMatch.Value);
+ }
+ switch (query.Operator)
+ {
+ case Aliyun.OTS.DataModel.Search.Query.QueryOperator.AND:
+ builder.SetOperator(QueryOperator.AND);
+ break;
+ case Aliyun.OTS.DataModel.Search.Query.QueryOperator.OR:
+ builder.SetOperator(QueryOperator.OR);
+ break;
+ default:
+ throw new ArgumentException("unsupported operator:" + query.Operator);
+
+ }
+
+ return builder.Build();
+ }
+
+ public static MatchPhraseQuery BuildMatchPhraseQuery(Aliyun.OTS.DataModel.Search.Query.MatchPhraseQuery query)
+ {
+ MatchPhraseQuery.Builder builder = MatchPhraseQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ builder.SetText(query.Text);
+ return builder.Build();
+ }
+
+ public static TermQuery BuildTermQuery(Aliyun.OTS.DataModel.Search.Query.TermQuery query)
+ {
+ TermQuery.Builder builder = TermQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ builder.SetTerm(ByteString.CopyFrom(SearchVariantType.toVariant(query.Term)));
+ return builder.Build();
+ }
+
+ public static TermsQuery BuildTermsQuery(Aliyun.OTS.DataModel.Search.Query.TermsQuery query)
+ {
+ TermsQuery.Builder builder = TermsQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ if (query.Terms == null)
+ {
+ throw new ArgumentException("terms is null");
+ }
+ foreach (var item in query.Terms)
+ {
+ builder.AddTerms(ByteString.CopyFrom(SearchVariantType.toVariant(item)));
+ }
+ return builder.Build();
+ }
+
+ public static RangeQuery BuildRangeQuery(Aliyun.OTS.DataModel.Search.Query.RangeQuery query)
+ {
+ RangeQuery.Builder builder = RangeQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ if (query.From != null)
+ {
+ builder.SetRangeFrom(ByteString.CopyFrom(SearchVariantType.toVariant(query.From)));
+ builder.SetIncludeLower(query.IncludeLower);
+ }
+ if (query.To != null)
+ {
+ builder.SetRangeTo(ByteString.CopyFrom(SearchVariantType.toVariant(query.To)));
+ builder.SetIncludeUpper(query.IncludeUpper);
+ }
+ return builder.Build();
+ }
+
+ public static PrefixQuery BuildPrefixQuery(Aliyun.OTS.DataModel.Search.Query.PrefixQuery query)
+ {
+ PrefixQuery.Builder builder = PrefixQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ builder.SetPrefix(query.Prefix);
+ return builder.Build();
+ }
+
+ public static WildcardQuery BuildWildcardQuery(Aliyun.OTS.DataModel.Search.Query.WildcardQuery query)
+ {
+ WildcardQuery.Builder builder = WildcardQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ builder.SetValue(query.Value);
+ return builder.Build();
+ }
+
+ public static BoolQuery BuildBoolQuery(Aliyun.OTS.DataModel.Search.Query.BoolQuery query)
+ {
+ BoolQuery.Builder builder = BoolQuery.CreateBuilder();
+ if (query.MinimumShouldMatch != null)
+ {
+ builder.SetMinimumShouldMatch(query.MinimumShouldMatch.Value);
+ }
+ if (query.MustQueries != null)
+ {
+ foreach (var q in query.MustQueries)
+ {
+ builder.AddMustQueries(BuildQuery(q));
+ }
+ }
+ if (query.MustNotQueries != null)
+ {
+ foreach (var q in query.MustNotQueries)
+ {
+ builder.AddMustNotQueries(BuildQuery(q));
+ }
+ }
+ if (query.ShouldQueries != null)
+ {
+ foreach (var q in query.ShouldQueries)
+ {
+ builder.AddShouldQueries(BuildQuery(q));
+ }
+ }
+ if (query.FilterQueries != null)
+ {
+ foreach (var q in query.FilterQueries)
+ {
+ builder.AddFilterQueries(BuildQuery(q));
+ }
+ }
+ return builder.Build();
+ }
+
+ public static ConstScoreQuery BuildConstScoreQuery(Aliyun.OTS.DataModel.Search.Query.ConstScoreQuery query)
+ {
+
+ ConstScoreQuery.Builder builder = ConstScoreQuery.CreateBuilder();
+ builder.SetFilter(SearchQueryBuilder.BuildQuery(query.Filter));
+ return builder.Build();
+ }
+
+ public static FieldValueFactor BuildFieldValueFactor(Aliyun.OTS.DataModel.Search.Query.FieldValueFactor fieldValueFactor)
+ {
+ FieldValueFactor.Builder builder = FieldValueFactor.CreateBuilder();
+ builder.SetFieldName(fieldValueFactor.FieldName);
+ return builder.Build();
+ }
+
+ public static FunctionScoreQuery BuildFunctionScoreQuery(Aliyun.OTS.DataModel.Search.Query.FunctionScoreQuery query)
+ {
+ FunctionScoreQuery.Builder builder = FunctionScoreQuery.CreateBuilder();
+ builder.SetQuery(SearchQueryBuilder.BuildQuery(query.Query));
+ builder.SetFieldValueFactor(BuildFieldValueFactor(query.FieldValueFactor));
+ return builder.Build();
+ }
+
+ public static ScoreMode BuildScoreMode(Aliyun.OTS.DataModel.Search.Query.ScoreMode scoreMode)
+ {
+ switch (scoreMode)
+ {
+ case Aliyun.OTS.DataModel.Search.Query.ScoreMode.Max:
+ return ScoreMode.SCORE_MODE_MAX;
+ case Aliyun.OTS.DataModel.Search.Query.ScoreMode.Min:
+ return ScoreMode.SCORE_MODE_MIN;
+ case Aliyun.OTS.DataModel.Search.Query.ScoreMode.Avg:
+ return ScoreMode.SCORE_MODE_AVG;
+ case Aliyun.OTS.DataModel.Search.Query.ScoreMode.Total:
+ return ScoreMode.SCORE_MODE_TOTAL;
+ case Aliyun.OTS.DataModel.Search.Query.ScoreMode.None:
+ return ScoreMode.SCORE_MODE_NONE;
+ default:
+ throw new ArgumentException("unknown scoreMode: " + scoreMode.ToString());
+ }
+ }
+
+ public static NestedQuery BuildNestedQuery(Aliyun.OTS.DataModel.Search.Query.NestedQuery query)
+ {
+ NestedQuery.Builder builder = NestedQuery.CreateBuilder();
+ builder.SetQuery(SearchQueryBuilder.BuildQuery(query.Query));
+ builder.SetPath(query.Path);
+ builder.SetScoreMode(BuildScoreMode(query.ScoreMode));
+ return builder.Build();
+ }
+
+ public static GeoBoundingBoxQuery BuildGeoBoundingBoxQuery(Aliyun.OTS.DataModel.Search.Query.GeoBoundingBoxQuery query)
+ {
+ GeoBoundingBoxQuery.Builder builder = GeoBoundingBoxQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ builder.SetTopLeft(query.TopLeft);
+ builder.SetBottomRight(query.BottomRight);
+ return builder.Build();
+ }
+
+ public static GeoDistanceQuery BuildGeoDistanceQuery(Aliyun.OTS.DataModel.Search.Query.GeoDistanceQuery query)
+ {
+ GeoDistanceQuery.Builder builder = GeoDistanceQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ builder.SetCenterPoint(query.CenterPoint);
+ builder.SetDistance(query.DistanceInMeter);
+ return builder.Build();
+ }
+
+ public static GeoPolygonQuery BuildGeoPolygonQuery(Aliyun.OTS.DataModel.Search.Query.GeoPolygonQuery query)
+ {
+ GeoPolygonQuery.Builder builder = GeoPolygonQuery.CreateBuilder();
+ builder.SetFieldName(query.FieldName);
+ builder.AddRangePoints(query.Points);
+ return builder.Build();
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchSortBuilder.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchSortBuilder.cs
new file mode 100644
index 0000000..f9d5575
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchSortBuilder.cs
@@ -0,0 +1,149 @@
+using System;
+using com.alicloud.openservices.tablestore.core.protocol;
+
+namespace Aliyun.OTS.ProtoBuffer
+{
+ public class SearchSortBuilder
+ {
+
+ public static SortOrder BuildSortOrder(DataModel.Search.Sort.SortOrder sortOrder)
+ {
+ switch (sortOrder)
+ {
+ case DataModel.Search.Sort.SortOrder.ASC:
+ return SortOrder.SORT_ORDER_ASC;
+ case DataModel.Search.Sort.SortOrder.DESC:
+ return SortOrder.SORT_ORDER_DESC;
+ default:
+ throw new ArgumentException("unknown sortOrder: " + sortOrder.ToString());
+ }
+ }
+
+ public static SortMode BuildSortMode(DataModel.Search.Sort.SortMode sortMode)
+ {
+ switch (sortMode)
+ {
+ case DataModel.Search.Sort.SortMode.MIN:
+ return SortMode.SORT_MODE_MIN;
+ case DataModel.Search.Sort.SortMode.MAX:
+ return SortMode.SORT_MODE_MAX;
+ case DataModel.Search.Sort.SortMode.AVG:
+ return SortMode.SORT_MODE_AVG;
+ default:
+ throw new ArgumentException("unknown sortOrder: " + sortMode.ToString());
+ }
+ }
+
+ public static NestedFilter BuildNestedFilter(DataModel.Search.Sort.NestedFilter nestedFilter)
+ {
+ NestedFilter.Builder builder = NestedFilter.CreateBuilder();
+ builder.SetPath(nestedFilter.Path);
+ builder.SetFilter(SearchQueryBuilder.BuildQuery(nestedFilter.Query));
+ return builder.Build();
+ }
+
+ public static FieldSort BuildFieldSort(DataModel.Search.Sort.FieldSort fieldSort)
+ {
+ FieldSort.Builder builder = FieldSort.CreateBuilder();
+ builder.SetFieldName(fieldSort.FieldName);
+
+ builder.SetOrder(BuildSortOrder(fieldSort.Order));
+
+ builder.SetMode(BuildSortMode(fieldSort.Mode));
+
+ if (fieldSort.NestedFilter != null)
+ {
+ builder.SetNestedFilter(BuildNestedFilter(fieldSort.NestedFilter));
+ }
+ return builder.Build();
+ }
+
+ public static ScoreSort BuildScoreSort(DataModel.Search.Sort.ScoreSort scoreSort)
+ {
+ ScoreSort.Builder builder = ScoreSort.CreateBuilder();
+ builder.SetOrder(BuildSortOrder(scoreSort.Order));
+ return builder.Build();
+ }
+
+ public static GeoDistanceType BuildGeoDistanceType(DataModel.Search.Sort.GeoDistanceType geoDistanceType)
+ {
+ switch (geoDistanceType)
+ {
+ case DataModel.Search.Sort.GeoDistanceType.ARC:
+ return GeoDistanceType.GEO_DISTANCE_ARC;
+ case DataModel.Search.Sort.GeoDistanceType.PLANE:
+ return GeoDistanceType.GEO_DISTANCE_PLANE;
+ default:
+ throw new ArgumentException("unknown geoDistanceType: " + geoDistanceType.ToString());
+ }
+ }
+
+ public static GeoDistanceSort BuildGeoDistanceSort(DataModel.Search.Sort.GeoDistanceSort geoDistanceSort)
+ {
+ GeoDistanceSort.Builder builder = GeoDistanceSort.CreateBuilder();
+ builder.SetFieldName(geoDistanceSort.FieldName);
+ if (geoDistanceSort.Points != null)
+ {
+ builder.AddRangePoints(geoDistanceSort.Points);
+ }
+
+ builder.SetOrder(BuildSortOrder(geoDistanceSort.Order));
+
+
+ builder.SetMode(BuildSortMode(geoDistanceSort.Mode));
+
+
+ builder.SetDistanceType(BuildGeoDistanceType(geoDistanceSort.DistanceType));
+
+ if (geoDistanceSort.NestedFilter != null)
+ {
+ builder.SetNestedFilter(BuildNestedFilter(geoDistanceSort.NestedFilter));
+ }
+ return builder.Build();
+ }
+
+ public static PrimaryKeySort BuilderPrimarykeySort(DataModel.Search.Sort.PrimaryKeySort primaryKeySort)
+ {
+ var builder = PrimaryKeySort.CreateBuilder();
+ builder.SetOrder(BuildSortOrder(primaryKeySort.Order));
+ return builder.Build();
+ }
+
+ public static Sorter BuildSorter(DataModel.Search.Sort.ISorter sorter)
+ {
+ Sorter.Builder builder = Sorter.CreateBuilder();
+ if (sorter is DataModel.Search.Sort.FieldSort)
+ {
+ builder.SetFieldSort(BuildFieldSort((DataModel.Search.Sort.FieldSort)sorter));
+ }
+ else if (sorter is DataModel.Search.Sort.ScoreSort)
+ {
+ builder.SetScoreSort(BuildScoreSort((DataModel.Search.Sort.ScoreSort)sorter));
+ }
+ else if (sorter is DataModel.Search.Sort.GeoDistanceSort)
+ {
+ builder.SetGeoDistanceSort(BuildGeoDistanceSort((DataModel.Search.Sort.GeoDistanceSort)sorter));
+ }
+ else if (sorter is DataModel.Search.Sort.PrimaryKeySort)
+ {
+ builder.SetPkSort(BuilderPrimarykeySort((DataModel.Search.Sort.PrimaryKeySort)sorter));
+ }
+ else
+ {
+ throw new ArgumentException("unknown sorter type: " + sorter.ToString());
+ }
+ return builder.Build();
+ }
+
+ public static Sort BuildSort(DataModel.Search.Sort.Sort sort)
+ {
+ Sort.Builder builder = Sort.CreateBuilder();
+ foreach (var sorter in sort.Sorters)
+ {
+ builder.AddSorter(BuildSorter(sorter));
+ }
+ return builder.Build();
+ }
+
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchVariantType.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchVariantType.cs
new file mode 100644
index 0000000..34ac2ce
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/SearchVariantType.cs
@@ -0,0 +1,116 @@
+using System;
+using System.IO;
+using System.Text;
+using Aliyun.OTS.DataModel;
+
+namespace Aliyun.OTS.ProtoBuffer
+{
+ public class SearchVariantType
+ {
+ public enum VariantType
+ {
+ INTEGER,
+ DOUBLE,
+ BOOLEAN,
+ STRING
+ }
+
+ // variant type
+ public static byte VT_INTEGER = 0x0;
+ public static byte VT_DOUBLE = 0x1;
+ public static byte VT_BOOLEAN = 0x2;
+ public static byte VT_STRING = 0x3;
+
+ public static VariantType GetVariantType(byte[] data)
+ {
+ if (data[0] == VT_INTEGER)
+ {
+ return VariantType.INTEGER;
+ }
+ else if (data[0] == VT_DOUBLE)
+ {
+ return VariantType.DOUBLE;
+ }
+ else if (data[0] == VT_BOOLEAN)
+ {
+ return VariantType.BOOLEAN;
+ }
+ else if (data[0] == VT_STRING)
+ {
+ return VariantType.STRING;
+ }
+ else
+ {
+ throw new ArgumentException("unknown type: " + data[0]);
+ }
+ }
+
+ public static byte[] FromLong(long v)
+ {
+ using (MemoryStream ms = new MemoryStream())
+ {
+ ms.WriteByte(VT_INTEGER);
+ foreach (var item in BitConverter.GetBytes(v))
+ {
+ ms.WriteByte(item);
+ }
+ return ms.ToArray();
+ }
+ }
+
+ public static byte[] FromDouble(double v)
+ {
+ using (MemoryStream ms = new MemoryStream())
+ {
+ ms.WriteByte(VT_DOUBLE);
+ foreach (var item in BitConverter.GetBytes(v))
+ {
+ ms.WriteByte(item);
+ }
+ return ms.ToArray();
+ }
+ }
+
+ public static byte[] FromString(string v)
+ {
+ using (MemoryStream ms = new MemoryStream())
+ {
+ byte[] strBytes = Encoding.UTF8.GetBytes(v);
+
+ ms.WriteByte(VT_STRING);
+ foreach (var item in BitConverter.GetBytes(strBytes.Length))
+ {
+ ms.WriteByte(item);
+ }
+
+ foreach (var item in Encoding.UTF8.GetBytes(v))
+ {
+ ms.WriteByte(item);
+ }
+ return ms.ToArray();
+ }
+ }
+
+ public static byte[] FromBoolean(bool v)
+ {
+ return new byte[] { VT_BOOLEAN, (byte)(v ? 1 : 0) };
+ }
+
+ public static byte[] toVariant(ColumnValue value)
+ {
+ switch (value.Type)
+ {
+ case ColumnValueType.String:
+ return FromString(value.StringValue);
+ case ColumnValueType.Integer:
+ return FromLong(value.IntegerValue);
+ case ColumnValueType.Double:
+ return FromDouble(value.DoubleValue);
+ case ColumnValueType.Boolean:
+ return FromBoolean(value.BooleanValue);
+ default:
+ throw new ArgumentException("unsupported type:" + value.Type);
+ }
+ }
+ }
+}
diff --git a/netstandard-sdk/Aliyun/OTS/ProtoBuffer/TableStore.cs b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/TableStore.cs
new file mode 100644
index 0000000..431c08f
--- /dev/null
+++ b/netstandard-sdk/Aliyun/OTS/ProtoBuffer/TableStore.cs
@@ -0,0 +1,29215 @@
+// Generated by ProtoGen, Version=2.4.1.555, Culture=neutral, PublicKeyToken=17b3b1f090c3ea48. DO NOT EDIT!
+#pragma warning disable 1591, 0612, 3021
+#region Designer generated code
+
+using pb = global::Google.ProtocolBuffers;
+using pbc = global::Google.ProtocolBuffers.Collections;
+using pbd = global::Google.ProtocolBuffers.Descriptors;
+using scg = global::System.Collections.Generic;
+namespace com.alicloud.openservices.tablestore.core.protocol {
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ public static partial class TableStore {
+
+ #region Extension registration
+ public static void RegisterAllExtensions(pb::ExtensionRegistry registry) {
+ }
+ #endregion
+ #region Static variables
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_Error__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_Error__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_PrimaryKeySchema__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_PrimaryKeySchema__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DefinedColumnSchema__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DefinedColumnSchema__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_PartitionRange__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_PartitionRange__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_TableOptions__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_TableOptions__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_IndexMeta__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_IndexMeta__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_TableMeta__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_TableMeta__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_Condition__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_Condition__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_CapacityUnit__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_CapacityUnit__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughputDetails__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughputDetails__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughput__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughput__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ConsumedCapacity__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ConsumedCapacity__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamSpecification__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamSpecification__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamDetails__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamDetails__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_TimeRange__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_TimeRange__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ReturnContent__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ReturnContent__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchGetRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchGetRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchGetRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchGetRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_RowInBatchGetRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_RowInBatchGetRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchGetRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchGetRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchGetRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchGetRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_RowInBatchWriteRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_RowInBatchWriteRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchWriteRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchWriteRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchWriteRowRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchWriteRowRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_RowInBatchWriteRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_RowInBatchWriteRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchWriteRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_TableInBatchWriteRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchWriteRowResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_BatchWriteRowResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRangeRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRangeRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRangeResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRangeResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_StartLocalTransactionRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_StartLocalTransactionRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_StartLocalTransactionResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_StartLocalTransactionResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_CommitTransactionRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_CommitTransactionRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_CommitTransactionResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_CommitTransactionResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_AbortTransactionRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_AbortTransactionRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_AbortTransactionResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_AbortTransactionResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ListStreamRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ListStreamRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_Stream__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_Stream__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ListStreamResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ListStreamResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamShard__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamShard__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeStreamRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeStreamRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeStreamResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeStreamResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetShardIteratorRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetShardIteratorRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetShardIteratorResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetShardIteratorResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetStreamRecordRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetStreamRecordRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetStreamRecordResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetStreamRecordResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_GetStreamRecordResponse_StreamRecord__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_GetStreamRecordResponse_StreamRecord__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ComputeSplitPointsBySizeRequest__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ComputeSplitPointsBySizeRequest__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ComputeSplitPointsBySizeResponse__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ComputeSplitPointsBySizeResponse__FieldAccessorTable;
+ internal static pbd::MessageDescriptor internal__static_com_alicloud_openservices_tablestore_core_protocol_ComputeSplitPointsBySizeResponse_SplitLocation__Descriptor;
+ internal static pb::FieldAccess.FieldAccessorTable internal__static_com_alicloud_openservices_tablestore_core_protocol_ComputeSplitPointsBySizeResponse_SplitLocation__FieldAccessorTable;
+ #endregion
+ #region Descriptor
+ public static pbd::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbd::FileDescriptor descriptor;
+
+ static TableStore() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChF0YWJsZV9zdG9yZS5wcm90bxIyY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNl",
+ "cy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wiJgoFRXJyb3ISDAoEY29kZRgB",
+ "IAIoCRIPCgdtZXNzYWdlGAIgASgJIsgBChBQcmltYXJ5S2V5U2NoZW1hEgwK",
+ "BG5hbWUYASACKAkSUAoEdHlwZRgCIAIoDjJCLmNvbS5hbGljbG91ZC5vcGVu",
+ "c2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlByaW1hcnlLZXlU",
+ "eXBlElQKBm9wdGlvbhgDIAEoDjJELmNvbS5hbGljbG91ZC5vcGVuc2Vydmlj",
+ "ZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlByaW1hcnlLZXlPcHRpb24i",
+ "eAoTRGVmaW5lZENvbHVtblNjaGVtYRIMCgRuYW1lGAEgAigJElMKBHR5cGUY",
+ "AiACKA4yRS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUu",
+ "Y29yZS5wcm90b2NvbC5EZWZpbmVkQ29sdW1uVHlwZSIsCg5QYXJ0aXRpb25S",
+ "YW5nZRINCgViZWdpbhgBIAIoDBILCgNlbmQYAiACKAwi1QEKDFRhYmxlT3B0",
+ "aW9ucxIUCgx0aW1lX3RvX2xpdmUYASABKAUSFAoMbWF4X3ZlcnNpb25zGAIg",
+ "ASgFEl4KEWJsb29tX2ZpbHRlcl90eXBlGAMgASgOMkMuY29tLmFsaWNsb3Vk",
+ "Lm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuQmxvb21G",
+ "aWx0ZXJUeXBlEhIKCmJsb2NrX3NpemUYBCABKAUSJQodZGV2aWF0aW9uX2Nl",
+ "bGxfdmVyc2lvbl9pbl9zZWMYBSABKAMi+QEKCUluZGV4TWV0YRIMCgRuYW1l",
+ "GAEgAigJEhMKC3ByaW1hcnlfa2V5GAIgAygJEhYKDmRlZmluZWRfY29sdW1u",
+ "GAMgAygJEl4KEWluZGV4X3VwZGF0ZV9tb2RlGAQgAigOMkMuY29tLmFsaWNs",
+ "b3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuSW5k",
+ "ZXhVcGRhdGVNb2RlElEKCmluZGV4X3R5cGUYBSACKA4yPS5jb20uYWxpY2xv",
+ "dWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5JbmRl",
+ "eFR5cGUirgIKCVRhYmxlTWV0YRISCgp0YWJsZV9uYW1lGAEgAigJElkKC3By",
+ "aW1hcnlfa2V5GAIgAygLMkQuY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50",
+ "YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuUHJpbWFyeUtleVNjaGVtYRJfCg5k",
+ "ZWZpbmVkX2NvbHVtbhgDIAMoCzJHLmNvbS5hbGljbG91ZC5vcGVuc2Vydmlj",
+ "ZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLkRlZmluZWRDb2x1bW5TY2hl",
+ "bWESUQoKaW5kZXhfbWV0YRgEIAMoCzI9LmNvbS5hbGljbG91ZC5vcGVuc2Vy",
+ "dmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLkluZGV4TWV0YSKJAQoJ",
+ "Q29uZGl0aW9uEmIKDXJvd19leGlzdGVuY2UYASACKA4ySy5jb20uYWxpY2xv",
+ "dWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5Sb3dF",
+ "eGlzdGVuY2VFeHBlY3RhdGlvbhIYChBjb2x1bW5fY29uZGl0aW9uGAIgASgM",
+ "IisKDENhcGFjaXR5VW5pdBIMCgRyZWFkGAEgASgFEg0KBXdyaXRlGAIgASgF",
+ "IqwBChlSZXNlcnZlZFRocm91Z2hwdXREZXRhaWxzElcKDWNhcGFjaXR5X3Vu",
+ "aXQYASACKAsyQC5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3Rv",
+ "cmUuY29yZS5wcm90b2NvbC5DYXBhY2l0eVVuaXQSGgoSbGFzdF9pbmNyZWFz",
+ "ZV90aW1lGAIgAigDEhoKEmxhc3RfZGVjcmVhc2VfdGltZRgDIAEoAyJtChJS",
+ "ZXNlcnZlZFRocm91Z2hwdXQSVwoNY2FwYWNpdHlfdW5pdBgBIAIoCzJALmNv",
+ "bS5hbGljbG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3Rv",
+ "Y29sLkNhcGFjaXR5VW5pdCJrChBDb25zdW1lZENhcGFjaXR5ElcKDWNhcGFj",
+ "aXR5X3VuaXQYASACKAsyQC5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRh",
+ "Ymxlc3RvcmUuY29yZS5wcm90b2NvbC5DYXBhY2l0eVVuaXQiRQoTU3RyZWFt",
+ "U3BlY2lmaWNhdGlvbhIVCg1lbmFibGVfc3RyZWFtGAEgAigIEhcKD2V4cGly",
+ "YXRpb25fdGltZRgCIAEoBSJsCg1TdHJlYW1EZXRhaWxzEhUKDWVuYWJsZV9z",
+ "dHJlYW0YASACKAgSEQoJc3RyZWFtX2lkGAIgASgJEhcKD2V4cGlyYXRpb25f",
+ "dGltZRgDIAEoBRIYChBsYXN0X2VuYWJsZV90aW1lGAQgASgDIq8EChJDcmVh",
+ "dGVUYWJsZVJlcXVlc3QSUQoKdGFibGVfbWV0YRgBIAIoCzI9LmNvbS5hbGlj",
+ "bG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlRh",
+ "YmxlTWV0YRJjChNyZXNlcnZlZF90aHJvdWdocHV0GAIgAigLMkYuY29tLmFs",
+ "aWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wu",
+ "UmVzZXJ2ZWRUaHJvdWdocHV0ElcKDXRhYmxlX29wdGlvbnMYAyABKAsyQC5j",
+ "b20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90",
+ "b2NvbC5UYWJsZU9wdGlvbnMSVgoKcGFydGl0aW9ucxgEIAMoCzJCLmNvbS5h",
+ "bGljbG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29s",
+ "LlBhcnRpdGlvblJhbmdlElwKC3N0cmVhbV9zcGVjGAUgASgLMkcuY29tLmFs",
+ "aWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wu",
+ "U3RyZWFtU3BlY2lmaWNhdGlvbhJSCgtpbmRleF9tZXRhcxgHIAMoCzI9LmNv",
+ "bS5hbGljbG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3Rv",
+ "Y29sLkluZGV4TWV0YSIVChNDcmVhdGVUYWJsZVJlc3BvbnNlIpsBChJDcmVh",
+ "dGVJbmRleFJlcXVlc3QSFwoPbWFpbl90YWJsZV9uYW1lGAEgAigJElEKCmlu",
+ "ZGV4X21ldGEYAiACKAsyPS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRh",
+ "Ymxlc3RvcmUuY29yZS5wcm90b2NvbC5JbmRleE1ldGESGQoRaW5jbHVkZV9i",
+ "YXNlX2RhdGEYAyABKAgiFQoTQ3JlYXRlSW5kZXhSZXNwb25zZSI/ChBEcm9w",
+ "SW5kZXhSZXF1ZXN0EhcKD21haW5fdGFibGVfbmFtZRgBIAIoCRISCgppbmRl",
+ "eF9uYW1lGAIgAigJIhMKEURyb3BJbmRleFJlc3BvbnNlIsQCChJVcGRhdGVU",
+ "YWJsZVJlcXVlc3QSEgoKdGFibGVfbmFtZRgBIAIoCRJjChNyZXNlcnZlZF90",
+ "aHJvdWdocHV0GAIgASgLMkYuY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50",
+ "YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuUmVzZXJ2ZWRUaHJvdWdocHV0ElcK",
+ "DXRhYmxlX29wdGlvbnMYAyABKAsyQC5jb20uYWxpY2xvdWQub3BlbnNlcnZp",
+ "Y2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5UYWJsZU9wdGlvbnMSXAoL",
+ "c3RyZWFtX3NwZWMYBCABKAsyRy5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2Vz",
+ "LnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5TdHJlYW1TcGVjaWZpY2F0aW9u",
+ "Ir0CChNVcGRhdGVUYWJsZVJlc3BvbnNlEnIKG3Jlc2VydmVkX3Rocm91Z2hw",
+ "dXRfZGV0YWlscxgBIAIoCzJNLmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMu",
+ "dGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlJlc2VydmVkVGhyb3VnaHB1dERl",
+ "dGFpbHMSVwoNdGFibGVfb3B0aW9ucxgCIAIoCzJALmNvbS5hbGljbG91ZC5v",
+ "cGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlRhYmxlT3B0",
+ "aW9ucxJZCg5zdHJlYW1fZGV0YWlscxgDIAEoCzJBLmNvbS5hbGljbG91ZC5v",
+ "cGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlN0cmVhbURl",
+ "dGFpbHMiKgoURGVzY3JpYmVUYWJsZVJlcXVlc3QSEgoKdGFibGVfbmFtZRgB",
+ "IAIoCSLTBAoVRGVzY3JpYmVUYWJsZVJlc3BvbnNlElEKCnRhYmxlX21ldGEY",
+ "ASACKAsyPS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUu",
+ "Y29yZS5wcm90b2NvbC5UYWJsZU1ldGEScgobcmVzZXJ2ZWRfdGhyb3VnaHB1",
+ "dF9kZXRhaWxzGAIgAigLMk0uY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50",
+ "YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuUmVzZXJ2ZWRUaHJvdWdocHV0RGV0",
+ "YWlscxJXCg10YWJsZV9vcHRpb25zGAMgAigLMkAuY29tLmFsaWNsb3VkLm9w",
+ "ZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuVGFibGVPcHRp",
+ "b25zElUKDHRhYmxlX3N0YXR1cxgEIAIoDjI/LmNvbS5hbGljbG91ZC5vcGVu",
+ "c2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlRhYmxlU3RhdHVz",
+ "ElkKDnN0cmVhbV9kZXRhaWxzGAUgASgLMkEuY29tLmFsaWNsb3VkLm9wZW5z",
+ "ZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuU3RyZWFtRGV0YWls",
+ "cxIUCgxzaGFyZF9zcGxpdHMYBiADKAwSUgoLaW5kZXhfbWV0YXMYCCADKAsy",
+ "PS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5w",
+ "cm90b2NvbC5JbmRleE1ldGEiEgoQTGlzdFRhYmxlUmVxdWVzdCIoChFMaXN0",
+ "VGFibGVSZXNwb25zZRITCgt0YWJsZV9uYW1lcxgBIAMoCSIoChJEZWxldGVU",
+ "YWJsZVJlcXVlc3QSEgoKdGFibGVfbmFtZRgBIAIoCSIVChNEZWxldGVUYWJs",
+ "ZVJlc3BvbnNlIiYKEExvYWRUYWJsZVJlcXVlc3QSEgoKdGFibGVfbmFtZRgB",
+ "IAIoCSITChFMb2FkVGFibGVSZXNwb25zZSIoChJVbmxvYWRUYWJsZVJlcXVl",
+ "c3QSEgoKdGFibGVfbmFtZRgBIAIoCSIVChNVbmxvYWRUYWJsZVJlc3BvbnNl",
+ "IkgKCVRpbWVSYW5nZRISCgpzdGFydF90aW1lGAEgASgDEhAKCGVuZF90aW1l",
+ "GAIgASgDEhUKDXNwZWNpZmljX3RpbWUYAyABKAMigQEKDVJldHVybkNvbnRl",
+ "bnQSUwoLcmV0dXJuX3R5cGUYASABKA4yPi5jb20uYWxpY2xvdWQub3BlbnNl",
+ "cnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5SZXR1cm5UeXBlEhsK",
+ "E3JldHVybl9jb2x1bW5fbmFtZXMYAiADKAkitgIKDUdldFJvd1JlcXVlc3QS",
+ "EgoKdGFibGVfbmFtZRgBIAIoCRITCgtwcmltYXJ5X2tleRgCIAIoDBIWCg5j",
+ "b2x1bW5zX3RvX2dldBgDIAMoCRJRCgp0aW1lX3JhbmdlGAQgASgLMj0uY29t",
+ "LmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9j",
+ "b2wuVGltZVJhbmdlEhQKDG1heF92ZXJzaW9ucxgFIAEoBRIaCgxjYWNoZV9i",
+ "bG9ja3MYBiABKAg6BHRydWUSDgoGZmlsdGVyGAcgASgMEhQKDHN0YXJ0X2Nv",
+ "bHVtbhgIIAEoCRISCgplbmRfY29sdW1uGAkgASgJEg0KBXRva2VuGAogASgM",
+ "EhYKDnRyYW5zYWN0aW9uX2lkGAsgASgJIokBCg5HZXRSb3dSZXNwb25zZRJW",
+ "Cghjb25zdW1lZBgBIAIoCzJELmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMu",
+ "dGFibGVzdG9yZS5jb3JlLnByb3RvY29sLkNvbnN1bWVkQ2FwYWNpdHkSCwoD",
+ "cm93GAIgAigMEhIKCm5leHRfdG9rZW4YAyABKAwi/wEKEFVwZGF0ZVJvd1Jl",
+ "cXVlc3QSEgoKdGFibGVfbmFtZRgBIAIoCRISCgpyb3dfY2hhbmdlGAIgAigM",
+ "ElAKCWNvbmRpdGlvbhgDIAIoCzI9LmNvbS5hbGljbG91ZC5vcGVuc2Vydmlj",
+ "ZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLkNvbmRpdGlvbhJZCg5yZXR1",
+ "cm5fY29udGVudBgEIAEoCzJBLmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMu",
+ "dGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlJldHVybkNvbnRlbnQSFgoOdHJh",
+ "bnNhY3Rpb25faWQYBSABKAkieAoRVXBkYXRlUm93UmVzcG9uc2USVgoIY29u",
+ "c3VtZWQYASACKAsyRC5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxl",
+ "c3RvcmUuY29yZS5wcm90b2NvbC5Db25zdW1lZENhcGFjaXR5EgsKA3JvdxgC",
+ "IAEoDCL1AQoNUHV0Um93UmVxdWVzdBISCgp0YWJsZV9uYW1lGAEgAigJEgsK",
+ "A3JvdxgCIAIoDBJQCgljb25kaXRpb24YAyACKAsyPS5jb20uYWxpY2xvdWQu",
+ "b3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5Db25kaXRp",
+ "b24SWQoOcmV0dXJuX2NvbnRlbnQYBCABKAsyQS5jb20uYWxpY2xvdWQub3Bl",
+ "bnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5SZXR1cm5Db250",
+ "ZW50EhYKDnRyYW5zYWN0aW9uX2lkGAUgASgJInUKDlB1dFJvd1Jlc3BvbnNl",
+ "ElYKCGNvbnN1bWVkGAEgAigLMkQuY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNl",
+ "cy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuQ29uc3VtZWRDYXBhY2l0eRIL",
+ "CgNyb3cYAiABKAwigAIKEERlbGV0ZVJvd1JlcXVlc3QSEgoKdGFibGVfbmFt",
+ "ZRgBIAIoCRITCgtwcmltYXJ5X2tleRgCIAIoDBJQCgljb25kaXRpb24YAyAC",
+ "KAsyPS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29y",
+ "ZS5wcm90b2NvbC5Db25kaXRpb24SWQoOcmV0dXJuX2NvbnRlbnQYBCABKAsy",
+ "QS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5w",
+ "cm90b2NvbC5SZXR1cm5Db250ZW50EhYKDnRyYW5zYWN0aW9uX2lkGAUgASgJ",
+ "IngKEURlbGV0ZVJvd1Jlc3BvbnNlElYKCGNvbnN1bWVkGAEgAigLMkQuY29t",
+ "LmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9j",
+ "b2wuQ29uc3VtZWRDYXBhY2l0eRILCgNyb3cYAiABKAwiqgIKGVRhYmxlSW5C",
+ "YXRjaEdldFJvd1JlcXVlc3QSEgoKdGFibGVfbmFtZRgBIAIoCRITCgtwcmlt",
+ "YXJ5X2tleRgCIAMoDBINCgV0b2tlbhgDIAMoDBIWCg5jb2x1bW5zX3RvX2dl",
+ "dBgEIAMoCRJRCgp0aW1lX3JhbmdlGAUgASgLMj0uY29tLmFsaWNsb3VkLm9w",
+ "ZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuVGltZVJhbmdl",
+ "EhQKDG1heF92ZXJzaW9ucxgGIAEoBRIaCgxjYWNoZV9ibG9ja3MYByABKAg6",
+ "BHRydWUSDgoGZmlsdGVyGAggASgMEhQKDHN0YXJ0X2NvbHVtbhgJIAEoCRIS",
+ "CgplbmRfY29sdW1uGAogASgJInMKEkJhdGNoR2V0Um93UmVxdWVzdBJdCgZ0",
+ "YWJsZXMYASADKAsyTS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxl",
+ "c3RvcmUuY29yZS5wcm90b2NvbC5UYWJsZUluQmF0Y2hHZXRSb3dSZXF1ZXN0",
+ "IuwBChhSb3dJbkJhdGNoR2V0Um93UmVzcG9uc2USDQoFaXNfb2sYASACKAgS",
+ "SAoFZXJyb3IYAiABKAsyOS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRh",
+ "Ymxlc3RvcmUuY29yZS5wcm90b2NvbC5FcnJvchJWCghjb25zdW1lZBgDIAEo",
+ "CzJELmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3Jl",
+ "LnByb3RvY29sLkNvbnN1bWVkQ2FwYWNpdHkSCwoDcm93GAQgASgMEhIKCm5l",
+ "eHRfdG9rZW4YBSABKAwijAEKGlRhYmxlSW5CYXRjaEdldFJvd1Jlc3BvbnNl",
+ "EhIKCnRhYmxlX25hbWUYASACKAkSWgoEcm93cxgCIAMoCzJMLmNvbS5hbGlj",
+ "bG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlJv",
+ "d0luQmF0Y2hHZXRSb3dSZXNwb25zZSJ1ChNCYXRjaEdldFJvd1Jlc3BvbnNl",
+ "El4KBnRhYmxlcxgBIAMoCzJOLmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMu",
+ "dGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlRhYmxlSW5CYXRjaEdldFJvd1Jl",
+ "c3BvbnNlIq0CChlSb3dJbkJhdGNoV3JpdGVSb3dSZXF1ZXN0Ek8KBHR5cGUY",
+ "ASACKA4yQS5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUu",
+ "Y29yZS5wcm90b2NvbC5PcGVyYXRpb25UeXBlEhIKCnJvd19jaGFuZ2UYAiAC",
+ "KAwSUAoJY29uZGl0aW9uGAMgAigLMj0uY29tLmFsaWNsb3VkLm9wZW5zZXJ2",
+ "aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuQ29uZGl0aW9uElkKDnJl",
+ "dHVybl9jb250ZW50GAQgASgLMkEuY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNl",
+ "cy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuUmV0dXJuQ29udGVudCKOAQob",
+ "VGFibGVJbkJhdGNoV3JpdGVSb3dSZXF1ZXN0EhIKCnRhYmxlX25hbWUYASAC",
+ "KAkSWwoEcm93cxgCIAMoCzJNLmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMu",
+ "dGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlJvd0luQmF0Y2hXcml0ZVJvd1Jl",
+ "cXVlc3QijwEKFEJhdGNoV3JpdGVSb3dSZXF1ZXN0El8KBnRhYmxlcxgBIAMo",
+ "CzJPLmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3Jl",
+ "LnByb3RvY29sLlRhYmxlSW5CYXRjaFdyaXRlUm93UmVxdWVzdBIWCg50cmFu",
+ "c2FjdGlvbl9pZBgCIAEoCSLaAQoaUm93SW5CYXRjaFdyaXRlUm93UmVzcG9u",
+ "c2USDQoFaXNfb2sYASACKAgSSAoFZXJyb3IYAiABKAsyOS5jb20uYWxpY2xv",
+ "dWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5FcnJv",
+ "chJWCghjb25zdW1lZBgDIAEoCzJELmNvbS5hbGljbG91ZC5vcGVuc2Vydmlj",
+ "ZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLkNvbnN1bWVkQ2FwYWNpdHkS",
+ "CwoDcm93GAQgASgMIpABChxUYWJsZUluQmF0Y2hXcml0ZVJvd1Jlc3BvbnNl",
+ "EhIKCnRhYmxlX25hbWUYASACKAkSXAoEcm93cxgCIAMoCzJOLmNvbS5hbGlj",
+ "bG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnByb3RvY29sLlJv",
+ "d0luQmF0Y2hXcml0ZVJvd1Jlc3BvbnNlInkKFUJhdGNoV3JpdGVSb3dSZXNw",
+ "b25zZRJgCgZ0YWJsZXMYASADKAsyUC5jb20uYWxpY2xvdWQub3BlbnNlcnZp",
+ "Y2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5UYWJsZUluQmF0Y2hXcml0",
+ "ZVJvd1Jlc3BvbnNlItEFCg9HZXRSYW5nZVJlcXVlc3QSEgoKdGFibGVfbmFt",
+ "ZRgBIAIoCRJQCglkaXJlY3Rpb24YAiACKA4yPS5jb20uYWxpY2xvdWQub3Bl",
+ "bnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5EaXJlY3Rpb24S",
+ "FgoOY29sdW1uc190b19nZXQYAyADKAkSUQoKdGltZV9yYW5nZRgEIAEoCzI9",
+ "LmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMudGFibGVzdG9yZS5jb3JlLnBy",
+ "b3RvY29sLlRpbWVSYW5nZRIUCgxtYXhfdmVyc2lvbnMYBSABKAUSDQoFbGlt",
+ "aXQYBiABKAUSIwobaW5jbHVzaXZlX3N0YXJ0X3ByaW1hcnlfa2V5GAcgAigM",
+ "EiEKGWV4Y2x1c2l2ZV9lbmRfcHJpbWFyeV9rZXkYCCACKAwSGgoMY2FjaGVf",
+ "YmxvY2tzGAkgASgIOgR0cnVlEg4KBmZpbHRlchgKIAEoDBIUCgxzdGFydF9j",
+ "b2x1bW4YCyABKAkSEgoKZW5kX2NvbHVtbhgMIAEoCRINCgV0b2tlbhgNIAEo",
+ "DBIWCg50cmFuc2FjdGlvbl9pZBgOIAEoCRJxChRkYXRhX2Jsb2NrX3R5cGVf",
+ "aGludBgPIAEoDjJBLmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMudGFibGVz",
+ "dG9yZS5jb3JlLnByb3RvY29sLkRhdGFCbG9ja1R5cGU6EERCVF9QTEFJTl9C",
+ "VUZGRVISKAoacmV0dXJuX2VudGlyZV9wcmltYXJ5X2tleXMYECABKAg6BHRy",
+ "dWUSZgoSY29tcHJlc3NfdHlwZV9oaW50GBEgASgOMkAuY29tLmFsaWNsb3Vk",
+ "Lm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuQ29tcHJl",
+ "c3NUeXBlOghDUFRfTk9ORSLhAgoQR2V0UmFuZ2VSZXNwb25zZRJWCghjb25z",
+ "dW1lZBgBIAIoCzJELmNvbS5hbGljbG91ZC5vcGVuc2VydmljZXMudGFibGVz",
+ "dG9yZS5jb3JlLnByb3RvY29sLkNvbnN1bWVkQ2FwYWNpdHkSDAoEcm93cxgC",
+ "IAIoDBIeChZuZXh0X3N0YXJ0X3ByaW1hcnlfa2V5GAMgASgMEhIKCm5leHRf",
+ "dG9rZW4YBCABKAwSWgoPZGF0YV9ibG9ja190eXBlGAUgASgOMkEuY29tLmFs",
+ "aWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wu",
+ "RGF0YUJsb2NrVHlwZRJXCg1jb21wcmVzc190eXBlGAYgASgOMkAuY29tLmFs",
+ "aWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wu",
+ "Q29tcHJlc3NUeXBlIj8KHFN0YXJ0TG9jYWxUcmFuc2FjdGlvblJlcXVlc3QS",
+ "EgoKdGFibGVfbmFtZRgBIAIoCRILCgNrZXkYAiACKAwiNwodU3RhcnRMb2Nh",
+ "bFRyYW5zYWN0aW9uUmVzcG9uc2USFgoOdHJhbnNhY3Rpb25faWQYASACKAki",
+ "MgoYQ29tbWl0VHJhbnNhY3Rpb25SZXF1ZXN0EhYKDnRyYW5zYWN0aW9uX2lk",
+ "GAEgAigJIhsKGUNvbW1pdFRyYW5zYWN0aW9uUmVzcG9uc2UiMQoXQWJvcnRU",
+ "cmFuc2FjdGlvblJlcXVlc3QSFgoOdHJhbnNhY3Rpb25faWQYASACKAkiGgoY",
+ "QWJvcnRUcmFuc2FjdGlvblJlc3BvbnNlIicKEUxpc3RTdHJlYW1SZXF1ZXN0",
+ "EhIKCnRhYmxlX25hbWUYASABKAkiRgoGU3RyZWFtEhEKCXN0cmVhbV9pZBgB",
+ "IAIoCRISCgp0YWJsZV9uYW1lGAIgAigJEhUKDWNyZWF0aW9uX3RpbWUYAyAC",
+ "KAMiYQoSTGlzdFN0cmVhbVJlc3BvbnNlEksKB3N0cmVhbXMYASADKAsyOi5j",
+ "b20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5wcm90",
+ "b2NvbC5TdHJlYW0iTQoLU3RyZWFtU2hhcmQSEAoIc2hhcmRfaWQYASACKAkS",
+ "EQoJcGFyZW50X2lkGAIgASgJEhkKEXBhcmVudF9zaWJsaW5nX2lkGAMgASgJ",
+ "ImEKFURlc2NyaWJlU3RyZWFtUmVxdWVzdBIRCglzdHJlYW1faWQYASACKAkS",
+ "IAoYaW5jbHVzaXZlX3N0YXJ0X3NoYXJkX2lkGAIgASgJEhMKC3NoYXJkX2xp",
+ "bWl0GAMgASgFIrACChZEZXNjcmliZVN0cmVhbVJlc3BvbnNlEhEKCXN0cmVh",
+ "bV9pZBgBIAIoCRIXCg9leHBpcmF0aW9uX3RpbWUYAiACKAUSEgoKdGFibGVf",
+ "bmFtZRgDIAIoCRIVCg1jcmVhdGlvbl90aW1lGAQgAigDElcKDXN0cmVhbV9z",
+ "dGF0dXMYBSACKA4yQC5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxl",
+ "c3RvcmUuY29yZS5wcm90b2NvbC5TdHJlYW1TdGF0dXMSTwoGc2hhcmRzGAYg",
+ "AygLMj8uY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNv",
+ "cmUucHJvdG9jb2wuU3RyZWFtU2hhcmQSFQoNbmV4dF9zaGFyZF9pZBgHIAEo",
+ "CSI+ChdHZXRTaGFyZEl0ZXJhdG9yUmVxdWVzdBIRCglzdHJlYW1faWQYASAC",
+ "KAkSEAoIc2hhcmRfaWQYAiACKAkiMgoYR2V0U2hhcmRJdGVyYXRvclJlc3Bv",
+ "bnNlEhYKDnNoYXJkX2l0ZXJhdG9yGAEgAigJIj8KFkdldFN0cmVhbVJlY29y",
+ "ZFJlcXVlc3QSFgoOc2hhcmRfaXRlcmF0b3IYASACKAkSDQoFbGltaXQYAiAB",
+ "KAUinQIKF0dldFN0cmVhbVJlY29yZFJlc3BvbnNlEnAKDnN0cmVhbV9yZWNv",
+ "cmRzGAEgAygLMlguY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0",
+ "b3JlLmNvcmUucHJvdG9jb2wuR2V0U3RyZWFtUmVjb3JkUmVzcG9uc2UuU3Ry",
+ "ZWFtUmVjb3JkEhsKE25leHRfc2hhcmRfaXRlcmF0b3IYAiABKAkacwoMU3Ry",
+ "ZWFtUmVjb3JkElMKC2FjdGlvbl90eXBlGAEgAigOMj4uY29tLmFsaWNsb3Vk",
+ "Lm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNvcmUucHJvdG9jb2wuQWN0aW9u",
+ "VHlwZRIOCgZyZWNvcmQYAiACKAwiagofQ29tcHV0ZVNwbGl0UG9pbnRzQnlT",
+ "aXplUmVxdWVzdBISCgp0YWJsZV9uYW1lGAEgAigJEhIKCnNwbGl0X3NpemUY",
+ "AiACKAMSHwoXc3BsaXRfc2l6ZV91bml0X2luX2J5dGUYAyABKAMikAMKIENv",
+ "bXB1dGVTcGxpdFBvaW50c0J5U2l6ZVJlc3BvbnNlElYKCGNvbnN1bWVkGAEg",
+ "AigLMkQuY29tLmFsaWNsb3VkLm9wZW5zZXJ2aWNlcy50YWJsZXN0b3JlLmNv",
+ "cmUucHJvdG9jb2wuQ29uc3VtZWRDYXBhY2l0eRJUCgZzY2hlbWEYAiADKAsy",
+ "RC5jb20uYWxpY2xvdWQub3BlbnNlcnZpY2VzLnRhYmxlc3RvcmUuY29yZS5w",
+ "cm90b2NvbC5QcmltYXJ5S2V5U2NoZW1hEhQKDHNwbGl0X3BvaW50cxgDIAMo",
+ "DBJ1Cglsb2NhdGlvbnMYBCADKAsyYi5jb20uYWxpY2xvdWQub3BlbnNlcnZp",
+ "Y2VzLnRhYmxlc3RvcmUuY29yZS5wcm90b2NvbC5Db21wdXRlU3BsaXRQb2lu",
+ "dHNCeVNpemVSZXNwb25zZS5TcGxpdExvY2F0aW9uGjEKDVNwbGl0TG9jYXRp",
+ "b24SEAoIbG9jYXRpb24YASACKAkSDgoGcmVwZWF0GAIgAigSKjUKDlByaW1h",
+ "cnlLZXlUeXBlEgsKB0lOVEVHRVIQARIKCgZTVFJJTkcQAhIKCgZCSU5BUlkQ",
+ "AypjChFEZWZpbmVkQ29sdW1uVHlwZRIPCgtEQ1RfSU5URUdFUhABEg4KCkRD",
+ "VF9ET1VCTEUQAhIPCgtEQ1RfQk9PTEVBThADEg4KCkRDVF9TVFJJTkcQBBIM",
+ "CghEQ1RfQkxPQhAHKiYKEFByaW1hcnlLZXlPcHRpb24SEgoOQVVUT19JTkNS",
+ "RU1FTlQQASouCg9CbG9vbUZpbHRlclR5cGUSCAoETk9ORRABEggKBENFTEwQ",
+ "AhIHCgNST1cQAypACg1EYXRhQmxvY2tUeXBlEhQKEERCVF9QTEFJTl9CVUZG",
+ "RVIQABIZChVEQlRfU0lNUExFX1JPV19NQVRSSVgQASocCgxDb21wcmVzc1R5",
+ "cGUSDAoIQ1BUX05PTkUQACo6Cg9JbmRleFVwZGF0ZU1vZGUSEwoPSVVNX0FT",
+ "WU5DX0lOREVYEAASEgoOSVVNX1NZTkNfSU5ERVgQASo0CglJbmRleFR5cGUS",
+ "EwoPSVRfR0xPQkFMX0lOREVYEAASEgoOSVRfTE9DQUxfSU5ERVgQASpRCgtU",
+ "YWJsZVN0YXR1cxIKCgZBQ1RJVkUQARIMCghJTkFDVElWRRACEgsKB0xPQURJ",
+ "TkcQAxINCglVTkxPQURJTkcQBBIMCghVUERBVElORxAFKk0KF1Jvd0V4aXN0",
+ "ZW5jZUV4cGVjdGF0aW9uEgoKBklHTk9SRRAAEhAKDEVYUEVDVF9FWElTVBAB",
+ "EhQKEEVYUEVDVF9OT1RfRVhJU1QQAio5CgpSZXR1cm5UeXBlEgsKB1JUX05P",
+ "TkUQABIJCgVSVF9QSxABEhMKD1JUX0FGVEVSX01PRElGWRACKjAKDU9wZXJh",
+ "dGlvblR5cGUSBwoDUFVUEAESCgoGVVBEQVRFEAISCgoGREVMRVRFEAMqJgoJ",
+ "RGlyZWN0aW9uEgsKB0ZPUldBUkQQABIMCghCQUNLV0FSRBABKjYKDFN0cmVh",
+ "bVN0YXR1cxITCg9TVFJFQU1fRU5BQkxJTkcQARIRCg1TVFJFQU1fQUNUSVZF",
+ "EAIqOQoKQWN0aW9uVHlwZRILCgdQVVRfUk9XEAESDgoKVVBEQVRFX1JPVxAC",
+ "Eg4KCkRFTEVURV9ST1cQAw=="));
+ pbd::FileDescriptor.InternalDescriptorAssigner assigner = delegate(pbd::FileDescriptor root) {
+ descriptor = root;
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_Error__Descriptor = Descriptor.MessageTypes[0];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_Error__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_Error__Descriptor,
+ new string[] { "Code", "Message", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PrimaryKeySchema__Descriptor = Descriptor.MessageTypes[1];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PrimaryKeySchema__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_PrimaryKeySchema__Descriptor,
+ new string[] { "Name", "Type", "Option", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DefinedColumnSchema__Descriptor = Descriptor.MessageTypes[2];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DefinedColumnSchema__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_DefinedColumnSchema__Descriptor,
+ new string[] { "Name", "Type", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PartitionRange__Descriptor = Descriptor.MessageTypes[3];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PartitionRange__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_PartitionRange__Descriptor,
+ new string[] { "Begin", "End", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_TableOptions__Descriptor = Descriptor.MessageTypes[4];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_TableOptions__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_TableOptions__Descriptor,
+ new string[] { "TimeToLive", "MaxVersions", "BloomFilterType", "BlockSize", "DeviationCellVersionInSec", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_IndexMeta__Descriptor = Descriptor.MessageTypes[5];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_IndexMeta__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_IndexMeta__Descriptor,
+ new string[] { "Name", "PrimaryKey", "DefinedColumn", "IndexUpdateMode", "IndexType", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_TableMeta__Descriptor = Descriptor.MessageTypes[6];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_TableMeta__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_TableMeta__Descriptor,
+ new string[] { "TableName", "PrimaryKey", "DefinedColumn", "IndexMeta", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_Condition__Descriptor = Descriptor.MessageTypes[7];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_Condition__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_Condition__Descriptor,
+ new string[] { "RowExistence", "ColumnCondition", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CapacityUnit__Descriptor = Descriptor.MessageTypes[8];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CapacityUnit__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_CapacityUnit__Descriptor,
+ new string[] { "Read", "Write", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughputDetails__Descriptor = Descriptor.MessageTypes[9];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughputDetails__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughputDetails__Descriptor,
+ new string[] { "CapacityUnit", "LastIncreaseTime", "LastDecreaseTime", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughput__Descriptor = Descriptor.MessageTypes[10];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughput__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_ReservedThroughput__Descriptor,
+ new string[] { "CapacityUnit", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ConsumedCapacity__Descriptor = Descriptor.MessageTypes[11];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ConsumedCapacity__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_ConsumedCapacity__Descriptor,
+ new string[] { "CapacityUnit", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamSpecification__Descriptor = Descriptor.MessageTypes[12];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamSpecification__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamSpecification__Descriptor,
+ new string[] { "EnableStream", "ExpirationTime", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamDetails__Descriptor = Descriptor.MessageTypes[13];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamDetails__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_StreamDetails__Descriptor,
+ new string[] { "EnableStream", "StreamId", "ExpirationTime", "LastEnableTime", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableRequest__Descriptor = Descriptor.MessageTypes[14];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableRequest__Descriptor,
+ new string[] { "TableMeta", "ReservedThroughput", "TableOptions", "Partitions", "StreamSpec", "IndexMetas", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableResponse__Descriptor = Descriptor.MessageTypes[15];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateTableResponse__Descriptor,
+ new string[] { });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexRequest__Descriptor = Descriptor.MessageTypes[16];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexRequest__Descriptor,
+ new string[] { "MainTableName", "IndexMeta", "IncludeBaseData", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexResponse__Descriptor = Descriptor.MessageTypes[17];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_CreateIndexResponse__Descriptor,
+ new string[] { });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexRequest__Descriptor = Descriptor.MessageTypes[18];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexRequest__Descriptor,
+ new string[] { "MainTableName", "IndexName", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexResponse__Descriptor = Descriptor.MessageTypes[19];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_DropIndexResponse__Descriptor,
+ new string[] { });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableRequest__Descriptor = Descriptor.MessageTypes[20];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableRequest__Descriptor,
+ new string[] { "TableName", "ReservedThroughput", "TableOptions", "StreamSpec", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableResponse__Descriptor = Descriptor.MessageTypes[21];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateTableResponse__Descriptor,
+ new string[] { "ReservedThroughputDetails", "TableOptions", "StreamDetails", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableRequest__Descriptor = Descriptor.MessageTypes[22];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableRequest__Descriptor,
+ new string[] { "TableName", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableResponse__Descriptor = Descriptor.MessageTypes[23];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_DescribeTableResponse__Descriptor,
+ new string[] { "TableMeta", "ReservedThroughputDetails", "TableOptions", "TableStatus", "StreamDetails", "ShardSplits", "IndexMetas", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableRequest__Descriptor = Descriptor.MessageTypes[24];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableRequest__Descriptor,
+ new string[] { });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableResponse__Descriptor = Descriptor.MessageTypes[25];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_ListTableResponse__Descriptor,
+ new string[] { "TableNames", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableRequest__Descriptor = Descriptor.MessageTypes[26];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableRequest__Descriptor,
+ new string[] { "TableName", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableResponse__Descriptor = Descriptor.MessageTypes[27];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_DeleteTableResponse__Descriptor,
+ new string[] { });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableRequest__Descriptor = Descriptor.MessageTypes[28];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableRequest__Descriptor,
+ new string[] { "TableName", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableResponse__Descriptor = Descriptor.MessageTypes[29];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_LoadTableResponse__Descriptor,
+ new string[] { });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableRequest__Descriptor = Descriptor.MessageTypes[30];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableRequest__Descriptor,
+ new string[] { "TableName", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableResponse__Descriptor = Descriptor.MessageTypes[31];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_UnloadTableResponse__Descriptor,
+ new string[] { });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_TimeRange__Descriptor = Descriptor.MessageTypes[32];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_TimeRange__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_TimeRange__Descriptor,
+ new string[] { "StartTime", "EndTime", "SpecificTime", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ReturnContent__Descriptor = Descriptor.MessageTypes[33];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_ReturnContent__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_ReturnContent__Descriptor,
+ new string[] { "ReturnType", "ReturnColumnNames", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowRequest__Descriptor = Descriptor.MessageTypes[34];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowRequest__Descriptor,
+ new string[] { "TableName", "PrimaryKey", "ColumnsToGet", "TimeRange", "MaxVersions", "CacheBlocks", "Filter", "StartColumn", "EndColumn", "Token", "TransactionId", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowResponse__Descriptor = Descriptor.MessageTypes[35];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_GetRowResponse__Descriptor,
+ new string[] { "Consumed", "Row", "NextToken", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowRequest__Descriptor = Descriptor.MessageTypes[36];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowRequest__Descriptor,
+ new string[] { "TableName", "RowChange", "Condition", "ReturnContent", "TransactionId", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowResponse__Descriptor = Descriptor.MessageTypes[37];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_UpdateRowResponse__Descriptor,
+ new string[] { "Consumed", "Row", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowRequest__Descriptor = Descriptor.MessageTypes[38];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowRequest__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable(internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowRequest__Descriptor,
+ new string[] { "TableName", "Row", "Condition", "ReturnContent", "TransactionId", });
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowResponse__Descriptor = Descriptor.MessageTypes[39];
+ internal__static_com_alicloud_openservices_tablestore_core_protocol_PutRowResponse__FieldAccessorTable =
+ new pb::FieldAccess.FieldAccessorTable