vastdb 0.1.7__tar.gz → 0.1.9__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {vastdb-0.1.7 → vastdb-0.1.9}/CHANGELOG.md +15 -0
- {vastdb-0.1.7/vastdb.egg-info → vastdb-0.1.9}/PKG-INFO +1 -1
- {vastdb-0.1.7 → vastdb-0.1.9}/README.md +19 -10
- {vastdb-0.1.7 → vastdb-0.1.9}/setup.py +1 -1
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/_internal.py +34 -18
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/conftest.py +16 -2
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/errors.py +12 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/schema.py +2 -1
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/table.py +63 -48
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_projections.py +5 -1
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_sanity.py +2 -3
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_tables.py +40 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/util.py +8 -1
- vastdb-0.1.9/vastdb/vast_tests/__init__.py +0 -0
- vastdb-0.1.9/vastdb/vast_tests/test_ha.py +29 -0
- {vastdb-0.1.7 → vastdb-0.1.9/vastdb.egg-info}/PKG-INFO +1 -1
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb.egg-info/SOURCES.txt +3 -1
- {vastdb-0.1.7 → vastdb-0.1.9}/LICENSE +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/MANIFEST.in +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/requirements.txt +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/setup.cfg +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Aggregate.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/ArraySlice.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/ArraySubscript.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/BinaryLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/BooleanLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Bound.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Call.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/CaseFragment.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Cast.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/ConcreteBoundImpl.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/ConditionalCase.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/CurrentRow.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/DateLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/DecimalLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Deref.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/DurationLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Expression.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/ExpressionImpl.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/FieldIndex.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/FieldRef.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Filter.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/FixedSizeBinaryLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Float16Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Float32Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Float64Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Following.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Frame.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Grouping.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Int16Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Int32Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Int64Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Int8Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/IntervalLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/IntervalLiteralDaysMilliseconds.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/IntervalLiteralImpl.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/IntervalLiteralMonths.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Join.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/JoinKind.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/KeyValue.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Limit.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/ListLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/LiteralColumn.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/LiteralImpl.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/LiteralRelation.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/MapKey.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/MapLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/OrderBy.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Ordering.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Plan.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Preceding.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Project.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/RelId.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Relation.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/RelationImpl.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/SetOpKind.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/SetOperation.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/SimpleCase.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/SortKey.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Source.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/StringLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/StructField.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/StructLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/TimeLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/TimestampLiteral.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/UInt16Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/UInt32Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/UInt64Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/UInt8Literal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/Unbounded.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/WindowCall.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/computeir/flatbuf/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Binary.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Block.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/BodyCompression.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/BodyCompressionMethod.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Bool.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Buffer.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/CompressionType.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Date.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/DateUnit.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Decimal.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/DictionaryBatch.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/DictionaryEncoding.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/DictionaryKind.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Duration.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Endianness.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Feature.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Field.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/FieldNode.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/FixedSizeBinary.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/FixedSizeList.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/FloatingPoint.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Footer.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Int.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Interval.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/IntervalUnit.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/KeyValue.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/LargeBinary.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/LargeList.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/LargeUtf8.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/List.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Map.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Message.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/MessageHeader.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/MetadataVersion.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Null.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Precision.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/RecordBatch.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Schema.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/SparseMatrixCompressedAxis.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/SparseMatrixIndexCSX.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/SparseTensor.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/SparseTensorIndex.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/SparseTensorIndexCOO.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/SparseTensorIndexCSF.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Struct_.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Tensor.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/TensorDim.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Time.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/TimeUnit.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Timestamp.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Type.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Union.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/UnionMode.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/Utf8.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/org/apache/arrow/flatbuf/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/AlterColumnRequest.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/AlterProjectionTableRequest.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/AlterSchemaRequest.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/AlterTableRequest.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/Column.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/ColumnType.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/CreateProjectionRequest.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/CreateSchemaRequest.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/GetProjectionTableStatsResponse.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/GetTableStatsResponse.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/ImportDataRequest.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/ListProjectionsResponse.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/ListSchemasResponse.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/ListTablesResponse.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/ObjectDetails.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/S3File.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/VipRange.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vast_flatbuf/tabular/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/bench/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/bench/test_perf.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/bucket.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/session.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/__init__.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_duckdb.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_imports.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_nested.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_schemas.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/test_util.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/tests/util.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb/transaction.py +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb.egg-info/dependency_links.txt +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb.egg-info/requires.txt +0 -0
- {vastdb-0.1.7 → vastdb-0.1.9}/vastdb.egg-info/top_level.txt +0 -0
|
@@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|
6
6
|
|
|
7
|
+
## [0.1.9] (2024-07-01)
|
|
8
|
+
[0.1.9]: https://github.com/vast-data/vastdb_sdk/compare/v0.1.8...v0.1.9
|
|
9
|
+
|
|
10
|
+
## Fixed
|
|
11
|
+
- Don't drop timezone information when creating a table
|
|
12
|
+
- Clarify the catalog example
|
|
13
|
+
|
|
14
|
+
## [0.1.8] (2024-06-26)
|
|
15
|
+
[0.1.8]: https://github.com/vast-data/vastdb_sdk/compare/v0.1.7...v0.1.8
|
|
16
|
+
|
|
17
|
+
## Fixed
|
|
18
|
+
- Allow retries also during query response parsing
|
|
19
|
+
- Don't retrieve stats during Table.select() if not needed
|
|
20
|
+
- Log successful server-side file import
|
|
21
|
+
|
|
7
22
|
## [0.1.7] (2024-06-03)
|
|
8
23
|
[0.1.7]: https://github.com/vast-data/vastdb_sdk/compare/v0.1.6...v0.1.7
|
|
9
24
|
|
|
@@ -65,7 +65,7 @@ with session.transaction() as tx:
|
|
|
65
65
|
|
|
66
66
|
# run `SELECT * FROM t`
|
|
67
67
|
reader = table.select() # return a `pyarrow.RecordBatchReader`
|
|
68
|
-
result =
|
|
68
|
+
result = reader.read_all() # build an PyArrow Table from the `pyarrow.RecordBatch` objects read from VAST
|
|
69
69
|
assert result == arrow_table
|
|
70
70
|
|
|
71
71
|
# the transaction is automatically committed when exiting the context
|
|
@@ -176,18 +176,27 @@ batches = snaps[0].schema('schema-name').table('table-name').select()
|
|
|
176
176
|
[VAST Catalog](https://vastdata.com/blog/vast-catalog-treat-your-file-system-like-a-database) can be queried as a regular table:
|
|
177
177
|
|
|
178
178
|
```python
|
|
179
|
-
|
|
180
|
-
|
|
179
|
+
import pyarrow as pa
|
|
180
|
+
import vastdb
|
|
181
|
+
|
|
182
|
+
session = vastdb.connect(
|
|
183
|
+
endpoint='http://vip-pool.v123-xy.VastENG.lab',
|
|
184
|
+
access=AWS_ACCESS_KEY_ID,
|
|
185
|
+
secret=AWS_SECRET_ACCESS_KEY)
|
|
186
|
+
|
|
187
|
+
with session.transaction() as tx:
|
|
188
|
+
table = tx.catalog().select(['element_type']).read_all()
|
|
189
|
+
df = table.to_pandas()
|
|
181
190
|
|
|
182
|
-
total_elements = len(df)
|
|
183
|
-
print(f"Total elements in the catalog: {total_elements}")
|
|
191
|
+
total_elements = len(df)
|
|
192
|
+
print(f"Total elements in the catalog: {total_elements}")
|
|
184
193
|
|
|
185
|
-
file_count = (df['element_type'] == 'FILE').sum()
|
|
186
|
-
print(f"Number of files/objects: {file_count}")
|
|
194
|
+
file_count = (df['element_type'] == 'FILE').sum()
|
|
195
|
+
print(f"Number of files/objects: {file_count}")
|
|
187
196
|
|
|
188
|
-
distinct_elements = df['element_type'].unique()
|
|
189
|
-
print("Distinct element types on the system:")
|
|
190
|
-
print(distinct_elements)
|
|
197
|
+
distinct_elements = df['element_type'].unique()
|
|
198
|
+
print("Distinct element types on the system:")
|
|
199
|
+
print(distinct_elements)
|
|
191
200
|
```
|
|
192
201
|
|
|
193
202
|
See the following blog posts for more examples:
|
|
@@ -722,23 +722,30 @@ def _parse_table_info(obj):
|
|
|
722
722
|
TableStatsResult = namedtuple("TableStatsResult", ["num_rows", "size_in_bytes", "is_external_rowid_alloc", "endpoints"])
|
|
723
723
|
|
|
724
724
|
|
|
725
|
+
_RETRIABLE_EXCEPTIONS = (
|
|
726
|
+
errors.ConnectionError, # only if 'may_retry' is True
|
|
727
|
+
errors.Slowdown,
|
|
728
|
+
)
|
|
729
|
+
|
|
730
|
+
|
|
725
731
|
def _backoff_giveup(exc: Exception) -> bool:
|
|
732
|
+
"""Exception types below MUST be part of `_RETRIABLE_EXCEPTIONS` above."""
|
|
726
733
|
|
|
734
|
+
_logger.info("Backoff giveup: %r", exc)
|
|
727
735
|
if isinstance(exc, errors.Slowdown):
|
|
728
|
-
# the server is overloaded,
|
|
729
|
-
return False
|
|
736
|
+
return False # the server is overloaded, don't give up
|
|
730
737
|
|
|
731
|
-
if isinstance(exc,
|
|
732
|
-
if exc.
|
|
733
|
-
#
|
|
734
|
-
return False
|
|
738
|
+
if isinstance(exc, errors.ConnectionError):
|
|
739
|
+
if exc.may_retry:
|
|
740
|
+
return False # don't give up of retriable connection errors
|
|
735
741
|
|
|
736
|
-
return True #
|
|
742
|
+
return True # give up in case of other exceptions
|
|
737
743
|
|
|
738
744
|
|
|
739
745
|
@dataclass
|
|
740
746
|
class BackoffConfig:
|
|
741
747
|
wait_gen: Callable = field(default=backoff.expo)
|
|
748
|
+
max_value: Optional[float] = None # max duration for a single wait period
|
|
742
749
|
max_tries: int = 10
|
|
743
750
|
max_time: float = 60.0 # in seconds
|
|
744
751
|
backoff_log_level: int = logging.DEBUG
|
|
@@ -767,14 +774,15 @@ class VastdbApi:
|
|
|
767
774
|
self._session.headers['user-agent'] = self.client_sdk_version
|
|
768
775
|
|
|
769
776
|
backoff_config = backoff_config or BackoffConfig()
|
|
770
|
-
|
|
777
|
+
self._backoff_decorator = backoff.on_exception(
|
|
771
778
|
wait_gen=backoff_config.wait_gen,
|
|
772
|
-
exception=
|
|
779
|
+
exception=_RETRIABLE_EXCEPTIONS,
|
|
773
780
|
giveup=_backoff_giveup,
|
|
774
781
|
max_tries=backoff_config.max_tries,
|
|
775
782
|
max_time=backoff_config.max_time,
|
|
783
|
+
max_value=backoff_config.max_value, # passed to `backoff_config.wait_gen`
|
|
776
784
|
backoff_log_level=backoff_config.backoff_log_level)
|
|
777
|
-
self._request =
|
|
785
|
+
self._request = self._backoff_decorator(self._single_request)
|
|
778
786
|
|
|
779
787
|
if url.port in {80, 443, None}:
|
|
780
788
|
self.aws_host = f'{url.host}'
|
|
@@ -812,7 +820,14 @@ class VastdbApi:
|
|
|
812
820
|
raise NotImplementedError(msg)
|
|
813
821
|
|
|
814
822
|
def _single_request(self, *, method, url, skip_status_check=False, **kwargs):
|
|
815
|
-
|
|
823
|
+
_logger.debug("Sending request: %s %s %s", method, url, kwargs)
|
|
824
|
+
try:
|
|
825
|
+
res = self._session.request(method=method, url=url, **kwargs)
|
|
826
|
+
except requests.exceptions.ConnectionError as err:
|
|
827
|
+
# low-level connection issue, it is safe to retry only read-only requests
|
|
828
|
+
may_retry = (method == "GET")
|
|
829
|
+
raise errors.ConnectionError(cause=err, may_retry=may_retry) from err
|
|
830
|
+
|
|
816
831
|
if not skip_status_check:
|
|
817
832
|
if exc := errors.from_response(res):
|
|
818
833
|
raise exc # application-level error
|
|
@@ -1380,7 +1395,8 @@ class VastdbApi:
|
|
|
1380
1395
|
|
|
1381
1396
|
url_params = self._build_query_data_url_params(projection, query_imports_table)
|
|
1382
1397
|
|
|
1383
|
-
|
|
1398
|
+
# The retries will be done during SelectSplitState processing:
|
|
1399
|
+
return self._single_request(
|
|
1384
1400
|
method="GET",
|
|
1385
1401
|
url=self._url(bucket=bucket, schema=schema, table=table, command="data", url_params=url_params),
|
|
1386
1402
|
data=params, headers=headers, stream=True)
|
|
@@ -1460,6 +1476,10 @@ class VastdbApi:
|
|
|
1460
1476
|
else:
|
|
1461
1477
|
_logger.debug("import_data of object name '%s' is in progress. "
|
|
1462
1478
|
"status: %s", chunk_dict['object_name'], chunk_dict['res'])
|
|
1479
|
+
if chunk_dict['res'] == 'Success':
|
|
1480
|
+
_logger.info("imported /%s/%s into table=/%s/%s/%s",
|
|
1481
|
+
chunk_dict['bucket_name'], chunk_dict['object_name'],
|
|
1482
|
+
bucket, schema, table)
|
|
1463
1483
|
return response
|
|
1464
1484
|
|
|
1465
1485
|
headers = self._fill_common_headers(txid=txid, client_tags=client_tags)
|
|
@@ -1792,15 +1812,12 @@ def _iter_query_data_response_columns(fileobj, stream_ids=None):
|
|
|
1792
1812
|
yield (stream_id, next_row_id, table)
|
|
1793
1813
|
|
|
1794
1814
|
|
|
1795
|
-
def parse_query_data_response(conn, schema, stream_ids=None,
|
|
1815
|
+
def parse_query_data_response(conn, schema, stream_ids=None, debug=False, parser: Optional[QueryDataParser] = None):
|
|
1796
1816
|
"""
|
|
1797
1817
|
Generates pyarrow.Table objects from QueryData API response stream.
|
|
1798
1818
|
|
|
1799
1819
|
A pyarrow.Table is a helper class that combines a Schema with multiple RecordBatches and allows easy data access.
|
|
1800
1820
|
"""
|
|
1801
|
-
if start_row_ids is None:
|
|
1802
|
-
start_row_ids = {}
|
|
1803
|
-
|
|
1804
1821
|
is_empty_projection = (len(schema) == 0)
|
|
1805
1822
|
if parser is None:
|
|
1806
1823
|
parser = QueryDataParser(schema, debug=debug)
|
|
@@ -1819,8 +1836,7 @@ def parse_query_data_response(conn, schema, stream_ids=None, start_row_ids=None,
|
|
|
1819
1836
|
|
|
1820
1837
|
_logger.debug("stream_id=%d rows=%d next_row_id=%d table=%s",
|
|
1821
1838
|
stream_id, len(parsed_table), next_row_id, parsed_table)
|
|
1822
|
-
|
|
1823
|
-
yield parsed_table # the result of a single "select_rows()" cycle
|
|
1839
|
+
yield stream_id, next_row_id, parsed_table
|
|
1824
1840
|
|
|
1825
1841
|
if states:
|
|
1826
1842
|
raise EOFError(f'all streams should be done before EOF. {states}')
|
|
@@ -9,11 +9,15 @@ import vastdb
|
|
|
9
9
|
|
|
10
10
|
def pytest_addoption(parser):
|
|
11
11
|
parser.addoption("--tabular-bucket-name", help="Name of the S3 bucket with Tabular enabled", default="vastdb")
|
|
12
|
-
parser.addoption("--tabular-access-key", help="Access key with Tabular permissions (AWS_ACCESS_KEY_ID)",
|
|
13
|
-
|
|
12
|
+
parser.addoption("--tabular-access-key", help="Access key with Tabular permissions (AWS_ACCESS_KEY_ID)",
|
|
13
|
+
default=os.environ.get("AWS_ACCESS_KEY_ID", None))
|
|
14
|
+
parser.addoption("--tabular-secret-key", help="Secret key with Tabular permissions (AWS_SECRET_ACCESS_KEY)",
|
|
15
|
+
default=os.environ.get("AWS_SECRET_ACCESS_KEY", None))
|
|
14
16
|
parser.addoption("--tabular-endpoint-url", help="Tabular server endpoint", default="http://localhost:9090")
|
|
15
17
|
parser.addoption("--data-path", help="Data files location", default=None)
|
|
16
18
|
parser.addoption("--crater-path", help="Save benchmark results in a dedicated location", default=None)
|
|
19
|
+
parser.addoption("--schema-name", help="Name of schema for the test to operate on", default=None)
|
|
20
|
+
parser.addoption("--table-name", help="Name of table for the test to operate on", default=None)
|
|
17
21
|
|
|
18
22
|
|
|
19
23
|
@pytest.fixture(scope="session")
|
|
@@ -67,3 +71,13 @@ def parquets_path(request):
|
|
|
67
71
|
@pytest.fixture(scope="function")
|
|
68
72
|
def crater_path(request):
|
|
69
73
|
return request.config.getoption("--crater-path")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@pytest.fixture(scope="function")
|
|
77
|
+
def schema_name(request):
|
|
78
|
+
return request.config.getoption("--schema-name")
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@pytest.fixture(scope="function")
|
|
82
|
+
def table_name(request):
|
|
83
|
+
return request.config.getoption("--table-name")
|
|
@@ -3,6 +3,7 @@ import xml.etree.ElementTree
|
|
|
3
3
|
from dataclasses import dataclass
|
|
4
4
|
from enum import Enum
|
|
5
5
|
|
|
6
|
+
import pyarrow as pa
|
|
6
7
|
import requests
|
|
7
8
|
|
|
8
9
|
|
|
@@ -169,12 +170,23 @@ class NotSupportedCommand(NotSupported):
|
|
|
169
170
|
table: str
|
|
170
171
|
|
|
171
172
|
|
|
173
|
+
@dataclass
|
|
174
|
+
class NotSupportedType(NotSupported):
|
|
175
|
+
field: pa.Field
|
|
176
|
+
|
|
177
|
+
|
|
172
178
|
@dataclass
|
|
173
179
|
class NotSupportedVersion(NotSupported):
|
|
174
180
|
err_msg: str
|
|
175
181
|
version: str
|
|
176
182
|
|
|
177
183
|
|
|
184
|
+
@dataclass
|
|
185
|
+
class ConnectionError(Exception):
|
|
186
|
+
cause: Exception
|
|
187
|
+
may_retry: bool
|
|
188
|
+
|
|
189
|
+
|
|
178
190
|
def handle_unavailable(**kwargs):
|
|
179
191
|
if kwargs['code'] == 'SlowDown':
|
|
180
192
|
raise Slowdown(**kwargs)
|
|
@@ -10,7 +10,7 @@ from typing import TYPE_CHECKING, Iterable, List, Optional
|
|
|
10
10
|
|
|
11
11
|
import pyarrow as pa
|
|
12
12
|
|
|
13
|
-
from . import bucket, errors, schema, table
|
|
13
|
+
from . import bucket, errors, schema, table, util
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
16
|
from .table import Table
|
|
@@ -86,6 +86,7 @@ class Schema:
|
|
|
86
86
|
if use_external_row_ids_allocation:
|
|
87
87
|
self.tx._rpc.features.check_external_row_ids_allocation()
|
|
88
88
|
|
|
89
|
+
util.check_supported_types(columns)
|
|
89
90
|
self.tx._rpc.api.create_table(self.bucket.name, self.name, table_name, columns, txid=self.tx.txid,
|
|
90
91
|
use_external_row_ids_allocation=use_external_row_ids_allocation)
|
|
91
92
|
log.info("Created table: %s", table_name)
|
|
@@ -7,12 +7,11 @@ import queue
|
|
|
7
7
|
from dataclasses import dataclass, field
|
|
8
8
|
from math import ceil
|
|
9
9
|
from threading import Event
|
|
10
|
-
from typing import
|
|
10
|
+
from typing import Callable, Dict, Iterable, List, Optional, Tuple, Union
|
|
11
11
|
|
|
12
|
-
import backoff
|
|
13
12
|
import ibis
|
|
14
13
|
import pyarrow as pa
|
|
15
|
-
import
|
|
14
|
+
import urllib3
|
|
16
15
|
|
|
17
16
|
from . import _internal, errors, schema, util
|
|
18
17
|
|
|
@@ -40,12 +39,6 @@ class TableStats:
|
|
|
40
39
|
endpoints: Tuple[str, ...] = ()
|
|
41
40
|
|
|
42
41
|
|
|
43
|
-
RETRIABLE_ERRORS = (
|
|
44
|
-
errors.Slowdown,
|
|
45
|
-
requests.exceptions.ConnectionError,
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
|
|
49
42
|
@dataclass
|
|
50
43
|
class QueryConfig:
|
|
51
44
|
"""Query execution configiration."""
|
|
@@ -85,9 +78,6 @@ class QueryConfig:
|
|
|
85
78
|
# - if unset, the request will be added to the queue's end.
|
|
86
79
|
queue_priority: Optional[int] = None
|
|
87
80
|
|
|
88
|
-
# DEPRECATED: will be removed in a future release
|
|
89
|
-
backoff_func: Any = field(default=backoff.on_exception(backoff.expo, RETRIABLE_ERRORS, max_tries=10))
|
|
90
|
-
|
|
91
81
|
|
|
92
82
|
@dataclass
|
|
93
83
|
class ImportConfig:
|
|
@@ -107,37 +97,53 @@ class SelectSplitState:
|
|
|
107
97
|
self.query_data_request = query_data_request
|
|
108
98
|
self.table = table
|
|
109
99
|
|
|
110
|
-
def
|
|
111
|
-
"""Execute QueryData
|
|
100
|
+
def process_split(self, api: _internal.VastdbApi, record_batches_queue: queue.Queue[pa.RecordBatch], check_stop: Callable):
|
|
101
|
+
"""Execute a sequence of QueryData requests, and queue the parsed RecordBatch objects.
|
|
112
102
|
|
|
113
|
-
Can be called repeatedly, to
|
|
103
|
+
Can be called repeatedly, to support resuming the query after a disconnection / retriable error.
|
|
114
104
|
"""
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
105
|
+
try:
|
|
106
|
+
# contains RecordBatch parts received from the server, must be re-created in case of a retry
|
|
107
|
+
while not self.done:
|
|
108
|
+
# raises if request parsing fails or throttled due to server load, and will be externally retried
|
|
109
|
+
response = api.query_data(
|
|
110
|
+
bucket=self.table.bucket.name,
|
|
111
|
+
schema=self.table.schema.name,
|
|
112
|
+
table=self.table.name,
|
|
113
|
+
params=self.query_data_request.serialized,
|
|
114
|
+
split=(self.split_id, self.config.num_splits, self.config.num_row_groups_per_sub_split),
|
|
115
|
+
num_sub_splits=self.config.num_sub_splits,
|
|
116
|
+
response_row_id=False,
|
|
117
|
+
txid=self.table.tx.txid,
|
|
118
|
+
limit_rows=self.config.limit_rows_per_sub_split,
|
|
119
|
+
sub_split_start_row_ids=self.subsplits_state.items(),
|
|
120
|
+
schedule_id=self.config.queue_priority,
|
|
121
|
+
enable_sorted_projections=self.config.use_semi_sorted_projections,
|
|
122
|
+
query_imports_table=self.table._imports_table,
|
|
123
|
+
projection=self.config.semi_sorted_projection_name)
|
|
124
|
+
|
|
125
|
+
# can raise during response parsing (e.g. due to disconnections), and will be externally retried
|
|
126
|
+
# the pagination state is stored in `self.subsplits_state` and must be correct in case of a reconnection
|
|
127
|
+
# the partial RecordBatch chunks are managed internally in `parse_query_data_response`
|
|
128
|
+
response_iter = _internal.parse_query_data_response(
|
|
129
|
+
conn=response.raw,
|
|
130
|
+
schema=self.query_data_request.response_schema,
|
|
131
|
+
parser=self.query_data_request.response_parser)
|
|
132
|
+
|
|
133
|
+
for stream_id, next_row_id, table_chunk in response_iter:
|
|
134
|
+
# in case of I/O error, `response_iter` will be closed and an appropriate exception will be thrown.
|
|
135
|
+
self.subsplits_state[stream_id] = next_row_id
|
|
136
|
+
# we have parsed a pyarrow.Table successfully, self.subsplits_state is now correctly updated
|
|
137
|
+
# if the below loop fails, the query is not retried
|
|
138
|
+
for batch in table_chunk.to_batches():
|
|
139
|
+
check_stop() # may raise StoppedException to early-exit the query (without retries)
|
|
140
|
+
if batch:
|
|
141
|
+
record_batches_queue.put(batch)
|
|
142
|
+
except urllib3.exceptions.ProtocolError as err:
|
|
143
|
+
log.warning("Failed parsing QueryData response table=%r split=%s/%s offsets=%s cause=%s",
|
|
144
|
+
self.table, self.split_id, self.config.num_splits, self.subsplits_state, err)
|
|
145
|
+
# since this is a read-only idempotent operation, it is safe to retry
|
|
146
|
+
raise errors.ConnectionError(cause=err, may_retry=True)
|
|
141
147
|
|
|
142
148
|
@property
|
|
143
149
|
def done(self):
|
|
@@ -321,10 +327,15 @@ class Table:
|
|
|
321
327
|
if config is None:
|
|
322
328
|
config = QueryConfig()
|
|
323
329
|
|
|
324
|
-
#
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
330
|
+
# Retrieve snapshots only if needed
|
|
331
|
+
if config.data_endpoints is None or config.num_splits is None:
|
|
332
|
+
stats = self.get_stats()
|
|
333
|
+
log.debug("stats: %s", stats)
|
|
334
|
+
|
|
335
|
+
if config.data_endpoints is None:
|
|
336
|
+
endpoints = stats.endpoints
|
|
337
|
+
else:
|
|
338
|
+
endpoints = tuple(config.data_endpoints)
|
|
328
339
|
log.debug("endpoints: %s", endpoints)
|
|
329
340
|
|
|
330
341
|
if config.num_splits is None:
|
|
@@ -382,6 +393,7 @@ class Table:
|
|
|
382
393
|
def single_endpoint_worker(endpoint: str):
|
|
383
394
|
try:
|
|
384
395
|
host_api = _internal.VastdbApi(endpoint=endpoint, access_key=self.tx._rpc.api.access_key, secret_key=self.tx._rpc.api.secret_key)
|
|
396
|
+
backoff_decorator = self.tx._rpc.api._backoff_decorator
|
|
385
397
|
while True:
|
|
386
398
|
check_stop()
|
|
387
399
|
try:
|
|
@@ -395,9 +407,9 @@ class Table:
|
|
|
395
407
|
split_id=split,
|
|
396
408
|
config=config)
|
|
397
409
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
410
|
+
process_with_retries = backoff_decorator(split_state.process_split)
|
|
411
|
+
process_with_retries(host_api, record_batches_queue, check_stop)
|
|
412
|
+
|
|
401
413
|
except StoppedException:
|
|
402
414
|
log.debug("stop signal.", exc_info=True)
|
|
403
415
|
return
|
|
@@ -474,6 +486,7 @@ class Table:
|
|
|
474
486
|
raise errors.NotSupportedCommand(self.bucket.name, self.schema.name, self.name)
|
|
475
487
|
try:
|
|
476
488
|
row_ids = []
|
|
489
|
+
util.check_supported_types(rows.schema)
|
|
477
490
|
serialized_slices = util.iter_serialized_slices(rows, MAX_INSERT_ROWS_PER_PATCH)
|
|
478
491
|
for slice in serialized_slices:
|
|
479
492
|
res = self.tx._rpc.api.insert_rows(self.bucket.name, self.schema.name, self.name, record_batch=slice,
|
|
@@ -516,6 +529,7 @@ class Table:
|
|
|
516
529
|
|
|
517
530
|
update_rows_rb = util.sort_record_batch_if_needed(update_rows_rb, INTERNAL_ROW_ID)
|
|
518
531
|
|
|
532
|
+
util.check_supported_types(update_rows_rb.schema)
|
|
519
533
|
serialized_slices = util.iter_serialized_slices(update_rows_rb, MAX_ROWS_PER_BATCH)
|
|
520
534
|
for slice in serialized_slices:
|
|
521
535
|
self.tx._rpc.api.update_rows(self.bucket.name, self.schema.name, self.name, record_batch=slice,
|
|
@@ -560,6 +574,7 @@ class Table:
|
|
|
560
574
|
"""Add a new column."""
|
|
561
575
|
if self._imports_table:
|
|
562
576
|
raise errors.NotSupportedCommand(self.bucket.name, self.schema.name, self.name)
|
|
577
|
+
util.check_supported_types(new_column)
|
|
563
578
|
self.tx._rpc.api.add_columns(self.bucket.name, self.schema.name, self.name, new_column, txid=self.tx.txid)
|
|
564
579
|
log.info("Added column(s): %s", new_column)
|
|
565
580
|
self.arrow_schema = self.columns()
|
|
@@ -105,7 +105,11 @@ def test_query_data_with_projection(session, clean_bucket_name):
|
|
|
105
105
|
t = s.table(table_name)
|
|
106
106
|
projection_actual = pa.Table.from_batches(t.select(columns=['a', 'b', 's'], predicate=(t['b'] < 5), config=config))
|
|
107
107
|
# no projection supply - need to be with p1 projeciton
|
|
108
|
-
|
|
108
|
+
# doing this since we also run this test against production clusters
|
|
109
|
+
if expected_projection_p1 != projection_actual:
|
|
110
|
+
config.num_row_groups_per_sub_split = 8
|
|
111
|
+
projection_actual = pa.Table.from_batches(t.select(columns=['a', 'b', 's'], predicate=(t['b'] < 5), config=config))
|
|
112
|
+
assert expected_projection_p1 == projection_actual
|
|
109
113
|
|
|
110
114
|
config.semi_sorted_projection_name = 'p1'
|
|
111
115
|
projection_actual = pa.Table.from_batches(t.select(columns=['a', 'b', 's'], predicate=(t['b'] < 5), config=config))
|
|
@@ -5,9 +5,8 @@ from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
|
5
5
|
from itertools import cycle
|
|
6
6
|
|
|
7
7
|
import pytest
|
|
8
|
-
import requests
|
|
9
8
|
|
|
10
|
-
import vastdb
|
|
9
|
+
import vastdb.errors
|
|
11
10
|
|
|
12
11
|
log = logging.getLogger(__name__)
|
|
13
12
|
|
|
@@ -26,7 +25,7 @@ def test_bad_credentials(session):
|
|
|
26
25
|
|
|
27
26
|
def test_bad_endpoint(session):
|
|
28
27
|
backoff_config = vastdb.session.BackoffConfig(max_tries=3)
|
|
29
|
-
with pytest.raises(
|
|
28
|
+
with pytest.raises(vastdb.errors.ConnectionError):
|
|
30
29
|
vastdb.connect(access='BAD', secret='BAD', endpoint='http://invalid-host-name-for-tests:12345', backoff_config=backoff_config)
|
|
31
30
|
|
|
32
31
|
|
|
@@ -311,6 +311,46 @@ def test_types(session, clean_bucket_name):
|
|
|
311
311
|
assert select(t['ts9'] == ts_literal) == expected.filter(pc.field('ts9') == ts_literal)
|
|
312
312
|
|
|
313
313
|
|
|
314
|
+
TIMESTAMP_UNITS = ['s', 'ms', 'us', 'ns']
|
|
315
|
+
|
|
316
|
+
|
|
317
|
+
def test_unsupported_timezone(session, clean_bucket_name):
|
|
318
|
+
with session.transaction() as tx:
|
|
319
|
+
s = tx.bucket(clean_bucket_name).create_schema('s1')
|
|
320
|
+
for unit in TIMESTAMP_UNITS:
|
|
321
|
+
col_type = pa.timestamp(unit, 'UTC')
|
|
322
|
+
with pytest.raises(errors.NotSupportedType):
|
|
323
|
+
s.create_table('t1', pa.schema([('ts', col_type)]))
|
|
324
|
+
assert s.tables() == []
|
|
325
|
+
|
|
326
|
+
cols = [('c', pa.int64())]
|
|
327
|
+
t1 = s.create_table('t1', pa.schema(cols))
|
|
328
|
+
for unit in TIMESTAMP_UNITS:
|
|
329
|
+
col_type = pa.timestamp(unit, 'UTC')
|
|
330
|
+
with pytest.raises(errors.NotSupportedType):
|
|
331
|
+
t1.add_column(pa.schema([('ts', col_type)]))
|
|
332
|
+
|
|
333
|
+
cols = [(f'c_{unit}', pa.timestamp(unit)) for unit in TIMESTAMP_UNITS]
|
|
334
|
+
t2 = s.create_table('t2', pa.schema(cols))
|
|
335
|
+
|
|
336
|
+
for unit in TIMESTAMP_UNITS:
|
|
337
|
+
col_type = pa.timestamp(unit, 'UTC')
|
|
338
|
+
|
|
339
|
+
rb = pa.record_batch(
|
|
340
|
+
data=[[None]],
|
|
341
|
+
schema=pa.schema([(f'c_{unit}', col_type)]))
|
|
342
|
+
with pytest.raises(errors.NotSupportedType):
|
|
343
|
+
t2.insert(rb)
|
|
344
|
+
|
|
345
|
+
rb = pa.record_batch(
|
|
346
|
+
data=[[0], [None]],
|
|
347
|
+
schema=pa.schema([
|
|
348
|
+
(INTERNAL_ROW_ID, pa.uint64()),
|
|
349
|
+
(f'c_{unit}', col_type)]))
|
|
350
|
+
with pytest.raises(errors.NotSupportedType):
|
|
351
|
+
t2.update(rb)
|
|
352
|
+
|
|
353
|
+
|
|
314
354
|
def test_filters(session, clean_bucket_name):
|
|
315
355
|
columns = pa.schema([
|
|
316
356
|
('a', pa.int32()),
|
|
@@ -6,7 +6,7 @@ import pyarrow as pa
|
|
|
6
6
|
import pyarrow.compute as pc
|
|
7
7
|
import pyarrow.parquet as pq
|
|
8
8
|
|
|
9
|
-
from .errors import InvalidArgument, TooWideRow
|
|
9
|
+
from .errors import InvalidArgument, NotSupportedType, TooWideRow
|
|
10
10
|
|
|
11
11
|
log = logging.getLogger(__name__)
|
|
12
12
|
|
|
@@ -152,3 +152,10 @@ def sort_record_batch_if_needed(record_batch, sort_column):
|
|
|
152
152
|
return record_batch.sort_by(sort_column)
|
|
153
153
|
else:
|
|
154
154
|
return record_batch
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def check_supported_types(fields: pa.Schema):
|
|
158
|
+
for f in fields:
|
|
159
|
+
if isinstance(f.type, pa.TimestampType):
|
|
160
|
+
if f.type.tz:
|
|
161
|
+
raise NotSupportedType(f)
|
|
File without changes
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import time
|
|
3
|
+
|
|
4
|
+
import pyarrow as pa
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from vastdb.table import QueryConfig
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.ha
|
|
13
|
+
def test_ha_query(session, test_bucket_name, schema_name, table_name):
|
|
14
|
+
# runs in parallel to ha scenario
|
|
15
|
+
times_to_query, records_in_table = 50, 100_000_000
|
|
16
|
+
arrow_array = pa.array(range(0, records_in_table), type=pa.int64())
|
|
17
|
+
|
|
18
|
+
with session.transaction() as tx:
|
|
19
|
+
config = QueryConfig(num_splits=1, num_sub_splits=1)
|
|
20
|
+
start = time.time()
|
|
21
|
+
for i in range(times_to_query):
|
|
22
|
+
table = tx.bucket(test_bucket_name).schema(schema_name).table(table_name)
|
|
23
|
+
s = time.time()
|
|
24
|
+
res = table.select(config=config).read_all()
|
|
25
|
+
e = time.time()
|
|
26
|
+
logger.info(f'query number {i} took {e - s} sec')
|
|
27
|
+
assert arrow_array == pa.concat_arrays(res.column('a').chunks)
|
|
28
|
+
end = time.time()
|
|
29
|
+
logger.info(f'SDK test took {end - start}')
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|