feat:Geospatial Data Type and GIS Function support for milvus (#43661)

issue: #43427
pr: #37417

This pr's main goal is merge #37417 to milvus 2.5 without conflicts.

# Main Goals

1. Create and describe collections with geospatial type
2. Insert geospatial data into the insert binlog
3. Load segments containing geospatial data into memory
4. Enable query and search can display  geospatial data
5. Support using GIS funtions like ST_EQUALS in query

# Solution

1. **Add Type**: Modify the Milvus core by adding a Geospatial type in
both the C++ and Go code layers, defining the Geospatial data structure
and the corresponding interfaces.
2. **Dependency Libraries**: Introduce necessary geospatial data
processing libraries. In the C++ source code, use Conan package
management to include the GDAL library. In the Go source code, add the
go-geom library to the go.mod file.
3. **Protocol Interface**: Revise the Milvus protocol to provide
mechanisms for Geospatial message serialization and deserialization.
4. **Data Pipeline**: Facilitate interaction between the client and
proxy using the WKT format for geospatial data. The proxy will convert
all data into WKB format for downstream processing, providing column
data interfaces, segment encapsulation, segment loading, payload
writing, and cache block management.
5. **Query Operators**: Implement simple display and support for filter
queries. Initially, focus on filtering based on spatial relationships
for a single column of geospatial literal values, providing parsing and
execution for query expressions.Now only support brutal search
6. **Client Modification**: Enable the client to handle user input for
geospatial data and facilitate end-to-end testing.Check the modification
in pymilvus.

---------

Signed-off-by: Yinwei Li <yinwei.li@zilliz.com>
Signed-off-by: Cai Zhang <cai.zhang@zilliz.com>
Co-authored-by: cai.zhang <cai.zhang@zilliz.com>
This commit is contained in:
ZhuXi 2025-08-26 19:11:55 +08:00 committed by GitHub
parent 8821743c17
commit cd931a0388
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
103 changed files with 5658 additions and 1143 deletions

117
client/column/geometry.go Normal file
View File

@ -0,0 +1,117 @@
package column
import (
"fmt"
"github.com/cockroachdb/errors"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
"github.com/milvus-io/milvus/client/v2/entity"
)
type ColumnGeometryBytes struct {
*genericColumnBase[[]byte]
}
// Name returns column name.
func (c *ColumnGeometryBytes) Name() string {
return c.name
}
// Type returns column entity.FieldType.
func (c *ColumnGeometryBytes) Type() entity.FieldType {
return entity.FieldTypeGeometry
}
// Len returns column values length.
func (c *ColumnGeometryBytes) Len() int {
return len(c.values)
}
func (c *ColumnGeometryBytes) Slice(start, end int) Column {
l := c.Len()
if start > l {
start = l
}
if end == -1 || end > l {
end = l
}
return &ColumnGeometryBytes{
genericColumnBase: c.genericColumnBase.slice(start, end),
}
}
// Get returns value at index as interface{}.
func (c *ColumnGeometryBytes) Get(idx int) (interface{}, error) {
if idx < 0 || idx >= c.Len() {
return nil, errors.New("index out of range")
}
return c.values[idx], nil
}
func (c *ColumnGeometryBytes) GetAsString(idx int) (string, error) {
bs, err := c.ValueByIdx(idx)
if err != nil {
return "", err
}
return string(bs), nil
}
// FieldData return column data mapped to schemapb.FieldData.
func (c *ColumnGeometryBytes) FieldData() *schemapb.FieldData {
fd := &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: c.name,
}
fd.Field = &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: c.values,
},
},
},
}
return fd
}
// ValueByIdx returns value of the provided index.
func (c *ColumnGeometryBytes) ValueByIdx(idx int) ([]byte, error) {
if idx < 0 || idx >= c.Len() {
return nil, errors.New("index out of range")
}
return c.values[idx], nil
}
// AppendValue append value into column.
func (c *ColumnGeometryBytes) AppendValue(i interface{}) error {
var v []byte
switch raw := i.(type) {
case []byte:
v = raw
case string:
v = []byte(raw)
default:
return fmt.Errorf("expect geometry compatible type([]byte, struct, map), got %T", i)
}
c.values = append(c.values, v)
return nil
}
// Data returns column data.
func (c *ColumnGeometryBytes) Data() [][]byte {
return c.values
}
func NewColumnGeometryBytes(name string, values [][]byte) *ColumnGeometryBytes {
return &ColumnGeometryBytes{
genericColumnBase: &genericColumnBase[[]byte]{
name: name,
fieldType: entity.FieldTypeGeometry,
values: values,
},
}
}

View File

@ -0,0 +1,82 @@
package column
import (
"fmt"
"math/rand"
"testing"
"time"
"github.com/stretchr/testify/suite"
"github.com/milvus-io/milvus/client/v2/entity"
)
type ColumnGeometryBytesSuite struct {
suite.Suite
}
func (s *ColumnGeometryBytesSuite) SetupSuite() {
rand.Seed(time.Now().UnixNano())
}
func (s *ColumnGeometryBytesSuite) TestAttrMethods() {
columnName := fmt.Sprintf("column_Geometrybs_%d", rand.Int())
columnLen := 8 + rand.Intn(10)
v := make([][]byte, columnLen)
column := NewColumnGeometryBytes(columnName, v)
s.Run("test_meta", func() {
ft := entity.FieldTypeGeometry
s.Equal("Geometry", ft.Name())
s.Equal("Geometry", ft.String())
pbName, pbType := ft.PbFieldType()
s.Equal("Geometry", pbName)
s.Equal("Geometry", pbType)
})
s.Run("test_column_attribute", func() {
s.Equal(columnName, column.Name())
s.Equal(entity.FieldTypeGeometry, column.Type())
s.Equal(columnLen, column.Len())
s.EqualValues(v, column.Data())
})
s.Run("test_column_field_data", func() {
fd := column.FieldData()
s.NotNil(fd)
s.Equal(fd.GetFieldName(), columnName)
})
s.Run("test_column_valuer_by_idx", func() {
_, err := column.ValueByIdx(-1)
s.Error(err)
_, err = column.ValueByIdx(columnLen)
s.Error(err)
for i := 0; i < columnLen; i++ {
v, err := column.ValueByIdx(i)
s.NoError(err)
s.Equal(column.values[i], v)
}
})
s.Run("test_append_value", func() {
item := make([]byte, 10)
err := column.AppendValue(item)
s.NoError(err)
s.Equal(columnLen+1, column.Len())
val, err := column.ValueByIdx(columnLen)
s.NoError(err)
s.Equal(item, val)
err = column.AppendValue("POINT (30.123 -10.456)")
s.NoError(err)
err = column.AppendValue(1)
s.Error(err)
})
}
func TestColumnGeometryBytes(t *testing.T) {
suite.Run(t, new(ColumnGeometryBytesSuite))
}

View File

@ -54,6 +54,8 @@ func (t FieldType) Name() string {
return "Array"
case FieldTypeJSON:
return "JSON"
case FieldTypeGeometry:
return "Geometry"
case FieldTypeBinaryVector:
return "BinaryVector"
case FieldTypeFloatVector:
@ -92,6 +94,8 @@ func (t FieldType) String() string {
return "Array"
case FieldTypeJSON:
return "JSON"
case FieldTypeGeometry:
return "Geometry"
case FieldTypeBinaryVector:
return "[]byte"
case FieldTypeFloatVector:
@ -128,6 +132,8 @@ func (t FieldType) PbFieldType() (string, string) {
return "VarChar", "string"
case FieldTypeJSON:
return "JSON", "JSON"
case FieldTypeGeometry:
return "Geometry", "Geometry"
case FieldTypeBinaryVector:
return "[]byte", ""
case FieldTypeFloatVector:
@ -167,6 +173,8 @@ const (
FieldTypeArray FieldType = 22
// FieldTypeJSON field type JSON
FieldTypeJSON FieldType = 23
// FieldTypeGeometry field type Geometry
FieldTypeGeometry FieldType = 24
// FieldTypeBinaryVector field type binary vector
FieldTypeBinaryVector FieldType = 100
// FieldTypeFloatVector field type float vector

View File

@ -6,7 +6,7 @@ require (
github.com/blang/semver/v4 v4.0.0
github.com/cockroachdb/errors v1.9.1
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786
github.com/milvus-io/milvus/pkg/v2 v2.5.7
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/samber/lo v1.27.0

View File

@ -318,8 +318,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17 h1:LDOodBVtc2AYxcgc51vDwe+gJp96s6yhJLfdGbLrK+0=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786 h1:GspXs2i+sm2GE4n46VRWBjSCQjqtJDIwwcye+gFyxZA=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/milvus/pkg/v2 v2.5.7 h1:b45jq1s1v03AekFucs2/dkkXohB57gEx7gspJuAkfbY=
github.com/milvus-io/milvus/pkg/v2 v2.5.7/go.mod h1:pImw1IGNS7k/5yvlZV2tZi5vZu1VQRlQij+r39d+XnI=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=

View File

@ -212,6 +212,22 @@ func (s *MockSuiteBase) getJSONBytesFieldData(name string, data [][]byte, isDyna
}
}
func (s *MockSuiteBase) getGeometryBytesFieldData(name string, data [][]byte) *schemapb.FieldData {
return &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: name,
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: data,
},
},
},
},
}
}
func (s *MockSuiteBase) getFloatVectorFieldData(name string, dim int64, data []float32) *schemapb.FieldData {
return &schemapb.FieldData{
Type: schemapb.DataType_FloatVector,

38
go.mod
View File

@ -4,10 +4,11 @@ go 1.24.4
require (
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.1.0
github.com/aliyun/credentials-go v1.2.7
github.com/apache/arrow/go/v12 v12.0.1
github.com/apache/pulsar-client-go v0.6.1-0.20210728062540-29414db801a7 // indirect
github.com/bits-and-blooms/bloom/v3 v3.3.1
github.com/blang/semver/v4 v4.0.0
github.com/casbin/casbin/v2 v2.44.2
@ -21,7 +22,7 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/klauspost/compress v1.18.0
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786
github.com/minio/minio-go/v7 v7.0.73
github.com/panjf2000/ants/v2 v2.11.3 // indirect
github.com/pingcap/log v1.1.1-0.20221015072633-39906604fb81
@ -35,6 +36,7 @@ require (
github.com/spf13/cast v1.3.1
github.com/spf13/viper v1.8.1
github.com/stretchr/testify v1.10.0
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.865
github.com/tikv/client-go/v2 v2.0.4
go.etcd.io/etcd/api/v3 v3.5.5
@ -61,7 +63,7 @@ require (
github.com/bits-and-blooms/bitset v1.10.0
github.com/bytedance/mockey v1.2.14
github.com/bytedance/sonic v1.13.2
github.com/cenkalti/backoff/v4 v4.2.1
github.com/cenkalti/backoff/v4 v4.3.0
github.com/cockroachdb/redact v1.1.3
github.com/goccy/go-json v0.10.3
github.com/google/uuid v1.6.0
@ -73,6 +75,7 @@ require (
github.com/remeh/sizedwaitgroup v1.0.0
github.com/shirou/gopsutil/v4 v4.24.10
github.com/tidwall/gjson v1.17.1
github.com/twpayne/go-geom v1.5.7
github.com/valyala/fastjson v1.6.4
github.com/zeebo/xxh3 v1.0.2
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0
@ -98,7 +101,6 @@ require (
github.com/alibabacloud-go/debug v0.0.0-20190504072949-9472017b5c68 // indirect
github.com/alibabacloud-go/tea v1.1.8 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/apache/pulsar-client-go v0.6.1-0.20210728062540-29414db801a7 // indirect
github.com/apache/thrift v0.18.1 // indirect
github.com/ardielle/ardielle-go v1.5.2 // indirect
github.com/benesch/cgosymbolizer v0.0.0-20190515212042-bec6fe6e597b // indirect
@ -117,7 +119,7 @@ require (
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
github.com/ebitengine/purego v0.8.1 // indirect
@ -131,7 +133,7 @@ require (
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
@ -151,7 +153,7 @@ require (
github.com/gorilla/websocket v1.4.2 // indirect
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c // indirect
github.com/hashicorp/errwrap v1.0.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
@ -167,8 +169,8 @@ require (
github.com/kylelemons/godebug v1.1.0 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/linkedin/goavro/v2 v2.11.1 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.11 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
@ -197,12 +199,13 @@ require (
github.com/pingcap/kvproto v0.0.0-20221129023506-621ec37aac7a // indirect
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/rs/xid v1.5.0 // indirect
github.com/shirou/gopsutil/v3 v3.22.9 // indirect
github.com/shirou/gopsutil/v3 v3.24.2 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/smartystreets/assertions v1.2.0 // indirect
github.com/smartystreets/goconvey v1.7.2 // indirect
@ -214,13 +217,12 @@ require (
github.com/streamnative/pulsarctl v0.5.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
github.com/tiancaiamao/gp v0.0.0-20221230034425-4025bc8a4d4a // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tikv/pd/client v0.0.0-20221031025758-80f0d8ca4d07 // indirect
github.com/tklauser/go-sysconf v0.3.12 // indirect
github.com/tklauser/numcpus v0.6.1 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/twmb/murmur3 v1.1.6 // indirect
@ -237,13 +239,13 @@ require (
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
go.opentelemetry.io/otel/exporters/jaeger v1.13.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0 // indirect
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.20.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.0.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/automaxprocs v1.6.0 // indirect
golang.org/x/arch v0.11.0 // indirect
golang.org/x/mod v0.17.0 // indirect
@ -254,7 +256,7 @@ require (
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
gonum.org/v1/gonum v0.11.0 // indirect
google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect

81
go.sum
View File

@ -61,8 +61,8 @@ github.com/AthenZ/athenz v1.10.39 h1:mtwHTF/v62ewY2Z5KWhuZgVXftBej1/Tn80zx4DcawY
github.com/AthenZ/athenz v1.10.39/go.mod h1:3Tg8HLsiQZp81BJY58JBeU2BR6B/H4/0MQGfCwhHNEA=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM=
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0 h1:tfLQ34V6F7tVSwoTf/4lH5sE0o6eCJuNDTmH09nDpbc=
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo=
github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg=
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.2.0 h1:Ma67P/GGprNwsslzEH6+Kb8nybI8jpDTm4Wmzu2ReK8=
@ -77,6 +77,8 @@ github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/DataDog/zstd v1.5.0 h1:+K/VEwIAaPcHiMtQvpLD4lqW7f0Gk3xdYZmI1hD+CXo=
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/JohnCGriffin/overflow v0.0.0-20211019200055-46fa312c352c h1:RGWPOewvKIROun94nF7v2cua9qP+thov/7M50KEoeSU=
@ -93,6 +95,10 @@ github.com/actgardner/gogen-avro/v10 v10.2.1/go.mod h1:QUhjeHPchheYmMDni/Nx7VB0R
github.com/actgardner/gogen-avro/v9 v9.1.0/go.mod h1:nyTj6wPqDJoxM3qdnjcLv+EnMDSDFqE0qDpva2QRmKc=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -155,8 +161,8 @@ github.com/casbin/casbin/v2 v2.44.2/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRt
github.com/casbin/json-adapter/v2 v2.0.0 h1:nOCN3TK1CJKSNQQ/MnakbU9/cUcNR3N0AxBDnEBLSDI=
github.com/casbin/json-adapter/v2 v2.0.0/go.mod h1:LvsfPXXr8CD0ZFucAxawcY9Xb0FtLk3mozJ1qcSTUD4=
github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/certifi/gocertifi v0.0.0-20191021191039-0944d244cd40/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
github.com/certifi/gocertifi v0.0.0-20200922220541-2c3bb06c6054/go.mod h1:sGbDF6GwGcLpkNXPUTkMRoywsNa/ol15pxFe6ERfguA=
@ -227,8 +233,8 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4wg/adLLz5xh5CmpiCA=
github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
@ -314,8 +320,9 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
@ -354,8 +361,6 @@ github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeD
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.2.1 h1:OptwRhECazUx5ix5TTWC3EZhsZEHWcYWY4FQHTIubm4=
github.com/golang/glog v1.2.1/go.mod h1:6AhwSGph0fcJtXVM/PEHPqZlFeoLxhs7/t5UDAwmO+w=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@ -473,8 +478,8 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t
github.com/grpc-ecosystem/grpc-gateway v1.12.1/go.mod h1:8XEsbTttt/W+VvjtQhLACqCisSPWTxCZ7sBRjU6iH9c=
github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 h1:bkypFPDjIYGfCYD5mRBvpqxfYX1YCS1PXdKYWi8FsN0=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0/go.mod h1:P+Lt/0by1T8bfcF3z737NnSbmxQAppXMRziHUxPOC8k=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c h1:6rhixN/i8ZofjG1Y75iExal34USq5p+wiN1tpie8IrU=
github.com/gsterjov/go-libsecret v0.0.0-20161001094733-a6f4afe4910c/go.mod h1:NMPJylDgVpX0MLRlPy15sqSwOFv/U1GZ2m21JhFfek0=
github.com/hamba/avro v1.5.6/go.mod h1:3vNT0RLXXpFm2Tb/5KC71ZRJlOroggq1Rcitb6k4Fr8=
@ -506,6 +511,8 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/heetch/avro v0.3.1/go.mod h1:4xn38Oz/+hiEUTpbVfGVLfvOg0yKLlRP7Q9+gJJILgA=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
@ -601,12 +608,14 @@ github.com/linkedin/goavro/v2 v2.10.0/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF
github.com/linkedin/goavro/v2 v2.10.1/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
github.com/linkedin/goavro/v2 v2.11.1 h1:4cuAtbDfqkKnBXp9E+tRkIJGa6W6iAjwonwt8O1f4U0=
github.com/linkedin/goavro/v2 v2.11.1/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@ -639,8 +648,8 @@ github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119 h1:9VXijWu
github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b h1:TfeY0NxYxZzUfIfYe5qYDBzt4ZYRqzUjTR6CvUzjat8=
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b/go.mod h1:iwW+9cWfIzzDseEBCCeDSN5SD16Tidvy8cwQ7ZY8Qj4=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17 h1:LDOodBVtc2AYxcgc51vDwe+gJp96s6yhJLfdGbLrK+0=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786 h1:GspXs2i+sm2GE4n46VRWBjSCQjqtJDIwwcye+gFyxZA=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/pulsar-client-go v0.12.1 h1:O2JZp1tsYiO7C0MQ4hrUY/aJXnn2Gry6hpm7UodghmE=
github.com/milvus-io/pulsar-client-go v0.12.1/go.mod h1:dkutuH4oS2pXiGm+Ti7fQZ4MRjrMPZ8IJeEGAWMeckk=
github.com/minio/asm2plan9s v0.0.0-20200509001527-cdd76441f9d8 h1:AMFGa4R4MiIpspGNG7Z948v4n35fFGB3RR3G/ry4FWs=
@ -747,8 +756,9 @@ github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZ
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -813,10 +823,14 @@ github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtm
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA=
github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A=
github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y=
github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk=
github.com/shirou/gopsutil/v4 v4.24.10 h1:7VOzPtfw/5YDU+jLEoBwXwxJbQetULywoSV4RYY7HkM=
github.com/shirou/gopsutil/v4 v4.24.10/go.mod h1:s4D/wg+ag4rG0WO7AiTj2BeYCRhym0vM7DHbZRxnIT8=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/httpfs v0.0.0-20181222201310-74dc9339e414/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@ -883,6 +897,7 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
@ -903,12 +918,12 @@ github.com/tikv/client-go/v2 v2.0.4 h1:cPtMXTExqjzk8L40qhrgB/mXiBXKP5LRU0vwjtI2X
github.com/tikv/client-go/v2 v2.0.4/go.mod h1:v52O5zDtv2BBus4lm5yrSQhxGW4Z4RaXWfg0U1Kuyqo=
github.com/tikv/pd/client v0.0.0-20221031025758-80f0d8ca4d07 h1:ckPpxKcl75mO2N6a4cJXiZH43hvcHPpqc9dh1TmH1nc=
github.com/tikv/pd/client v0.0.0-20221031025758-80f0d8ca4d07/go.mod h1:CipBxPfxPUME+BImx9MUYXCnAVLS3VJUr3mnSJwh40A=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -916,6 +931,8 @@ github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/twmb/murmur3 v1.1.6 h1:mqrRot1BRxm+Yct+vavLMou2/iJt0tNVTTC0QoIjaZg=
github.com/twmb/murmur3 v1.1.6/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
github.com/twpayne/go-geom v1.5.7 h1:7fdceDUr03/MP7rAKOaTV6x9njMiQdxB/D0PDzMTCDc=
github.com/twpayne/go-geom v1.5.7/go.mod h1:y4fTAQtLedXW8eG2Yo4tYrIGN1yIwwKkmA+K3iSHKBA=
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@ -951,7 +968,6 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ=
@ -998,11 +1014,11 @@ go.opentelemetry.io/otel v1.28.0/go.mod h1:q68ijF8Fc8CnMHKyzqL6akLO46ePnjkgfIMIj
go.opentelemetry.io/otel/exporters/jaeger v1.13.0 h1:VAMoGujbVV8Q0JNM/cEbhzUIWWBxnEqH45HP9iBKN04=
go.opentelemetry.io/otel/exporters/jaeger v1.13.0/go.mod h1:fHwbmle6mBFJA1p2ZIhilvffCdq/dM5UTIiCOmEjS+w=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.0.1/go.mod h1:Kv8liBeVNFkkkbilbgWRpV+wWuu+H5xdOT6HAgd30iw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0 h1:DeFD0VgTZ+Cj6hxravYYZE2W4GlneVH81iAOPjZkzk8=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.20.0/go.mod h1:GijYcYmNpX1KazD5JmWGsi4P7dDTTTnfv1UbGn84MnU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 h1:3Q/xZUyC1BBkualc9ROb4G8qkH90LXEIICcs5zv1OYY=
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0/go.mod h1:s75jGIWA9OfCMzF0xr+ZgfrB5FEbbV7UuYo32ahUiFI=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.0.1/go.mod h1:xOvWoTOrQjxjW61xtOmD/WKGRYb/P4NzRo3bs65U6Rk=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0 h1:gvmNvqrPYovvyRmCSygkUDyL8lC5Tl845MLEwqpxhEU=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.20.0/go.mod h1:vNUq47TGFioo+ffTSnKNdob241vePmtNZnAODKapKd0=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0 h1:R3X6ZXmNPRR8ul6i3WgFURCHzaXjHdm0karRG/+dj3s=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.28.0/go.mod h1:QWFXnDavXWwMx2EEcZsf3yxgEKAqsxQ+Syjp+seyInw=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0 h1:CsBiKCiQPdSjS+MlRiqeTI9JDDpSuk0Hb6QTRfwer8k=
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.20.0/go.mod h1:CMJYNAfooOwSZSAmAeMUV1M+TXld3BiK++z9fqIm2xk=
go.opentelemetry.io/otel/exporters/stdout/stdouttrace v1.20.0 h1:4s9HxB4azeeQkhY0GE5wZlMj4/pz8tE5gx2OQpGUw58=
@ -1017,8 +1033,8 @@ go.opentelemetry.io/otel/trace v1.28.0 h1:GhQ9cUuQGmNDd5BTCP2dAvv75RdMxEfTmYejp+
go.opentelemetry.io/otel/trace v1.28.0/go.mod h1:jPyXzNPg6da9+38HEwElrQiHlVMTnVfM3/yv2OlIHaI=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v0.9.0/go.mod h1:1vKfU9rv61e9EVGthD1zNvUbiwPcimSsOPU9brfSHJg=
go.opentelemetry.io/proto/otlp v1.0.0 h1:T0TX0tmXU8a3CbNXzEKGeU5mIVOdf0oykP+u2lIVU/I=
go.opentelemetry.io/proto/otlp v1.0.0/go.mod h1:Sy6pihPLfYHkr3NkUbEhGHFhINUSI/v80hjKIs5JXpM=
go.opentelemetry.io/proto/otlp v1.3.1 h1:TrMUixzpM0yuc/znrFTP9MMRh8trP93mkCiDVeXrui0=
go.opentelemetry.io/proto/otlp v1.3.1/go.mod h1:0X1WI4de4ZsLrrJNLAQbFeLCm3T7yBkR0XqQ7niQU+8=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@ -1257,15 +1273,14 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
@ -1451,8 +1466,8 @@ google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+n
google.golang.org/genproto v0.0.0-20220503193339-ba3ae3f07e29/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d h1:PksQg4dV6Sem3/HkBX+Ltq8T0ke0PKIRBNBatoDTVls=
google.golang.org/genproto v0.0.0-20240624140628-dc46fd24d27d/go.mod h1:s7iA721uChleev562UJO2OYB0PPT9CMFjV+Ce7VJH5M=
google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4 h1:MuYw1wJzT+ZkybKfaOXKp5hJiZDn2iHaXRw0mRYdHSc=
google.golang.org/genproto/googleapis/api v0.0.0-20240617180043-68d350f18fd4/go.mod h1:px9SlOOZBg1wM1zdnr8jEL4CNGUBZ+ZKYtNPApNQc4c=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 h1:0+ozOGcrp+Y8Aq8TLNN2Aliibms5LEzsq99ZZmAGYm0=
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094/go.mod h1:fJ/e3If/Q67Mj99hin0hMhiNyCRmt6BQ2aWIJshUSJw=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf h1:liao9UHurZLtiEwBgT9LMOnKYsHze6eA6w1KQCMVN2Q=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240730163845-b1a4ccb954bf/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.12.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=

View File

@ -8,8 +8,8 @@ class MilvusConan(ConanFile):
"rocksdb/6.29.5@milvus/dev#b1842a53ddff60240c5282a3da498ba1",
"boost/1.82.0#744a17160ebb5838e9115eab4d6d0c06",
"onetbb/2021.9.0#4a223ff1b4025d02f31b65aedf5e7f4a",
"nlohmann_json/3.11.2#ffb9e9236619f1c883e36662f944345d",
"zstd/1.5.4#308b8b048f9a3823ce248f9c150cc889",
"nlohmann_json/3.11.3#ffb9e9236619f1c883e36662f944345d",
"zstd/1.5.5#34e9debe03bf0964834a09dfbc31a5dd",
"lz4/1.9.4#c5afb86edd69ac0df30e3a9e192e43db",
"snappy/1.1.9#0519333fef284acd04806243de7d3070",
"lzo/2.10#9517fc1bcc4d4cc229a79806003a1baa",
@ -47,7 +47,14 @@ class MilvusConan(ConanFile):
"rapidjson/cci.20230929#624c0094d741e6a3749d2e44d834b96c",
"simde/0.8.2#5e1edfd5cba92f25d79bf6ef4616b972",
"unordered_dense/4.4.0#6a855c992618cc4c63019109a2e47298",
"xxhash/0.8.3#199e63ab9800302c232d030b27accec0"
"xxhash/0.8.3#199e63ab9800302c232d030b27accec0",
"json-c/0.17#aaea4a8164c63860731ea7ce4fa206f2",
"sqlite3/3.44.2#497f5b5414e48e35a717dd3035947819",
"proj/9.3.1#38e8bacd0f98467d38e20f46a085b4b3",
"libtiff/4.6.0#32ca1d04c9f024637d49c0c2882cfdbe",
"libgeotiff/1.7.1#0375633ef1116fc067b3773be7fd902f",
"geos/3.12.0#b76c27884c1fa4ee8c9e486337b7dc4e",
"gdal/3.5.3#61a42c933d3440a449cac89fd0866621"
)
generators = ("cmake", "cmake_find_package")
default_options = {
@ -81,6 +88,8 @@ class MilvusConan(ConanFile):
"fmt:header_only": True,
"onetbb:tbbmalloc": False,
"onetbb:tbbproxy": False,
"gdal:shared": True,
"gdal:fPIC": True,
}
def configure(self):

View File

@ -231,7 +231,9 @@ class Array {
return true;
}
case DataType::STRING:
case DataType::VARCHAR: {
case DataType::VARCHAR:
//treat Geometry as wkb string
case DataType::GEOMETRY: {
for (int i = 0; i < length_; ++i) {
if (get_data<std::string_view>(i) !=
arr.get_data<std::string_view>(i)) {
@ -340,6 +342,13 @@ class Array {
}
break;
}
case DataType::GEOMETRY: {
for (int j = 0; j < length_; ++j) {
auto element = get_data<std::string>(j);
data_array.mutable_geometry_data()->add_data(element);
}
break;
}
default: {
// empty array
}
@ -427,7 +436,8 @@ class Array {
return true;
}
case DataType::VARCHAR:
case DataType::STRING: {
case DataType::STRING:
case DataType::GEOMETRY: {
for (int i = 0; i < length_; i++) {
auto val = get_data<std::string>(i);
if (val != arr2.array(i).string_val()) {
@ -577,6 +587,13 @@ class ArrayView {
}
break;
}
case DataType::GEOMETRY: {
for (int j = 0; j < length_; ++j) {
auto element = get_data<std::string>(j);
data_array.mutable_geometry_data()->add_data(element);
}
break;
}
default: {
// empty array
}
@ -661,7 +678,8 @@ class ArrayView {
return true;
}
case DataType::VARCHAR:
case DataType::STRING: {
case DataType::STRING:
case DataType::GEOMETRY: {
for (int i = 0; i < length_; i++) {
auto val = get_data<std::string>(i);
if (val != arr2.array(i).string_val()) {

View File

@ -33,6 +33,7 @@
namespace milvus {
constexpr uint64_t MMAP_STRING_PADDING = 1;
constexpr uint64_t MMAP_GEOMETRY_PADDING = 1;
constexpr uint64_t MMAP_ARRAY_PADDING = 1;
class Chunk {
public:
@ -211,6 +212,7 @@ class StringChunk : public Chunk {
};
using JSONChunk = StringChunk;
using GeometryChunk = StringChunk;
class ArrayChunk : public Chunk {
public:

View File

@ -20,6 +20,7 @@
#include "common/Chunk.h"
#include "common/EasyAssert.h"
#include "common/FieldDataInterface.h"
#include "common/Geometry.h"
#include "common/Types.h"
#include "common/VectorTrait.h"
#include "simdjson/common_defs.h"
@ -157,6 +158,66 @@ JSONChunkWriter::finish() {
row_nums_, data, size, nullable_, std::move(mmap_file_raii));
}
void
GeometryChunkWriter::write(std::shared_ptr<arrow::RecordBatchReader> data) {
auto size = 0;
std::vector<std::string> wkb_strs;
std::vector<std::pair<const uint8_t*, int64_t>> null_bitmaps;
for (auto batch : *data) {
auto data = batch.ValueOrDie()->column(0);
auto array = std::dynamic_pointer_cast<arrow::BinaryArray>(data);
for (int i = 0; i < array->length(); i++) {
auto str = array->GetView(i);
wkb_strs.emplace_back(str);
size += str.size();
}
if (nullable_) {
auto null_bitmap_n = (data->length() + 7) / 8;
null_bitmaps.emplace_back(data->null_bitmap_data(), null_bitmap_n);
size += null_bitmap_n;
}
row_nums_ += array->length();
}
// use 32-bit offsets to align with StringChunk layout
size += sizeof(uint32_t) * (row_nums_ + 1) + MMAP_GEOMETRY_PADDING;
if (!file_path_.empty()) {
target_ = std::make_shared<MmapChunkTarget>(file_path_);
} else {
target_ = std::make_shared<MemChunkTarget>(size);
}
// chunk layout: null bitmap, offset1, offset2, ..., offsetn, wkb1, wkb2, ..., wkbn, padding
// write null bitmaps
write_null_bit_maps(null_bitmaps);
int offset_num = row_nums_ + 1;
uint32_t offset_start_pos =
static_cast<uint32_t>(target_->tell() + sizeof(uint32_t) * offset_num);
std::vector<uint32_t> offsets;
for (auto str : wkb_strs) {
offsets.push_back(offset_start_pos);
offset_start_pos += str.size();
}
offsets.push_back(offset_start_pos);
target_->write(offsets.data(), offsets.size() * sizeof(uint32_t));
for (auto str : wkb_strs) {
target_->write(str.data(), str.size());
}
}
std::shared_ptr<Chunk>
GeometryChunkWriter::finish() {
// write padding, maybe not needed anymore
// FIXME
char padding[MMAP_GEOMETRY_PADDING];
target_->write(padding, MMAP_GEOMETRY_PADDING);
auto [data, size] = target_->get();
return std::make_shared<GeometryChunk>(row_nums_, data, size, nullable_);
}
void
ArrayChunkWriter::write(std::shared_ptr<arrow::RecordBatchReader> data) {
auto size = 0;
@ -368,6 +429,10 @@ create_chunk_writer(const FieldMeta& field_meta, Args&&... args) {
case milvus::DataType::JSON:
return std::make_shared<JSONChunkWriter>(
std::forward<Args>(args)..., nullable);
case milvus::DataType::GEOMETRY: {
return std::make_shared<GeometryChunkWriter>(
std::forward<Args>(args)..., nullable);
}
case milvus::DataType::ARRAY:
return std::make_shared<ArrayChunkWriter>(
field_meta.get_element_type(),

View File

@ -25,6 +25,7 @@
#include "storage/FileWriter.h"
#include "common/Geometry.h"
namespace milvus {
class ChunkWriterBase {
@ -207,6 +208,16 @@ class JSONChunkWriter : public ChunkWriterBase {
finish() override;
};
class GeometryChunkWriter : public ChunkWriterBase {
public:
using ChunkWriterBase::ChunkWriterBase;
void
write(std::shared_ptr<arrow::RecordBatchReader> data) override;
std::shared_ptr<Chunk>
finish() override;
};
class ArrayChunkWriter : public ChunkWriterBase {
public:
ArrayChunkWriter(const milvus::DataType element_type, bool nullable)

View File

@ -213,6 +213,19 @@ FieldDataImpl<Type, is_type_entire_row>::FillFieldData(
}
return FillFieldData(values.data(), element_count);
}
case DataType::GEOMETRY: {
auto geometry_array =
std::dynamic_pointer_cast<arrow::BinaryArray>(array);
std::vector<uint8_t> values(element_count);
for (size_t index = 0; index < element_count; ++index) {
values[index] = *geometry_array->GetValue(index, 0);
}
if (nullable_) {
return FillFieldData(
values.data(), array->null_bitmap_data(), element_count);
}
return FillFieldData(values.data(), element_count);
}
case DataType::ARRAY: {
auto array_array =
std::dynamic_pointer_cast<arrow::BinaryArray>(array);
@ -278,6 +291,7 @@ template class FieldDataImpl<float, true>;
template class FieldDataImpl<double, true>;
template class FieldDataImpl<std::string, true>;
template class FieldDataImpl<Json, true>;
template class FieldDataImpl<Geometry, true>;
template class FieldDataImpl<Array, true>;
// vector data
@ -315,6 +329,9 @@ InitScalarFieldData(const DataType& type, bool nullable, int64_t cap_rows) {
type, nullable, cap_rows);
case DataType::JSON:
return std::make_shared<FieldData<Json>>(type, nullable, cap_rows);
case DataType::GEOMETRY:
return std::make_shared<FieldData<Geometry>>(
type, nullable, cap_rows);
default:
PanicInfo(DataTypeInvalid,
"InitScalarFieldData not support data type " +

View File

@ -69,6 +69,17 @@ class FieldData<Json> : public FieldDataJsonImpl {
}
};
template <>
class FieldData<Geometry> : public FieldDataGeometryImpl {
public:
static_assert(IsScalar<Geometry>);
explicit FieldData(DataType data_type,
bool nullable,
int64_t buffered_num_rows = 0)
: FieldDataGeometryImpl(data_type, nullable, buffered_num_rows) {
}
};
template <>
class FieldData<Array> : public FieldDataArrayImpl {
public:

View File

@ -572,6 +572,75 @@ class FieldDataStringImpl : public FieldDataImpl<std::string, true> {
}
};
class FieldDataGeometryImpl : public FieldDataImpl<std::string, true> {
public:
explicit FieldDataGeometryImpl(DataType data_type,
bool nullable,
int64_t total_num_rows = 0)
: FieldDataImpl<std::string, true>(
1, data_type, nullable, total_num_rows) {
}
int64_t
DataSize() const override {
int64_t data_size = 0;
for (size_t offset = 0; offset < length(); ++offset) {
data_size += data_[offset].size();
}
return data_size;
}
int64_t
DataSize(ssize_t offset) const override {
AssertInfo(offset < get_num_rows(),
"field data subscript out of range");
AssertInfo(offset < length(),
"subscript position don't has valid value");
return data_[offset].size();
}
void
FillFieldData(const std::shared_ptr<arrow::Array> array) override {
AssertInfo(array->type()->id() == arrow::Type::type::BINARY,
"inconsistent data type, expected: {}, got: {}",
"BINARY",
array->type()->ToString());
auto geometry_array =
std::dynamic_pointer_cast<arrow::BinaryArray>(array);
FillFieldData(geometry_array);
}
void
FillFieldData(const std::shared_ptr<arrow::BinaryArray>& array) override {
auto n = array->length();
if (n == 0) {
return;
}
null_count_ = array->null_count();
std::lock_guard lck(tell_mutex_);
if (length_ + n > get_num_rows()) {
resize_field_data(length_ + n);
}
auto i = 0;
for (const auto& geometry : *array) {
if (!geometry.has_value()) {
i++;
continue;
}
data_[length_ + i] = geometry.value();
i++;
}
if (IsNullable()) {
auto valid_data = array->null_bitmap_data();
if (valid_data != nullptr) {
bitset::detail::ElementWiseBitsetPolicy<uint8_t>::op_copy(
valid_data, 0, valid_data_.data(), length_, n);
}
}
length_ += n;
}
};
class FieldDataJsonImpl : public FieldDataImpl<Json, true> {
public:
explicit FieldDataJsonImpl(DataType data_type,

View File

@ -0,0 +1,142 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#pragma once
#include "ogr_geometry.h"
#include <memory>
#include "common/EasyAssert.h"
namespace milvus {
struct OGRGeometryDeleter {
void
operator()(OGRGeometry* ptr) const noexcept {
if (ptr) {
OGRGeometryFactory::destroyGeometry(ptr);
}
}
};
class Geometry {
public:
Geometry() = default;
// all ctr assume that wkb data is valid
explicit Geometry(const void* wkb, size_t size) {
OGRGeometry* geometry = nullptr;
OGRGeometryFactory::createFromWkb(wkb, nullptr, &geometry, size);
AssertInfo(geometry != nullptr,
"failed to construct geometry from wkb data");
geometry_.reset(geometry);
}
explicit Geometry(const char* wkt) {
OGRGeometry* geometry = nullptr;
OGRGeometryFactory::createFromWkt(wkt, nullptr, &geometry);
AssertInfo(geometry != nullptr,
"failed to construct geometry from wkt data");
geometry_.reset(geometry);
}
Geometry(const Geometry& other) {
if (other.IsValid()) {
this->geometry_.reset(other.geometry_->clone());
}
}
Geometry(Geometry&& other) noexcept
: geometry_(std::move(other.geometry_)) {
}
Geometry&
operator=(const Geometry& other) {
if (this != &other && other.IsValid()) {
this->geometry_.reset(other.geometry_->clone());
}
return *this;
}
Geometry&
operator=(Geometry&& other) noexcept {
if (this != &other) {
geometry_ = std::move(other.geometry_);
}
return *this;
}
~Geometry() = default;
bool
IsValid() const {
return geometry_ != nullptr;
}
OGRGeometry*
GetGeometry() const {
return geometry_.get();
}
//spatial relation
bool
equals(const Geometry& other) const {
return geometry_->Equals(other.geometry_.get());
}
bool
touches(const Geometry& other) const {
return geometry_->Touches(other.geometry_.get());
}
bool
overlaps(const Geometry& other) const {
return geometry_->Overlaps(other.geometry_.get());
}
bool
crosses(const Geometry& other) const {
return geometry_->Crosses(other.geometry_.get());
}
bool
contains(const Geometry& other) const {
return geometry_->Contains(other.geometry_.get());
}
bool
intersects(const Geometry& other) const {
return geometry_->Intersects(other.geometry_.get());
}
bool
within(const Geometry& other) const {
return geometry_->Within(other.geometry_.get());
}
std::string
to_wkt_string() const {
return geometry_->exportToWkt();
}
// used for test
std::string
to_wkb_string() const {
std::unique_ptr<unsigned char[]> wkb(new unsigned char[geometry_->WkbSize()]);
geometry_->exportToWkb(wkbNDR, wkb.get());
return std::string(reinterpret_cast<const char*>(wkb.get()),
geometry_->WkbSize());
}
private:
std::unique_ptr<OGRGeometry, OGRGeometryDeleter> geometry_;
};
} // namespace milvus

View File

@ -45,6 +45,7 @@
#include "pb/schema.pb.h"
#include "pb/segcore.pb.h"
#include "Json.h"
#include "Geometry.h"
#include "CustomBitset.h"
@ -75,6 +76,7 @@ enum class DataType {
VARCHAR = 21,
ARRAY = 22,
JSON = 23,
GEOMETRY = 24,
// Some special Data type, start from after 50
// just for internal use now, may sync proto in future
@ -180,6 +182,8 @@ GetDataTypeName(DataType data_type) {
return "array";
case DataType::JSON:
return "json";
case DataType::GEOMETRY:
return "geometry";
case DataType::VECTOR_FLOAT:
return "vector_float";
case DataType::VECTOR_BINARY:
@ -216,6 +220,7 @@ using GroupByValueType = std::variant<std::monostate,
std::string>;
using ContainsType = proto::plan::JSONContainsExpr_JSONOp;
using NullExprType = proto::plan::NullExpr_NullOp;
using GISFunctionType = proto::plan::GISFunctionFilterExpr_GISOp;
inline bool
IsPrimaryKeyDataType(DataType data_type) {
@ -268,6 +273,11 @@ IsJsonDataType(DataType data_type) {
return data_type == DataType::JSON;
}
inline bool
IsGeometryDataType(DataType data_type) {
return data_type == DataType::GEOMETRY;
}
inline bool
IsArrayDataType(DataType data_type) {
return data_type == DataType::ARRAY;
@ -275,7 +285,8 @@ IsArrayDataType(DataType data_type) {
inline bool
IsBinaryDataType(DataType data_type) {
return IsJsonDataType(data_type) || IsArrayDataType(data_type);
return IsJsonDataType(data_type) || IsArrayDataType(data_type) ||
IsGeometryDataType(data_type);
}
inline bool
@ -301,6 +312,11 @@ IsJsonType(proto::schema::DataType type) {
return type == proto::schema::DataType::JSON;
}
inline bool
IsGeometryType(proto::schema::DataType type) {
return type == proto::schema::DataType::Geometry;
}
inline bool
IsArrayType(proto::schema::DataType type) {
return type == proto::schema::DataType::Array;
@ -543,6 +559,15 @@ struct TypeTraits<DataType::JSON> {
static constexpr const char* Name = "JSON";
};
template <>
struct TypeTraits<DataType::GEOMETRY> {
using NativeType = void;
static constexpr DataType TypeKind = DataType::GEOMETRY;
static constexpr bool IsPrimitiveType = false;
static constexpr bool IsFixedWidth = false;
static constexpr const char* Name = "GEOMETRY";
};
template <>
struct TypeTraits<DataType::ROW> {
using NativeType = void;
@ -630,6 +655,9 @@ struct fmt::formatter<milvus::DataType> : formatter<string_view> {
case milvus::DataType::JSON:
name = "JSON";
break;
case milvus::DataType::GEOMETRY:
name = "GEOMETRY";
break;
case milvus::DataType::ROW:
name = "ROW";
break;

View File

@ -60,9 +60,9 @@ constexpr bool IsVector = std::is_base_of_v<VectorTrait, T>;
template <typename T>
constexpr bool IsScalar =
std::is_fundamental_v<T> || std::is_same_v<T, std::string> ||
std::is_same_v<T, Json> || std::is_same_v<T, std::string_view> ||
std::is_same_v<T, Array> || std::is_same_v<T, ArrayView> ||
std::is_same_v<T, proto::plan::Array>;
std::is_same_v<T, Json> || std::is_same_v<T, Geometry> ||
std::is_same_v<T, std::string_view> || std::is_same_v<T, Array> ||
std::is_same_v<T, ArrayView> || std::is_same_v<T, proto::plan::Array>;
template <typename T>
constexpr bool IsSparse = std::is_same_v<T, SparseFloatVector> ||
@ -73,7 +73,7 @@ constexpr bool IsVariableType =
std::is_same_v<T, std::string> || std::is_same_v<T, std::string_view> ||
std::is_same_v<T, Array> || std::is_same_v<T, ArrayView> ||
std::is_same_v<T, proto::plan::Array> || std::is_same_v<T, Json> ||
IsSparse<T>;
std::is_same_v<T, Geometry> || IsSparse<T>;
template <typename T>
constexpr bool IsVariableTypeSupportInChunk =

View File

@ -25,12 +25,14 @@
#include "exec/expression/CompareExpr.h"
#include "exec/expression/ConjunctExpr.h"
#include "exec/expression/ExistsExpr.h"
#include "exec/expression/GISFunctionFilterExpr.h"
#include "exec/expression/JsonContainsExpr.h"
#include "exec/expression/LogicalBinaryExpr.h"
#include "exec/expression/LogicalUnaryExpr.h"
#include "exec/expression/NullExpr.h"
#include "exec/expression/TermExpr.h"
#include "exec/expression/UnaryExpr.h"
#include "expr/ITypeExpr.h"
#include "exec/expression/ValueExpr.h"
#include "expr/ITypeExpr.h"
@ -46,7 +48,6 @@ ExprSet::Eval(int32_t begin,
EvalCtx& context,
std::vector<VectorPtr>& results) {
results.resize(exprs_.size());
for (size_t i = begin; i < end; ++i) {
exprs_[i]->Eval(context, results[i]);
}
@ -305,6 +306,16 @@ CompileExpression(const expr::TypedExprPtr& expr,
context->get_active_count(),
context->query_config()->get_expr_batch_size(),
context->get_consistency_level());
} else if (auto casted_expr = std::dynamic_pointer_cast<
const milvus::expr::GISFunctionFilterExpr>(expr)) {
result = std::make_shared<PhyGISFunctionFilterExpr>(
compiled_inputs,
casted_expr,
"PhyGISFunctionFilterExpr",
context->get_segment(),
context->get_active_count(),
context->query_config()->get_expr_batch_size(),
context->get_consistency_level());
} else {
PanicInfo(ExprInvalid, "unsupport expr: ", expr->ToString());
}

View File

@ -0,0 +1,152 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#include "GISFunctionFilterExpr.h"
#include "common/EasyAssert.h"
#include "common/Geometry.h"
#include "common/Types.h"
#include "pb/plan.pb.h"
namespace milvus {
namespace exec {
#define GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(_DataType, method) \
auto execute_sub_batch = [](const _DataType* data, \
const bool* valid_data, \
const int32_t* offsets, \
const int size, \
TargetBitmapView res, \
TargetBitmapView valid_res, \
const Geometry& right_source) { \
for (int i = 0; i < size; ++i) { \
if (valid_data != nullptr && !valid_data[i]) { \
res[i] = valid_res[i] = false; \
continue; \
} \
res[i] = \
Geometry(data[i].data(), data[i].size()).method(right_source); \
} \
}; \
int64_t processed_size = ProcessDataChunks<_DataType>( \
execute_sub_batch, std::nullptr_t{}, res, valid_res, right_source); \
AssertInfo(processed_size == real_batch_size, \
"internal error: expr processed rows {} not equal " \
"expect batch size {}", \
processed_size, \
real_batch_size); \
return res_vec;
void
PhyGISFunctionFilterExpr::Eval(EvalCtx& context, VectorPtr& result) {
AssertInfo(expr_->column_.data_type_ == DataType::GEOMETRY,
"unsupported data type: {}",
expr_->column_.data_type_);
if (is_index_mode_) {
// result = EvalForIndexSegment();
PanicInfo(NotImplemented, "index for geos not implement");
} else {
result = EvalForDataSegment();
}
}
VectorPtr
PhyGISFunctionFilterExpr::EvalForDataSegment() {
auto real_batch_size = GetNextBatchSize();
if (real_batch_size == 0) {
return nullptr;
}
auto res_vec = std::make_shared<ColumnVector>(
TargetBitmap(real_batch_size), TargetBitmap(real_batch_size));
TargetBitmapView res(res_vec->GetRawData(), real_batch_size);
TargetBitmapView valid_res(res_vec->GetValidRawData(), real_batch_size);
valid_res.set();
auto& right_source = expr_->geometry_;
// Choose underlying data type according to segment type to avoid element
// size mismatch: Sealed segment variable column stores std::string_view;
// Growing segment stores std::string.
using SealedType = std::string_view;
using GrowingType = std::string;
switch (expr_->op_) {
case proto::plan::GISFunctionFilterExpr_GISOp_Equals: {
if (segment_->type() == SegmentType::Sealed) {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(SealedType, equals);
} else {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(GrowingType, equals);
}
}
case proto::plan::GISFunctionFilterExpr_GISOp_Touches: {
if (segment_->type() == SegmentType::Sealed) {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(SealedType, touches);
} else {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(GrowingType,
touches);
}
}
case proto::plan::GISFunctionFilterExpr_GISOp_Overlaps: {
if (segment_->type() == SegmentType::Sealed) {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(SealedType,
overlaps);
} else {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(GrowingType,
overlaps);
}
}
case proto::plan::GISFunctionFilterExpr_GISOp_Crosses: {
if (segment_->type() == SegmentType::Sealed) {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(SealedType, crosses);
} else {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(GrowingType,
crosses);
}
}
case proto::plan::GISFunctionFilterExpr_GISOp_Contains: {
if (segment_->type() == SegmentType::Sealed) {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(SealedType,
contains);
} else {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(GrowingType,
contains);
}
}
case proto::plan::GISFunctionFilterExpr_GISOp_Intersects: {
if (segment_->type() == SegmentType::Sealed) {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(SealedType,
intersects);
} else {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(GrowingType,
intersects);
}
}
case proto::plan::GISFunctionFilterExpr_GISOp_Within: {
if (segment_->type() == SegmentType::Sealed) {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(SealedType, within);
} else {
GEOMETRY_EXECUTE_SUB_BATCH_WITH_COMPARISON(GrowingType, within);
}
}
default: {
PanicInfo(NotImplemented,
"internal error: unknown GIS op : {}",
expr_->op_);
}
}
return res_vec;
}
// VectorPtr
// PhyGISFunctionFilterExpr::EvalForIndexSegment() {
// // TODO
// }
} //namespace exec
} // namespace milvus

View File

@ -0,0 +1,61 @@
// Copyright (C) 2019-2020 Zilliz. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software distributed under the License
// is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
// or implied. See the License for the specific language governing permissions and limitations under the License
#pragma once
#include <fmt/core.h>
#include "common/FieldDataInterface.h"
#include "common/Vector.h"
#include "exec/expression/Expr.h"
#include "expr/ITypeExpr.h"
#include "segcore/SegmentInterface.h"
namespace milvus {
namespace exec {
class PhyGISFunctionFilterExpr : public SegmentExpr {
public:
PhyGISFunctionFilterExpr(
const std::vector<std::shared_ptr<Expr>>& input,
const std::shared_ptr<const milvus::expr::GISFunctionFilterExpr>& expr,
const std::string& name,
const segcore::SegmentInternalInterface* segment,
int64_t active_count,
int64_t batch_size,
int32_t consistency_level)
: SegmentExpr(std::move(input),
name,
segment,
expr->column_.field_id_,
expr->column_.nested_path_,
DataType::GEOMETRY,
active_count,
batch_size,
consistency_level),
expr_(expr) {
}
void
Eval(EvalCtx& context, VectorPtr& result) override;
private:
// VectorPtr
// EvalForIndexSegment();
VectorPtr
EvalForDataSegment();
private:
std::shared_ptr<const milvus::expr::GISFunctionFilterExpr> expr_;
};
} //namespace exec
} // namespace milvus

View File

@ -21,11 +21,13 @@
#include <string>
#include <vector>
#include "common/Geometry.h"
#include "exec/expression/function/FunctionFactory.h"
#include "common/Exception.h"
#include "common/Schema.h"
#include "common/Types.h"
#include "common/Utils.h"
#include "ogr_geometry.h"
#include "pb/plan.pb.h"
namespace milvus {
@ -757,6 +759,28 @@ class CompareExpr : public ITypeFilterExpr {
const proto::plan::OpType op_type_;
};
class GISFunctionFilterExpr : public ITypeFilterExpr {
public:
GISFunctionFilterExpr(ColumnInfo cloumn,
GISFunctionType op,
const Geometry& geometry)
: column_(cloumn), op_(op), geometry_(geometry){};
std::string
ToString() const override {
return fmt::format(
"GISFunctionFilterExpr:[Column: {}, Operator: {} "
"WktValue: {}]",
column_.ToString(),
GISFunctionFilterExpr_GISOp_Name(op_),
geometry_.to_wkt_string());
}
public:
const ColumnInfo column_;
const GISFunctionType op_;
const Geometry geometry_;
};
class JsonContainsExpr : public ITypeFilterExpr {
public:
JsonContainsExpr(ColumnInfo column,

View File

@ -26,6 +26,7 @@
#include <vector>
#include "common/FieldMeta.h"
#include "common/Geometry.h"
#include "common/Types.h"
#include "mmap/Types.h"
#include "storage/Util.h"
@ -136,6 +137,27 @@ WriteFieldData(File& file,
}
break;
}
case DataType::GEOMETRY: {
// write as: |size|data|size|data......
for (ssize_t i = 0; i < data->get_num_rows(); ++i) {
indices.push_back(total_written);
auto geo_ptr =
static_cast<const std::string*>(data->RawValue(i));
ssize_t written_data_size =
file.WriteInt<uint32_t>(geo_ptr->size());
if (written_data_size != sizeof(uint32_t)) {
THROW_FILE_WRITE_ERROR
}
total_written += written_data_size;
ssize_t written_data =
file.Write(geo_ptr->data(), geo_ptr->size());
if (written_data < geo_ptr->size()) {
THROW_FILE_WRITE_ERROR
}
total_written += written_data;
}
break;
}
case DataType::ARRAY: {
// write as: |data|data|data|data|data......
for (size_t i = 0; i < data->get_num_rows(); ++i) {

View File

@ -14,12 +14,17 @@
#include <google/protobuf/text_format.h>
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include "common/Geometry.h"
#include "common/VectorTrait.h"
#include "common/EasyAssert.h"
#include "exec/expression/function/FunctionFactory.h"
#include "log/Log.h"
#include "ogr_core.h"
#include "ogr_geometry.h"
#include "pb/plan.pb.h"
#include "query/Utils.h"
#include "knowhere/comp/materialized_view.h"
@ -475,6 +480,19 @@ ProtoParser::ParseValueExprs(const proto::plan::ValueExpr& expr_pb) {
return std::make_shared<expr::ValueExpr>(expr_pb.value());
}
expr::TypedExprPtr
ProtoParser::ParseGISFunctionFilterExprs(
const proto::plan::GISFunctionFilterExpr& expr_pb) {
auto& columnInfo = expr_pb.column_info();
auto field_id = FieldId(columnInfo.field_id());
auto data_type = schema[field_id].get_data_type();
Assert(data_type == (DataType)columnInfo.data_type());
const std::string& str = expr_pb.wkt_string();
Geometry geometry(str.data());
return std::make_shared<expr::GISFunctionFilterExpr>(
columnInfo, expr_pb.op(), geometry);
}
expr::TypedExprPtr
ProtoParser::CreateAlwaysTrueExprs() {
return std::make_shared<expr::AlwaysTrueExpr>();
@ -544,6 +562,11 @@ ProtoParser::ParseExprs(const proto::plan::Expr& expr_pb,
result = ParseNullExprs(expr_pb.null_expr());
break;
}
case ppe::kGisfunctionFilterExpr: {
result =
ParseGISFunctionFilterExprs(expr_pb.gisfunction_filter_expr());
break;
}
default: {
std::string s;
google::protobuf::TextFormat::PrintToString(expr_pb, &s);

View File

@ -86,6 +86,10 @@ class ProtoParser {
expr::TypedExprPtr
ParseJsonContainsExprs(const proto::plan::JSONContainsExpr& expr_pb);
expr::TypedExprPtr
ParseGISFunctionFilterExprs(
const proto::plan::GISFunctionFilterExpr& expr_pb);
expr::TypedExprPtr
ParseTermExprs(const proto::plan::TermExpr& expr_pb);

View File

@ -33,6 +33,7 @@
#include "common/Consts.h"
#include "common/EasyAssert.h"
#include "common/FieldData.h"
#include "common/FieldDataInterface.h"
#include "common/FieldMeta.h"
#include "common/File.h"
#include "common/Json.h"
@ -369,6 +370,21 @@ ChunkedSegmentSealedImpl::LoadFieldData(FieldId field_id, FieldDataInfo& data) {
column = std::move(var_column);
break;
}
case milvus::DataType::GEOMETRY: {
auto var_column =
std::make_shared<ChunkedVariableColumn<std::string>>(
field_meta);
std::shared_ptr<milvus::ArrowDataWrapper> r;
while (data.arrow_reader_channel->pop(r)) {
auto chunk = create_chunk(field_meta, r->reader);
var_column->AddChunk(chunk);
}
// var_column->Seal();
stats_.mem_size += var_column->DataByteSize();
field_data_size = var_column->DataByteSize();
column = std::move(var_column);
break;
}
case milvus::DataType::ARRAY: {
auto var_column =
std::make_shared<ChunkedArrayColumn>(field_meta);
@ -531,6 +547,14 @@ ChunkedSegmentSealedImpl::MapFieldData(const FieldId field_id,
column = std::move(var_column);
break;
}
case milvus::DataType::GEOMETRY: {
auto var_column =
std::make_shared<ChunkedVariableColumn<std::string>>(
field_meta, chunks);
// var_column->Seal(std::move(indices));
column = std::move(var_column);
break;
}
case milvus::DataType::ARRAY: {
auto arr_column =
std::make_shared<ChunkedArrayColumn>(field_meta, chunks);
@ -1576,6 +1600,15 @@ ChunkedSegmentSealedImpl::get_raw_data(FieldId field_id,
break;
}
case DataType::GEOMETRY: {
bulk_subscript_ptr_impl<std::string>(column.get(),
seg_offsets,
count,
ret->mutable_scalars()
->mutable_geometry_data()
->mutable_data());
break;
}
case DataType::ARRAY: {
bulk_subscript_array_impl(
column.get(),

View File

@ -98,6 +98,18 @@ VectorBase::set_data_raw(ssize_t element_offset,
return set_data_raw(element_offset, data_raw.data(), element_count);
}
case DataType::GEOMETRY: {
// get the geometry array of a column from proto message
auto& geometry_data = FIELD_DATA(data, geometry);
std::vector<std::string> data_raw{};
data_raw.reserve(geometry_data.size());
for (auto& geometry_bytes : geometry_data) {
//this geometry_bytes consider as wkt strings from milvus-proto
data_raw.emplace_back(
std::string(geometry_bytes.data(), geometry_bytes.size()));
}
return set_data_raw(element_offset, data_raw.data(), element_count);
}
case DataType::ARRAY: {
auto& array_data = FIELD_DATA(data, array);
std::vector<Array> data_raw{};

View File

@ -437,6 +437,11 @@ struct InsertRecord {
field_id, size_per_chunk, scalar_mmap_descriptor);
break;
}
case DataType::GEOMETRY: {
this->append_data<std::string>(
field_id, size_per_chunk, scalar_mmap_descriptor);
break;
}
case DataType::ARRAY: {
this->append_data<Array>(
field_id, size_per_chunk, scalar_mmap_descriptor);

View File

@ -647,6 +647,15 @@ SegmentGrowingImpl::bulk_subscript(FieldId field_id,
result->mutable_scalars()->mutable_json_data()->mutable_data());
break;
}
case DataType::GEOMETRY: {
bulk_subscript_ptr_impl<std::string>(vec_ptr,
seg_offsets,
count,
result->mutable_scalars()
->mutable_geometry_data()
->mutable_data());
break;
}
case DataType::ARRAY: {
// element
bulk_subscript_array_impl(*vec_ptr,

View File

@ -35,6 +35,7 @@
#include "common/FieldMeta.h"
#include "common/File.h"
#include "common/Json.h"
#include "common/Geometry.h"
#include "common/LoadInfo.h"
#include "common/Tracer.h"
#include "common/Types.h"
@ -432,6 +433,20 @@ SegmentSealedImpl::LoadFieldData(FieldId field_id, FieldDataInfo& data) {
column = std::move(var_column);
break;
}
case milvus::DataType::GEOMETRY: {
auto var_column = std::make_shared<
SingleChunkVariableColumn<std::string>>(
num_rows, field_meta, get_block_size());
FieldDataPtr field_data;
while (data.channel->pop(field_data)) {
var_column->Append(std::move(field_data));
}
var_column->Seal();
stats_.mem_size += var_column->MemoryUsageBytes();
field_data_size = var_column->DataByteSize();
column = std::move(var_column);
break;
}
case milvus::DataType::ARRAY: {
auto var_column = std::make_shared<SingleChunkArrayColumn>(
num_rows, field_meta);
@ -593,6 +608,17 @@ SegmentSealedImpl::MapFieldData(const FieldId field_id, FieldDataInfo& data) {
column = std::move(var_column);
break;
}
case milvus::DataType::GEOMETRY: {
auto var_column =
std::make_shared<SingleChunkVariableColumn<std::string>>(
file,
total_written,
field_meta,
DEFAULT_MMAP_VRCOL_BLOCK_SIZE);
var_column->Seal(std::move(indices));
column = std::move(var_column);
break;
}
case milvus::DataType::ARRAY: {
auto arr_column = std::make_shared<SingleChunkArrayColumn>(
file, total_written, field_meta);
@ -1444,6 +1470,15 @@ SegmentSealedImpl::get_raw_data(FieldId field_id,
break;
}
case DataType::GEOMETRY: {
bulk_subscript_ptr_impl<std::string>(column.get(),
seg_offsets,
count,
ret->mutable_scalars()
->mutable_geometry_data()
->mutable_data());
break;
}
case DataType::ARRAY: {
bulk_subscript_array_impl(
column.get(),

View File

@ -19,7 +19,9 @@
#include "common/Common.h"
#include "common/FieldData.h"
#include "common/FieldDataInterface.h"
#include "common/Types.h"
#include "common/Utils.h"
#include "index/ScalarIndex.h"
#include "log/Log.h"
#include "storage/DataCodec.h"
@ -145,6 +147,13 @@ GetRawDataSizeOfDataArray(const DataArray* data,
}
break;
}
case DataType::GEOMETRY: {
auto& geometry_data = FIELD_DATA(data, geometry);
for (auto& geometry_bytes : geometry_data) {
result += geometry_bytes.size();
}
break;
}
case DataType::ARRAY: {
auto& array_data = FIELD_DATA(data, array);
switch (field_meta.get_element_type()) {
@ -291,6 +300,14 @@ CreateScalarDataArray(int64_t count, const FieldMeta& field_meta) {
}
break;
}
case DataType::GEOMETRY: {
auto obj = scalar_array->mutable_geometry_data();
obj->mutable_data()->Reserve(count);
for (int i = 0; i < count; i++) {
*(obj->mutable_data()->Add()) = std::string();
}
break;
}
case DataType::ARRAY: {
auto obj = scalar_array->mutable_array_data();
obj->mutable_data()->Reserve(count);
@ -439,6 +456,15 @@ CreateScalarDataArrayFrom(const void* data_raw,
}
break;
}
case DataType::GEOMETRY: {
auto data = reinterpret_cast<const std::string*>(data_raw);
auto obj = scalar_array->mutable_geometry_data();
for (auto i = 0; i < count; i++) {
*(obj->mutable_data()->Add()) =
std::string(data[i].data(), data[i].size());
}
break;
}
case DataType::ARRAY: {
auto data = reinterpret_cast<const ScalarArray*>(data_raw);
auto obj = scalar_array->mutable_array_data();
@ -654,6 +680,13 @@ MergeDataArray(std::vector<MergeBase>& merge_bases,
*(obj->mutable_data()->Add()) = data[src_offset];
break;
}
case DataType::GEOMETRY: {
auto& data = FIELD_DATA(src_field_data, geometry);
auto obj = scalar_array->mutable_geometry_data();
*(obj->mutable_data()->Add()) = std::string(
data[src_offset].data(), data[src_offset].size());
break;
}
case DataType::ARRAY: {
auto& data = FIELD_DATA(src_field_data, array);
auto obj = scalar_array->mutable_array_data();

View File

@ -21,6 +21,7 @@
#include "common/Consts.h"
#include "common/EasyAssert.h"
#include "common/FieldMeta.h"
#include "common/Geometry.h"
#include "common/Json.h"
#include "fmt/format.h"
#include "nlohmann/json.hpp"
@ -297,6 +298,17 @@ BaseEventData::Serialize() {
}
break;
}
case DataType::GEOMETRY: {
for (size_t offset = 0; offset < field_data->get_num_rows();
++offset) {
auto geo_ptr = static_cast<const std::string*>(
field_data->RawValue(offset));
payload_writer->add_one_binary_payload(
reinterpret_cast<const uint8_t*>(geo_ptr->data()),
geo_ptr->size());
}
break;
}
case DataType::VECTOR_SPARSE_FLOAT: {
for (size_t offset = 0; offset < field_data->get_num_rows();
++offset) {

View File

@ -275,7 +275,8 @@ CreateArrowBuilder(DataType data_type) {
return std::make_shared<arrow::StringBuilder>();
}
case DataType::ARRAY:
case DataType::JSON: {
case DataType::JSON:
case DataType::GEOMETRY: {
return std::make_shared<arrow::BinaryBuilder>();
}
// sparse float vector doesn't require a dim
@ -356,7 +357,8 @@ CreateArrowSchema(DataType data_type, bool nullable) {
{arrow::field("val", arrow::utf8(), nullable)});
}
case DataType::ARRAY:
case DataType::JSON: {
case DataType::JSON:
case DataType::GEOMETRY: {
return arrow::schema(
{arrow::field("val", arrow::binary(), nullable)});
}
@ -849,6 +851,9 @@ CreateFieldData(const DataType& type,
case DataType::JSON:
return std::make_shared<FieldData<Json>>(
type, nullable, total_num_rows);
case DataType::GEOMETRY:
return std::make_shared<FieldData<Geometry>>(
type, nullable, total_num_rows);
case DataType::ARRAY:
return std::make_shared<FieldData<Array>>(
type, nullable, total_num_rows);

View File

@ -251,7 +251,8 @@ class CachedSearchIteratorTest
size_t offset = 0;
for (size_t i = 0; i < num_chunks_; ++i) {
const size_t rows = std::min(nb_ - offset, kSizePerChunk);
const size_t rows =
std::min(static_cast<size_t>(nb_ - offset), kSizePerChunk);
const size_t chunk_bitset_size = (rows + 7) / 8;
const size_t buf_size =
chunk_bitset_size + rows * dim_ * sizeof(float);

View File

@ -26,6 +26,7 @@
#include "common/FieldDataInterface.h"
#include "common/FieldMeta.h"
#include "common/File.h"
#include "common/Geometry.h"
#include "common/Types.h"
#include "storage/Event.h"
#include "storage/Util.h"
@ -126,7 +127,8 @@ TEST(chunk, test_json_field) {
auto ser_data = event_data.Serialize();
auto get_record_batch_reader =
[&]() -> std::shared_ptr<::arrow::RecordBatchReader> {
[&]() -> std::pair<std::shared_ptr<::arrow::RecordBatchReader>,
std::unique_ptr<parquet::arrow::FileReader>> {
auto buffer = std::make_shared<arrow::io::BufferReader>(
ser_data.data() + 2 * sizeof(milvus::Timestamp),
ser_data.size() - 2 * sizeof(milvus::Timestamp));
@ -141,11 +143,11 @@ TEST(chunk, test_json_field) {
std::shared_ptr<::arrow::RecordBatchReader> rb_reader;
s = arrow_reader->GetRecordBatchReader(&rb_reader);
EXPECT_TRUE(s.ok());
return rb_reader;
return {rb_reader, std::move(arrow_reader)};
};
{
auto rb_reader = get_record_batch_reader();
auto [rb_reader, arrow_reader] = get_record_batch_reader();
// nullable=false
FieldMeta field_meta(
FieldName("a"), milvus::FieldId(1), DataType::JSON, false);
@ -173,7 +175,7 @@ TEST(chunk, test_json_field) {
}
}
{
auto rb_reader = get_record_batch_reader();
auto [rb_reader, arrow_reader] = get_record_batch_reader();
// nullable=true
FieldMeta field_meta(
FieldName("a"), milvus::FieldId(1), DataType::JSON, true);
@ -456,4 +458,204 @@ TEST(chunk, test_sparse_float) {
EXPECT_EQ(v1[j].val, v2[j].val);
}
}
}
class TempDir {
public:
TempDir() {
auto path = boost::filesystem::unique_path("%%%%_%%%%");
auto abs_path = boost::filesystem::temp_directory_path() / path;
boost::filesystem::create_directory(abs_path);
dir_ = abs_path;
}
~TempDir() {
boost::filesystem::remove_all(dir_);
}
std::string
dir() {
return dir_.string();
}
private:
boost::filesystem::path dir_;
};
TEST(chunk, test_geometry_field) {
// Create simple geometry data - just a few points
FixedVector<std::string> data;
data.reserve(3);
// Create simple point geometries using WKT format
std::string point1_wkt = "POINT(0 0)";
std::string point2_wkt = "POINT(1 1)";
std::string point3_wkt = "POINT(2 2)";
// Convert WKT to WKB format
data.push_back(Geometry(point1_wkt.data()).to_wkb_string());
data.push_back(Geometry(point2_wkt.data()).to_wkb_string());
data.push_back(Geometry(point3_wkt.data()).to_wkb_string());
auto field_data =
milvus::storage::CreateFieldData(storage::DataType::GEOMETRY);
field_data->FillFieldData(data.data(), data.size());
storage::InsertEventData event_data;
auto payload_reader =
std::make_shared<milvus::storage::PayloadReader>(field_data);
event_data.payload_reader = payload_reader;
auto ser_data = event_data.Serialize();
auto buffer = std::make_shared<arrow::io::BufferReader>(
ser_data.data() + 2 * sizeof(milvus::Timestamp),
ser_data.size() - 2 * sizeof(milvus::Timestamp));
parquet::arrow::FileReaderBuilder reader_builder;
auto s = reader_builder.Open(buffer);
EXPECT_TRUE(s.ok());
std::unique_ptr<parquet::arrow::FileReader> arrow_reader;
s = reader_builder.Build(&arrow_reader);
EXPECT_TRUE(s.ok());
std::shared_ptr<::arrow::RecordBatchReader> rb_reader;
s = arrow_reader->GetRecordBatchReader(&rb_reader);
EXPECT_TRUE(s.ok());
FieldMeta field_meta(
FieldName("a"), milvus::FieldId(1), DataType::GEOMETRY, false);
auto chunk = create_chunk(field_meta, rb_reader);
// Since GeometryChunk is an alias for StringChunk, we can use StringViews
auto views = std::dynamic_pointer_cast<GeometryChunk>(chunk)->StringViews(
std::nullopt);
EXPECT_EQ(views.first.size(), data.size());
for (size_t i = 0; i < data.size(); ++i) {
EXPECT_EQ(views.first[i], data[i]);
}
}
TEST(chunk, test_geometry_field_nullable_all_valid) {
// Prepare geometry data (WKB strings) all rows valid but nullable flag enabled
FixedVector<std::string> data;
data.reserve(3);
data.push_back(Geometry("POINT(0 0)").to_wkb_string());
data.push_back(Geometry("POINT(1 1)").to_wkb_string());
data.push_back(Geometry("POINT(2 2)").to_wkb_string());
auto field_data =
milvus::storage::CreateFieldData(storage::DataType::GEOMETRY, true);
// All rows are valid need explicit valid bitmap when nullable=true
uint8_t* valid_bitmap_all =
new uint8_t[1]{0x07}; // 0b00000111 (3 rows valid)
field_data->FillFieldData(data.data(), valid_bitmap_all, data.size());
storage::InsertEventData event_data;
event_data.payload_reader =
std::make_shared<milvus::storage::PayloadReader>(field_data);
auto ser_data = event_data.Serialize();
auto buffer = std::make_shared<arrow::io::BufferReader>(
ser_data.data() + 2 * sizeof(milvus::Timestamp),
ser_data.size() - 2 * sizeof(milvus::Timestamp));
parquet::arrow::FileReaderBuilder reader_builder;
ASSERT_TRUE(reader_builder.Open(buffer).ok());
std::unique_ptr<parquet::arrow::FileReader> arrow_reader;
ASSERT_TRUE(reader_builder.Build(&arrow_reader).ok());
std::shared_ptr<::arrow::RecordBatchReader> rb_reader;
ASSERT_TRUE(arrow_reader->GetRecordBatchReader(&rb_reader).ok());
FieldMeta field_meta(
FieldName("geo"), milvus::FieldId(1), DataType::GEOMETRY, true);
auto chunk = create_chunk(field_meta, rb_reader);
auto [views, valid] =
std::dynamic_pointer_cast<GeometryChunk>(chunk)->StringViews(
std::nullopt);
ASSERT_EQ(views.size(), data.size());
for (size_t i = 0; i < data.size(); ++i) {
EXPECT_EQ(views[i], data[i]);
EXPECT_TRUE(valid[i]);
}
delete[] valid_bitmap_all;
}
TEST(chunk, test_geometry_field_mmap_with_nulls) {
// Prepare geometry data with one NULL row (middle)
FixedVector<std::string> data;
data.reserve(3);
data.push_back(Geometry("POINT(0 0)").to_wkb_string());
data.push_back(
Geometry("POINT(1 1)").to_wkb_string()); // will be marked NULL
data.push_back(Geometry("POINT(2 2)").to_wkb_string());
// Validity bitmap: 0b00000101 -> rows 0 and 2 valid, row 1 invalid
uint8_t* valid_bitmap = new uint8_t[1]{0x05};
auto field_data =
milvus::storage::CreateFieldData(storage::DataType::GEOMETRY, true);
field_data->FillFieldData(data.data(), valid_bitmap, data.size());
storage::InsertEventData event_data;
event_data.payload_reader =
std::make_shared<milvus::storage::PayloadReader>(field_data);
auto ser_data = event_data.Serialize();
auto buffer = std::make_shared<arrow::io::BufferReader>(
ser_data.data() + 2 * sizeof(milvus::Timestamp),
ser_data.size() - 2 * sizeof(milvus::Timestamp));
parquet::arrow::FileReaderBuilder reader_builder;
ASSERT_TRUE(reader_builder.Open(buffer).ok());
std::unique_ptr<parquet::arrow::FileReader> arrow_reader;
ASSERT_TRUE(reader_builder.Build(&arrow_reader).ok());
std::shared_ptr<::arrow::RecordBatchReader> rb_reader;
ASSERT_TRUE(arrow_reader->GetRecordBatchReader(&rb_reader).ok());
// Prepare mmap file
TempDir temp;
std::string temp_dir = temp.dir();
auto file = File::Open(temp_dir + "/geo_mmap", O_CREAT | O_RDWR);
int file_offset = 0;
FieldMeta field_meta(
FieldName("geo"), milvus::FieldId(1), DataType::GEOMETRY, true);
auto chunk = create_chunk(field_meta, rb_reader);
auto [views, valid] =
std::dynamic_pointer_cast<GeometryChunk>(chunk)->StringViews(
std::nullopt);
ASSERT_EQ(views.size(), data.size());
for (size_t i = 0; i < data.size(); ++i) {
if (valid[i]) {
EXPECT_EQ(views[i], data[i]);
} else {
EXPECT_FALSE(valid[i]);
}
}
file.Close();
delete[] valid_bitmap;
}
TEST(array, test_geometry_array_output_data) {
// Prepare two simple geometries (WKB strings)
std::string wkb1 = Geometry("POINT(10 10)").to_wkb_string();
std::string wkb2 = Geometry("POINT(20 20)").to_wkb_string();
// Build raw buffer and offsets for two variable-length geometry elements
// Need to support kGeometry in construct Array(const ScalarArray& field_data)
uint32_t offsets_raw[2] = {0, static_cast<uint32_t>(wkb1.size())};
size_t total_size = wkb1.size() + wkb2.size();
std::vector<char> buf(total_size);
std::copy(wkb1.begin(), wkb1.end(), buf.begin());
std::copy(wkb2.begin(), wkb2.end(), buf.begin() + wkb1.size());
// Construct Array with element_type = GEOMETRY
Array geo_array(
buf.data(), /*len=*/2, total_size, DataType::GEOMETRY, offsets_raw);
auto serialized = geo_array.output_data();
ASSERT_EQ(serialized.geometry_data().data_size(), 2);
EXPECT_EQ(serialized.geometry_data().data(0), wkb1);
EXPECT_EQ(serialized.geometry_data().data(1), wkb2);
}

View File

@ -51,6 +51,7 @@ TEST_F(ChunkVectorTest, FillDataWithMmap) {
auto double_field = schema->AddDebugField("double", DataType::DOUBLE);
auto varchar_field = schema->AddDebugField("varchar", DataType::VARCHAR);
auto json_field = schema->AddDebugField("json", DataType::JSON);
auto geometry_field = schema->AddDebugField("geometry", DataType::GEOMETRY);
auto int_array_field =
schema->AddDebugField("int_array", DataType::ARRAY, DataType::INT8);
auto long_array_field =
@ -116,6 +117,8 @@ TEST_F(ChunkVectorTest, FillDataWithMmap) {
varchar_field, ids_ds->GetIds(), num_inserted);
auto json_result =
segment->bulk_subscript(json_field, ids_ds->GetIds(), num_inserted);
auto geometry_result = segment->bulk_subscript(
geometry_field, ids_ds->GetIds(), num_inserted);
auto int_array_result = segment->bulk_subscript(
int_array_field, ids_ds->GetIds(), num_inserted);
auto long_array_result = segment->bulk_subscript(
@ -150,6 +153,8 @@ TEST_F(ChunkVectorTest, FillDataWithMmap) {
EXPECT_EQ(varchar_result->scalars().string_data().data_size(),
num_inserted);
EXPECT_EQ(json_result->scalars().json_data().data_size(), num_inserted);
EXPECT_EQ(geometry_result->scalars().geometry_data().data_size(),
num_inserted);
EXPECT_EQ(fp32_vec_result->vectors().float_vector().data_size(),
num_inserted * dim);
EXPECT_EQ(fp16_vec_result->vectors().float16_vector().size(),

View File

@ -41,6 +41,7 @@
#include <string>
#include <unordered_map>
#include <vector>
#include <sys/mman.h>
struct DeferRelease {
using functype = std::function<void()>;
@ -79,8 +80,13 @@ TEST(test_chunk_segment, TestSearchOnSealed) {
auto data = dataset.get_col<float>(fakevec_id);
auto buf_size = chunk_bitset_size + 4 * data.size();
char* buf = new char[buf_size];
defer.AddDefer([buf]() { delete[] buf; });
char* buf = reinterpret_cast<char*>(mmap(nullptr,
buf_size,
PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANON,
-1,
0));
ASSERT_NE(buf, MAP_FAILED);
memcpy(buf + chunk_bitset_size, data.data(), 4 * data.size());
auto chunk = std::make_shared<FixedWidthChunk>(

View File

@ -17,6 +17,9 @@
#include <gtest/gtest.h>
#include <string>
#include "common/Geometry.h"
#include "ogr_core.h"
#include "ogr_geometry.h"
#include "storage/DataCodec.h"
#include "storage/InsertData.h"
#include "storage/IndexData.h"
@ -351,7 +354,109 @@ TEST(storage, InsertDataInt64Nullable) {
ASSERT_EQ(*new_payload->ValidData(), *valid_data);
delete[] valid_data;
}
TEST(storage, InsertDataGeometry) {
OGRPoint point1(10.25, 0.55), point2(9.75, -0.23), point3(-8.50, 1.44);
OGRLineString linstring;
linstring.addPoint(&point1);
linstring.addPoint(&point2);
linstring.addPoint(&point3);
OGRPolygon polygon;
OGRLinearRing ring;
ring.addPoint(&point1);
ring.addPoint(&point2);
ring.addPoint(&point3);
ring.closeRings();
polygon.addRing(&ring);
std::string str1, str2, str3;
str1 = Geometry(point1.exportToWkt().data()).to_wkb_string();
str2 = Geometry(linstring.exportToWkt().data()).to_wkb_string();
str3 = Geometry(polygon.exportToWkt().data()).to_wkb_string();
FixedVector<std::string> data = {str1, str2, str3};
auto field_data =
milvus::storage::CreateFieldData(storage::DataType::GEOMETRY, false);
field_data->FillFieldData(data.data(), data.size());
auto payload_reader =
std::make_shared<milvus::storage::PayloadReader>(field_data);
storage::InsertData insert_data(payload_reader);
storage::FieldDataMeta field_data_meta{100, 101, 102, 103};
insert_data.SetFieldDataMeta(field_data_meta);
insert_data.SetTimestamps(0, 100);
auto serialized_bytes = insert_data.Serialize(storage::StorageType::Remote);
std::shared_ptr<uint8_t[]> serialized_data_ptr(serialized_bytes.data(),
[&](uint8_t*) {});
auto new_insert_data = storage::DeserializeFileData(
serialized_data_ptr, serialized_bytes.size());
ASSERT_EQ(new_insert_data->GetCodecType(), storage::InsertDataType);
ASSERT_EQ(new_insert_data->GetTimeRage(),
std::make_pair(Timestamp(0), Timestamp(100)));
auto new_payload = new_insert_data->GetFieldData();
ASSERT_EQ(new_payload->get_data_type(), storage::DataType::GEOMETRY);
ASSERT_EQ(new_payload->get_num_rows(), data.size());
FixedVector<std::string> new_data(data.size());
ASSERT_EQ(new_payload->get_null_count(), 0);
for (int i = 0; i < data.size(); ++i) {
new_data[i] =
*static_cast<const std::string*>(new_payload->RawValue(i));
ASSERT_EQ(new_payload->DataSize(i), data[i].size());
}
ASSERT_EQ(data, new_data);
}
TEST(storage, InsertDataGeometryNullable) {
// Prepare five simple point geometries in WKB format
OGRPoint p1(0.0, 0.0), p2(1.0, 1.0), p3(2.0, 2.0), p4(3.0, 3.0),
p5(4.0, 4.0);
std::string str1 = Geometry(p1.exportToWkt().data()).to_wkb_string();
std::string str2 = Geometry(p2.exportToWkt().data()).to_wkb_string();
std::string str3 = Geometry(p3.exportToWkt().data()).to_wkb_string();
std::string str4 = Geometry(p4.exportToWkt().data()).to_wkb_string();
std::string str5 = Geometry(p5.exportToWkt().data()).to_wkb_string();
FixedVector<std::string> data = {str1, str2, str3, str4, str5};
// Create nullable geometry FieldData
auto field_data =
milvus::storage::CreateFieldData(storage::DataType::GEOMETRY, true);
// valid_data bitmap: 0xF3 (11110011 b) rows 0,1,4 valid; rows 2,3 null
uint8_t* valid_data = new uint8_t[1]{0xF3};
field_data->FillFieldData(data.data(), valid_data, data.size());
// Round-trip the payload through InsertData serialization pipeline
auto payload_reader =
std::make_shared<milvus::storage::PayloadReader>(field_data);
storage::InsertData insert_data(payload_reader);
storage::FieldDataMeta field_data_meta{100, 101, 102, 103};
insert_data.SetFieldDataMeta(field_data_meta);
insert_data.SetTimestamps(0, 100);
auto serialized_bytes = insert_data.Serialize(storage::StorageType::Remote);
std::shared_ptr<uint8_t[]> serialized_data_ptr(serialized_bytes.data(),
[&](uint8_t*) {});
auto new_insert_data = storage::DeserializeFileData(
serialized_data_ptr, serialized_bytes.size());
ASSERT_EQ(new_insert_data->GetCodecType(), storage::InsertDataType);
ASSERT_EQ(new_insert_data->GetTimeRage(),
std::make_pair(Timestamp(0), Timestamp(100)));
auto new_payload = new_insert_data->GetFieldData();
ASSERT_EQ(new_payload->get_data_type(), storage::DataType::GEOMETRY);
ASSERT_EQ(new_payload->get_num_rows(), data.size());
// Note: current geometry serialization path writes empty string for null
// rows and loses Arrow null-bitmap, so null_count()==0 after round-trip.
// Expected data: original rows preserved (bitmap ignored by codec)
FixedVector<std::string> new_data(data.size());
for (int i = 0; i < data.size(); ++i) {
new_data[i] =
*static_cast<const std::string*>(new_payload->RawValue(i));
ASSERT_EQ(new_payload->DataSize(i), data[i].size());
}
ASSERT_EQ(data, new_data);
delete[] valid_data;
}
TEST(storage, InsertDataString) {
FixedVector<std::string> data = {
"test1", "test2", "test3", "test4", "test5"};

View File

@ -27,6 +27,7 @@
#include <roaring/roaring.hh>
#include "common/FieldDataInterface.h"
#include "common/Geometry.h"
#include "common/Json.h"
#include "common/JsonCastType.h"
#include "common/LoadInfo.h"
@ -17081,3 +17082,407 @@ TEST_P(JsonIndexBinaryExprTest, TestBinaryRangeExpr) {
EXPECT_TRUE(res == expect_result);
}
}
TEST_P(ExprTest, TestGISFunction) {
using namespace milvus;
using namespace milvus::query;
using namespace milvus::segcore;
// Create schema with geometry field
auto schema = std::make_shared<Schema>();
auto int_fid = schema->AddDebugField("int", DataType::INT64);
auto vec_fid = schema->AddDebugField(
"fakevec", DataType::VECTOR_FLOAT, 16, knowhere::metric::L2);
auto geom_fid = schema->AddDebugField("geometry", DataType::GEOMETRY);
schema->set_primary_field_id(int_fid);
auto seg = CreateGrowingSegment(schema, empty_index_meta);
int N = 1000;
int num_iters = 1;
// Generate test data
for (int iter = 0; iter < num_iters; ++iter) {
auto raw_data = DataGen(schema, N, iter);
seg->PreInsert(N);
seg->Insert(iter * N,
N,
raw_data.row_ids_.data(),
raw_data.timestamps_.data(),
raw_data.raw_);
}
auto seg_promote = dynamic_cast<SegmentGrowingImpl*>(seg.get());
// Define GIS test cases using struct like JSON tests
struct GISTestcase {
std::string wkt_string;
proto::plan::GISFunctionFilterExpr_GISOp op;
};
std::vector<GISTestcase> testcases = {
{"POINT(0 0)", proto::plan::GISFunctionFilterExpr_GISOp_Intersects},
{"POLYGON((-1 -1, 1 -1, 1 1, -1 1, -1 -1))",
proto::plan::GISFunctionFilterExpr_GISOp_Contains},
{"LINESTRING(-2 0, 2 0)",
proto::plan::GISFunctionFilterExpr_GISOp_Crosses},
{"POINT(10 10)", proto::plan::GISFunctionFilterExpr_GISOp_Equals},
{"POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))",
proto::plan::GISFunctionFilterExpr_GISOp_Touches},
{"POLYGON((0.5 0.5, 1.5 0.5, 1.5 1.5, 0.5 1.5, 0.5 0.5))",
proto::plan::GISFunctionFilterExpr_GISOp_Overlaps},
{"POLYGON((-10 -10, 10 -10, 10 10, -10 10, -10 -10))",
proto::plan::GISFunctionFilterExpr_GISOp_Within}};
// Execute tests
for (const auto& testcase : testcases) {
// Create Geometry object from WKT string
milvus::Geometry geometry(testcase.wkt_string.c_str());
// Create GIS expression
auto gis_expr = std::make_shared<milvus::expr::GISFunctionFilterExpr>(
milvus::expr::ColumnInfo(geom_fid, DataType::GEOMETRY),
testcase.op,
geometry);
auto plan = std::make_shared<plan::FilterBitsNode>(DEFAULT_PLANNODE_ID,
gis_expr);
// Verify query execution doesn't throw exceptions
ASSERT_NO_THROW({
BitsetType final = ExecuteQueryExpr(
plan, seg_promote, N * num_iters, MAX_TIMESTAMP);
EXPECT_EQ(final.size(), N * num_iters);
// Verify result is not empty (at least some geometry data satisfies conditions)
bool has_true_result = false;
for (int i = 0; i < final.size(); ++i) {
if (final[i]) {
has_true_result = true;
break;
}
}
// Note: Since we use random data, all results might be false, which is normal
// We mainly verify the function execution doesn't crash
});
}
}
TEST(ExprTest, SealedSegmentAllOperators) {
// 1. Build schema with geometry field and primary key
auto schema = std::make_shared<Schema>();
auto pk_fid = schema->AddDebugField("pk", DataType::INT64);
auto geo_fid = schema->AddDebugField("geo", DataType::GEOMETRY);
schema->set_primary_field_id(pk_fid);
// 2. Generate random data and load into a sealed segment
const int64_t N = 1000;
auto dataset = DataGen(schema, N);
auto seg = CreateSealedSegment(schema);
SealedLoadFieldData(dataset, *seg);
// 3. Prepare (op, wkt) pairs to hit every GIS operator
std::vector<
std::pair<proto::plan::GISFunctionFilterExpr_GISOp, std::string>>
test_cases = {
{proto::plan::GISFunctionFilterExpr_GISOp_Equals, "POINT(0 0)"},
{proto::plan::GISFunctionFilterExpr_GISOp_Touches,
"POLYGON((-1 -1, -1 1, 1 1, 1 -1, -1 -1))"},
{proto::plan::GISFunctionFilterExpr_GISOp_Overlaps,
"POLYGON((0 0, 2 0, 2 2, 0 2, 0 0))"},
{proto::plan::GISFunctionFilterExpr_GISOp_Crosses,
"LINESTRING(-1 0, 1 0)"},
{proto::plan::GISFunctionFilterExpr_GISOp_Contains,
"POLYGON((-2 -2, 2 -2, 2 2, -2 2, -2 -2))"},
{proto::plan::GISFunctionFilterExpr_GISOp_Intersects, "POINT(1 1)"},
{proto::plan::GISFunctionFilterExpr_GISOp_Within,
"POLYGON((-5 -5, 5 -5, 5 5, -5 5, -5 -5))"},
};
for (const auto& [op, wkt] : test_cases) {
// Build constant geometry used on right side of comparison
milvus::Geometry right_source(wkt.c_str());
// Create expression & plan node
auto gis_expr = std::make_shared<expr::GISFunctionFilterExpr>(
expr::ColumnInfo(geo_fid, DataType::GEOMETRY), op, right_source);
auto plan_node = std::make_shared<plan::FilterBitsNode>(
DEFAULT_PLANNODE_ID, gis_expr);
// Execute expression over the sealed segment
BitsetType result =
ExecuteQueryExpr(plan_node, seg.get(), N, MAX_TIMESTAMP);
// Validate basic expectations: bitset size should equal N
ASSERT_EQ(result.size(), N);
}
}
TEST_P(ExprTest, TestGISFunctionWithControlledData) {
using namespace milvus;
using namespace milvus::query;
using namespace milvus::segcore;
// Create schema with geometry field
auto schema = std::make_shared<Schema>();
auto int_fid = schema->AddDebugField("int", DataType::INT64);
auto vec_fid = schema->AddDebugField(
"fakevec", DataType::VECTOR_FLOAT, 16, knowhere::metric::L2);
auto geom_fid = schema->AddDebugField("geometry", DataType::GEOMETRY);
schema->set_primary_field_id(int_fid);
auto seg = CreateGrowingSegment(schema, empty_index_meta);
int N = 100;
int num_iters = 1;
// Generate controlled test data
for (int iter = 0; iter < num_iters; ++iter) {
auto raw_data = DataGen(schema, N, iter);
// Replace geometry data with controlled test data
milvus::proto::schema::FieldData* geometry_field_data = nullptr;
for (auto& fd : *raw_data.raw_->mutable_fields_data()) {
if (fd.field_id() == geom_fid.get()) {
geometry_field_data = &fd;
break;
}
}
assert(geometry_field_data != nullptr);
geometry_field_data->mutable_scalars()
->mutable_geometry_data()
->clear_data();
// Create some controlled geometry data for testing
for (int i = 0; i < N; ++i) {
OGRGeometry* geometry = nullptr;
if (i % 4 == 0) {
// Create point (0, 0)
OGRPoint point(0.0, 0.0);
geometry = point.clone();
} else if (i % 4 == 1) {
// Create polygon containing (0, 0)
OGRPolygon polygon;
OGRLinearRing ring;
ring.addPoint(-1.0, -1.0);
ring.addPoint(1.0, -1.0);
ring.addPoint(1.0, 1.0);
ring.addPoint(-1.0, 1.0);
ring.addPoint(-1.0, -1.0);
polygon.addRing(&ring);
geometry = polygon.clone();
} else if (i % 4 == 2) {
// Create polygon not containing (0, 0)
OGRPolygon polygon;
OGRLinearRing ring;
ring.addPoint(10.0, 10.0);
ring.addPoint(20.0, 10.0);
ring.addPoint(20.0, 20.0);
ring.addPoint(10.0, 20.0);
ring.addPoint(10.0, 10.0);
polygon.addRing(&ring);
geometry = polygon.clone();
} else {
// Create line passing through (0, 0)
OGRLineString lineString;
lineString.addPoint(-1.0, 0.0);
lineString.addPoint(1.0, 0.0);
geometry = lineString.clone();
}
// Convert to WKB format
size_t size = geometry->WkbSize();
std::vector<unsigned char> wkb(size);
geometry->exportToWkb(wkbNDR, wkb.data());
geometry_field_data->mutable_scalars()
->mutable_geometry_data()
->add_data(
std::string(reinterpret_cast<char*>(wkb.data()), size));
OGRGeometryFactory::destroyGeometry(geometry);
}
seg->PreInsert(N);
seg->Insert(iter * N,
N,
raw_data.row_ids_.data(),
raw_data.timestamps_.data(),
raw_data.raw_);
}
auto seg_promote = dynamic_cast<SegmentGrowingImpl*>(seg.get());
// Test specific GIS operations
auto test_gis_operation = [&](const std::string& wkt,
proto::plan::GISFunctionFilterExpr_GISOp op,
std::function<bool(int)> expected_func) {
// Create Geometry object from WKT string
milvus::Geometry geometry(wkt.c_str());
// Create GIS expression directly
auto gis_expr = std::make_shared<milvus::expr::GISFunctionFilterExpr>(
milvus::expr::ColumnInfo(geom_fid, DataType::GEOMETRY),
op,
geometry);
auto plan = std::make_shared<plan::FilterBitsNode>(DEFAULT_PLANNODE_ID,
gis_expr);
BitsetType final =
ExecuteQueryExpr(plan, seg_promote, N * num_iters, MAX_TIMESTAMP);
EXPECT_EQ(final.size(), N * num_iters);
// Verify results
for (int i = 0; i < N * num_iters; ++i) {
auto ans = final[i];
auto expected = expected_func(i);
ASSERT_EQ(ans, expected) << "GIS operation failed at index " << i;
}
};
// Test contains operation
test_gis_operation("POLYGON((-2 -2, 2 -2, 2 2, -2 2, -2 -2))",
proto::plan::GISFunctionFilterExpr_GISOp_Within,
[](int i) -> bool {
// Only geometry at index 0,1 (polygon containing (0,0))
return (i % 4 == 0) || (i % 4 == 1) || (i % 4 == 3);
});
// Test intersects operation
test_gis_operation("POINT(0 0)",
proto::plan::GISFunctionFilterExpr_GISOp_Intersects,
[](int i) -> bool {
// Point at index 0 (0,0), polygon at index 1, line at index 3 should all intersect with point (0,0)
return (i % 4 == 0) || (i % 4 == 1) || (i % 4 == 3);
});
// Test equals operation
test_gis_operation("POINT(0 0)",
proto::plan::GISFunctionFilterExpr_GISOp_Equals,
[](int i) -> bool {
// Only point at index 0 (0,0) should be equal
return (i % 4 == 0);
});
}
TEST_P(ExprTest, ParseGISFunctionFilterExprs) {
// Build Schema
auto schema = std::make_shared<Schema>();
auto dim = 16;
auto vec_id = schema->AddDebugField(
"vec", DataType::VECTOR_FLOAT, dim, knowhere::metric::L2);
auto geo_id = schema->AddDebugField("geo", DataType::GEOMETRY);
auto pk_id = schema->AddDebugField("pk", DataType::INT64);
schema->set_primary_field_id(pk_id);
// Generate data and load
int64_t N = 1000;
auto dataset = DataGen(schema, N);
auto seg = CreateSealedSegment(schema);
SealedLoadFieldData(dataset, *seg);
// Test plan with gisfunction_filter_expr
std::string raw_plan = R"PLAN(vector_anns: <
field_id: 100
predicates: <
gisfunction_filter_expr: <
column_info: <
field_id: 101
data_type: Geometry
>
op: Within
wkt_string: "POLYGON((0 0,1 0,1 1,0 1,0 0))"
>
>
query_info: <
topk: 5
metric_type: "L2"
round_decimal: 3
search_params: "{\"nprobe\":10}"
>
placeholder_tag: "$0"
>)PLAN";
// Convert and parse
auto bin_plan = translate_text_plan_with_metric_type(raw_plan);
auto plan =
CreateSearchPlanByExpr(*schema, bin_plan.data(), bin_plan.size());
// If parsing fails, test will fail with exception
// If parsing succeeds, ParseGISFunctionFilterExprs is covered
// Execute search to verify execution logic
auto ph_raw = CreatePlaceholderGroup(5, dim, 123);
auto ph_grp = ParsePlaceholderGroup(plan.get(), ph_raw.SerializeAsString());
auto sr = seg->Search(plan.get(), ph_grp.get(), MAX_TIMESTAMP);
}
TEST(ExprTest, ParseGISFunctionFilterExprsMultipleOps) {
// Build Schema
auto schema = std::make_shared<Schema>();
auto dim = 16;
auto vec_id = schema->AddDebugField(
"vec", DataType::VECTOR_FLOAT, dim, knowhere::metric::L2);
auto geo_id = schema->AddDebugField("geo", DataType::GEOMETRY);
auto pk_id = schema->AddDebugField("pk", DataType::INT64);
schema->set_primary_field_id(pk_id);
// Generate data and load
int64_t N = 1000;
auto dataset = DataGen(schema, N);
auto seg = CreateSealedSegment(schema);
SealedLoadFieldData(dataset, *seg);
// Test different GIS operations
std::vector<std::pair<std::string, std::string>> test_cases = {
{"Within", "POLYGON((0 0,1 0,1 1,0 1,0 0))"},
{"Contains", "POINT(0.5 0.5)"},
{"Intersects", "LINESTRING(0 0,1 1)"},
{"Equals", "POINT(0 0)"},
{"Touches", "POLYGON((10 10,11 10,11 11,10 11,10 10))"}};
for (const auto& test_case : test_cases) {
const auto& op = test_case.first;
const auto& wkt = test_case.second;
std::string raw_plan = R"(
vector_anns: <
field_id: 100
predicates: <
gisfunction_filter_expr: <
column_info: <
field_id: 101
data_type: Geometry
>
op: )" +
op + R"(
wkt_string: ")" +
wkt + R"("
>
>
query_info: <
topk: 5
metric_type: "L2"
round_decimal: 3
search_params: "{\"nprobe\":10}"
>
placeholder_tag: "$0"
>
)";
// Convert and parse
auto bin_plan = translate_text_plan_to_binary_plan(raw_plan.c_str());
auto plan =
CreateSearchPlanByExpr(*schema, bin_plan.data(), bin_plan.size());
// Execute search to verify execution logic
auto ph_raw = CreatePlaceholderGroup(5, dim, 123);
auto ph_grp =
ParsePlaceholderGroup(plan.get(), ph_raw.SerializeAsString());
auto sr = seg->Search(plan.get(), ph_grp.get(), MAX_TIMESTAMP);
EXPECT_EQ(sr->total_nq_, 5) << "Failed for operation: " << op;
}
}

View File

@ -10,6 +10,7 @@
// or implied. See the License for the specific language governing permissions and limitations under the License
#include <gtest/gtest.h>
#include <cstdint>
#include "common/Schema.h"
#include "query/Plan.h"
#include "segcore/SegmentSealedImpl.h"
@ -543,9 +544,9 @@ TEST(GroupBY, Reduce) {
int repeat_count_1 = 2;
int repeat_count_2 = 5;
auto raw_data1 =
DataGen(schema, N, seed, ts_offset, repeat_count_1, false, false);
DataGen(schema, N, seed, ts_offset, repeat_count_1, 10, false, false);
auto raw_data2 =
DataGen(schema, N, seed, ts_offset, repeat_count_2, false, false);
DataGen(schema, N, seed, ts_offset, repeat_count_2, 10, false, false);
auto fields = schema->get_fields();
//load segment1 raw data

View File

@ -150,6 +150,7 @@ TEST_P(GrowingTest, FillData) {
auto double_field = schema->AddDebugField("double", DataType::DOUBLE);
auto varchar_field = schema->AddDebugField("varchar", DataType::VARCHAR);
auto json_field = schema->AddDebugField("json", DataType::JSON);
auto geometry_field = schema->AddDebugField("geometry", DataType::GEOMETRY);
auto int_array_field =
schema->AddDebugField("int_array", DataType::ARRAY, DataType::INT8);
auto long_array_field =
@ -213,6 +214,8 @@ TEST_P(GrowingTest, FillData) {
varchar_field, ids_ds->GetIds(), num_inserted);
auto json_result =
segment->bulk_subscript(json_field, ids_ds->GetIds(), num_inserted);
auto geometry_result = segment->bulk_subscript(
geometry_field, ids_ds->GetIds(), num_inserted);
auto int_array_result = segment->bulk_subscript(
int_array_field, ids_ds->GetIds(), num_inserted);
auto long_array_result = segment->bulk_subscript(
@ -241,6 +244,8 @@ TEST_P(GrowingTest, FillData) {
EXPECT_EQ(varchar_result->scalars().string_data().data_size(),
num_inserted);
EXPECT_EQ(json_result->scalars().json_data().data_size(), num_inserted);
EXPECT_EQ(geometry_result->scalars().geometry_data().data_size(),
num_inserted);
if (data_type == DataType::VECTOR_FLOAT) {
EXPECT_EQ(vec_result->vectors().float_vector().data_size(),
num_inserted * dim);

View File

@ -491,6 +491,7 @@ TEST(Sealed, LoadFieldData) {
schema->AddDebugField("int16", DataType::INT16);
schema->AddDebugField("float", DataType::FLOAT);
schema->AddDebugField("json", DataType::JSON);
schema->AddDebugField("geometry", DataType::GEOMETRY);
schema->AddDebugField("array", DataType::ARRAY, DataType::INT64);
schema->set_primary_field_id(counter_id);
auto int8_nullable_id =
@ -668,6 +669,7 @@ TEST(Sealed, ClearData) {
schema->AddDebugField("int16", DataType::INT16);
schema->AddDebugField("float", DataType::FLOAT);
schema->AddDebugField("json", DataType::JSON);
schema->AddDebugField("geometry", DataType::GEOMETRY);
schema->AddDebugField("array", DataType::ARRAY, DataType::INT64);
schema->set_primary_field_id(counter_id);
@ -799,6 +801,7 @@ TEST(Sealed, LoadFieldDataMmap) {
schema->AddDebugField("int16", DataType::INT16);
schema->AddDebugField("float", DataType::FLOAT);
schema->AddDebugField("json", DataType::JSON);
schema->AddDebugField("geometry", DataType::GEOMETRY);
schema->AddDebugField("array", DataType::ARRAY, DataType::INT64);
schema->set_primary_field_id(counter_id);
@ -2263,6 +2266,7 @@ TEST(Sealed, QueryAllFields) {
auto double_field = schema->AddDebugField("double", DataType::DOUBLE);
auto varchar_field = schema->AddDebugField("varchar", DataType::VARCHAR);
auto json_field = schema->AddDebugField("json", DataType::JSON);
auto geometry_field = schema->AddDebugField("geometry", DataType::GEOMETRY);
auto int_array_field =
schema->AddDebugField("int_array", DataType::ARRAY, DataType::INT8);
auto long_array_field =
@ -2310,6 +2314,7 @@ TEST(Sealed, QueryAllFields) {
auto double_values = dataset.get_col<double>(double_field);
auto varchar_values = dataset.get_col<std::string>(varchar_field);
auto json_values = dataset.get_col<std::string>(json_field);
auto geometry_values = dataset.get_col<std::string>(geometry_field);
auto int_array_values = dataset.get_col<ScalarArray>(int_array_field);
auto long_array_values = dataset.get_col<ScalarArray>(long_array_field);
auto bool_array_values = dataset.get_col<ScalarArray>(bool_array_field);
@ -2339,6 +2344,8 @@ TEST(Sealed, QueryAllFields) {
segment->bulk_subscript(varchar_field, ids_ds->GetIds(), dataset_size);
auto json_result =
segment->bulk_subscript(json_field, ids_ds->GetIds(), dataset_size);
auto geometry_result =
segment->bulk_subscript(geometry_field, ids_ds->GetIds(), dataset_size);
auto int_array_result = segment->bulk_subscript(
int_array_field, ids_ds->GetIds(), dataset_size);
auto long_array_result = segment->bulk_subscript(
@ -2368,6 +2375,8 @@ TEST(Sealed, QueryAllFields) {
EXPECT_EQ(varchar_result->scalars().string_data().data_size(),
dataset_size);
EXPECT_EQ(json_result->scalars().json_data().data_size(), dataset_size);
EXPECT_EQ(geometry_result->scalars().geometry_data().data_size(),
dataset_size);
EXPECT_EQ(vec_result->vectors().float_vector().data_size(),
dataset_size * dim);
EXPECT_EQ(float16_vec_result->vectors().float16_vector().size(),
@ -2417,6 +2426,8 @@ TEST(Sealed, QueryAllNullableFields) {
auto varchar_field =
schema->AddDebugField("varchar", DataType::VARCHAR, true);
auto json_field = schema->AddDebugField("json", DataType::JSON, true);
auto geometry_field =
schema->AddDebugField("geometry", DataType::GEOMETRY, true);
auto int_array_field = schema->AddDebugField(
"int_array", DataType::ARRAY, DataType::INT8, true);
auto long_array_field = schema->AddDebugField(
@ -2460,6 +2471,7 @@ TEST(Sealed, QueryAllNullableFields) {
auto double_values = dataset.get_col<double>(double_field);
auto varchar_values = dataset.get_col<std::string>(varchar_field);
auto json_values = dataset.get_col<std::string>(json_field);
auto geometry_values = dataset.get_col<std::string>(geometry_field);
auto int_array_values = dataset.get_col<ScalarArray>(int_array_field);
auto long_array_values = dataset.get_col<ScalarArray>(long_array_field);
auto bool_array_values = dataset.get_col<ScalarArray>(bool_array_field);
@ -2476,6 +2488,7 @@ TEST(Sealed, QueryAllNullableFields) {
auto double_valid_values = dataset.get_col_valid(double_field);
auto varchar_valid_values = dataset.get_col_valid(varchar_field);
auto json_valid_values = dataset.get_col_valid(json_field);
auto geometry_valid_values = dataset.get_col_valid(geometry_field);
auto int_array_valid_values = dataset.get_col_valid(int_array_field);
auto long_array_valid_values = dataset.get_col_valid(long_array_field);
auto bool_array_valid_values = dataset.get_col_valid(bool_array_field);
@ -2502,6 +2515,8 @@ TEST(Sealed, QueryAllNullableFields) {
segment->bulk_subscript(varchar_field, ids_ds->GetIds(), dataset_size);
auto json_result =
segment->bulk_subscript(json_field, ids_ds->GetIds(), dataset_size);
auto geometry_result =
segment->bulk_subscript(geometry_field, ids_ds->GetIds(), dataset_size);
auto int_array_result = segment->bulk_subscript(
int_array_field, ids_ds->GetIds(), dataset_size);
auto long_array_result = segment->bulk_subscript(
@ -2527,6 +2542,8 @@ TEST(Sealed, QueryAllNullableFields) {
EXPECT_EQ(varchar_result->scalars().string_data().data_size(),
dataset_size);
EXPECT_EQ(json_result->scalars().json_data().data_size(), dataset_size);
EXPECT_EQ(geometry_result->scalars().geometry_data().data_size(),
dataset_size);
EXPECT_EQ(vec_result->vectors().float_vector().data_size(),
dataset_size * dim);
EXPECT_EQ(int_array_result->scalars().array_data().data_size(),
@ -2550,6 +2567,7 @@ TEST(Sealed, QueryAllNullableFields) {
EXPECT_EQ(double_result->valid_data_size(), dataset_size);
EXPECT_EQ(varchar_result->valid_data_size(), dataset_size);
EXPECT_EQ(json_result->valid_data_size(), dataset_size);
EXPECT_EQ(geometry_result->valid_data_size(), dataset_size);
EXPECT_EQ(int_array_result->valid_data_size(), dataset_size);
EXPECT_EQ(long_array_result->valid_data_size(), dataset_size);
EXPECT_EQ(bool_array_result->valid_data_size(), dataset_size);
@ -2579,3 +2597,46 @@ TEST(Sealed, SearchSortedPk) {
EXPECT_EQ(5, offsets2.size());
EXPECT_EQ(100, offsets2[0].get());
}
TEST(Sealed, QueryAllFieldsWithGeo) {
auto schema = std::make_shared<Schema>();
auto metric_type = knowhere::metric::L2;
auto int64_field = schema->AddDebugField("int64", DataType::INT64);
auto geometry_field = schema->AddDebugField("geometry", DataType::GEOMETRY);
auto vec = schema->AddDebugField(
"embeddings", DataType::VECTOR_FLOAT, 128, metric_type);
schema->set_primary_field_id(int64_field);
std::map<std::string, std::string> index_params = {
{"index_type", "IVF_FLAT"},
{"metric_type", metric_type},
{"nlist", "128"}};
std::map<std::string, std::string> type_params = {{"dim", "128"}};
FieldIndexMeta fieldIndexMeta(
vec, std::move(index_params), std::move(type_params));
std::map<FieldId, FieldIndexMeta> filedMap = {{vec, fieldIndexMeta}};
IndexMetaPtr metaPtr =
std::make_shared<CollectionIndexMeta>(100000, std::move(filedMap));
auto segment_sealed = CreateSealedSegment(schema, metaPtr);
auto segment = dynamic_cast<SegmentSealedImpl*>(segment_sealed.get());
int64_t dataset_size = 1000;
auto dataset = DataGen(schema, dataset_size);
SealedLoadFieldData(dataset, *segment);
auto geometry_values = dataset.get_col<std::string>(geometry_field);
auto ids_ds = GenRandomIds(dataset_size);
auto geometry_result =
segment->bulk_subscript(geometry_field, ids_ds->GetIds(), dataset_size);
EXPECT_EQ(geometry_result->scalars().geometry_data().data_size(),
dataset_size);
for (size_t i = 0; i < dataset_size; ++i) {
auto id = ids_ds->GetIds()[i];
// verify
ASSERT_EQ(geometry_values[id],
geometry_result->scalars().geometry_data().data(i));
}
}

View File

@ -19,6 +19,7 @@
#include <cmath>
#include <google/protobuf/text_format.h>
#include <gtest/gtest.h>
#include <ogr_geometry.h>
#include <cstdlib>
#include "Constants.h"
@ -207,6 +208,14 @@ struct GeneratedData {
std::copy(src_data.begin(), src_data.end(), ret_data);
break;
}
case DataType::GEOMETRY: {
auto ret_data =
reinterpret_cast<std::string*>(ret.data());
auto src_data =
target_field_data.scalars().geometry_data().data();
std::copy(src_data.begin(), src_data.end(), ret_data);
break;
}
default: {
PanicInfo(Unsupported, "unsupported");
}
@ -335,6 +344,109 @@ GenerateRandomSparseFloatVector(size_t rows,
return tensor;
}
inline OGRGeometry* makeGeometryValid(OGRGeometry* geometry) {
if (!geometry || geometry->IsValid())
return geometry;
OGRGeometry* fixed = geometry->MakeValid();
if (fixed) {
OGRGeometryFactory::destroyGeometry(geometry);
geometry = fixed;
}
return geometry;
}
inline void
generateRandomPoint(OGRPoint& point) {
point.setX(static_cast<double>(rand()) / RAND_MAX * 360.0 - 180.0);
point.setY(static_cast<double>(rand()) / RAND_MAX * 180.0 - 90.0);
}
inline void
generateRandomValidLineString(OGRLineString& lineString, int numPoints) {
// Generate a simple line string that doesn't self-intersect
double startX = static_cast<double>(rand()) / RAND_MAX * 300.0 - 150.0;
double startY = static_cast<double>(rand()) / RAND_MAX * 160.0 - 80.0;
OGRPoint point;
point.setX(startX);
point.setY(startY);
lineString.addPoint(&point);
for (int i = 1; i < numPoints; ++i) {
// Generate next point with some distance from previous point
double deltaX = (static_cast<double>(rand()) / RAND_MAX - 0.5) * 20.0;
double deltaY = (static_cast<double>(rand()) / RAND_MAX - 0.5) * 20.0;
point.setX(startX + deltaX);
point.setY(startY + deltaY);
lineString.addPoint(&point);
startX = point.getX();
startY = point.getY();
}
}
inline void
generateRandomValidPolygon(OGRPolygon& polygon, int numPoints) {
// Generate a simple convex polygon to avoid self-intersection
if (numPoints < 3)
numPoints = 3;
OGRLinearRing ring;
// Generate center point
double centerX = static_cast<double>(rand()) / RAND_MAX * 300.0 - 150.0;
double centerY = static_cast<double>(rand()) / RAND_MAX * 160.0 - 80.0;
// Generate radius
double radius = 5.0 + static_cast<double>(rand()) / RAND_MAX * 15.0;
// Generate points in a circle to form a convex polygon
for (int i = 0; i < numPoints; ++i) {
double angle = 2.0 * M_PI * i / numPoints;
double x = centerX + radius * cos(angle);
double y = centerY + radius * sin(angle);
OGRPoint point;
point.setX(x);
point.setY(y);
ring.addPoint(&point);
}
// Close the ring
ring.closeRings();
polygon.addRing(&ring);
}
inline OGRGeometry*
GenRandomGeometry() {
OGRGeometry* geometry = nullptr;
int geomType = rand() % 3; // Randomly select a geometry type (0 to 2)
switch (geomType) {
case 0: {
OGRPoint point;
generateRandomPoint(point);
geometry = point.clone();
break;
}
case 1: {
OGRLineString lineString;
generateRandomValidLineString(lineString, 5);
geometry = lineString.clone();
break;
}
case 2: {
OGRPolygon polygon;
generateRandomValidPolygon(polygon, 5);
geometry = polygon.clone();
break;
}
}
geometry = makeGeometryValid(geometry);
return geometry;
}
inline GeneratedData
DataGen(SchemaPtr schema,
int64_t N,
@ -545,6 +657,21 @@ DataGen(SchemaPtr schema,
insert_cols(data, N, field_meta, random_valid);
break;
}
case DataType::GEOMETRY: {
vector<std::string> data(N);
for (int i = 0; i < N / repeat_count; i++) {
OGRGeometry* geo = GenRandomGeometry();
size_t size = geo->WkbSize();
auto wkb_data = new unsigned char[size];
geo->exportToWkb(wkbNDR, wkb_data);
data[i] = std::string(
reinterpret_cast<const char*>(wkb_data), size);
OGRGeometryFactory::destroyGeometry(geo);
delete[] wkb_data;
}
insert_cols(data, N, field_meta, random_valid);
break;
}
case DataType::ARRAY: {
vector<ScalarArray> data(N);
switch (field_meta.get_element_type()) {
@ -1186,6 +1313,16 @@ CreateFieldDataFromDataArray(ssize_t raw_count,
}
break;
}
case DataType::GEOMETRY: {
auto src_data = data->scalars().geometry_data().data();
std::vector<std::string> data_raw(src_data.size());
for (int i = 0; i < src_data.size(); i++) {
auto str = src_data.Get(i);
data_raw[i] = std::move(std::string(str));
}
createFieldData(data_raw.data(), DataType::GEOMETRY, dim);
break;
}
case DataType::ARRAY: {
auto src_data = data->scalars().array_data().data();
std::vector<Array> data_raw(src_data.size());

View File

@ -19,6 +19,7 @@ package httpserver
import (
"bytes"
"context"
"encoding/base64"
"fmt"
"math"
"reflect"
@ -30,6 +31,8 @@ import (
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"github.com/tidwall/gjson"
"github.com/twpayne/go-geom/encoding/wkb"
"github.com/twpayne/go-geom/encoding/wkt"
"go.uber.org/zap"
"google.golang.org/protobuf/proto"
@ -545,6 +548,25 @@ func checkAndSetData(body []byte, collSchema *schemapb.CollectionSchema) (error,
}
case schemapb.DataType_JSON:
reallyData[fieldName] = []byte(dataString)
case schemapb.DataType_Geometry:
// treat as string(wkt) data,the string data must be valid
WktString, err := base64.StdEncoding.DecodeString(dataString)
if err != nil {
log.Warn("proxy can not decode datastring with base64", zap.String("WktString:", dataString))
return merr.WrapErrParameterInvalid(schemapb.DataType_name[int32(fieldType)], dataString, err.Error()), reallyDataArray, validDataMap
}
geomT, err := wkt.Unmarshal(string(WktString))
if err != nil {
log.Warn("proxy change wkt to geomtyr failed!!", zap.String("WktString:", dataString))
return merr.WrapErrParameterInvalid(schemapb.DataType_name[int32(fieldType)], dataString, err.Error()), reallyDataArray, validDataMap
}
// translate the wkt bytes to wkb bytes ,store the bytes in LittleEndian which cpp core used as well
dataWkbBytes, err := wkb.Marshal(geomT, wkb.NDR)
if err != nil {
log.Warn("proxy change geomtry to wkb failed!!", zap.String("WktString:", dataString))
return merr.WrapErrParameterInvalid(schemapb.DataType_name[int32(fieldType)], dataString, err.Error()), reallyDataArray, validDataMap
}
reallyData[fieldName] = dataWkbBytes
case schemapb.DataType_Float:
result, err := cast.ToFloat32E(dataString)
if err != nil {
@ -752,6 +774,8 @@ func anyToColumns(rows []map[string]interface{}, validDataMap map[string][]bool,
data = make([]*schemapb.ScalarField, 0, rowsLen)
case schemapb.DataType_JSON:
data = make([][]byte, 0, rowsLen)
case schemapb.DataType_Geometry:
data = make([][]byte, 0, rowsLen)
case schemapb.DataType_FloatVector:
data = make([][]float32, 0, rowsLen)
dim, _ := getDim(field)
@ -841,6 +865,8 @@ func anyToColumns(rows []map[string]interface{}, validDataMap map[string][]bool,
nameColumns[field.Name] = append(nameColumns[field.Name].([]*schemapb.ScalarField), candi.v.Interface().(*schemapb.ScalarField))
case schemapb.DataType_JSON:
nameColumns[field.Name] = append(nameColumns[field.Name].([][]byte), candi.v.Interface().([]byte))
case schemapb.DataType_Geometry:
nameColumns[field.Name] = append(nameColumns[field.Name].([][]byte), candi.v.Interface().([]byte))
case schemapb.DataType_FloatVector:
nameColumns[field.Name] = append(nameColumns[field.Name].([][]float32), candi.v.Interface().([]float32))
case schemapb.DataType_BinaryVector:
@ -1005,6 +1031,16 @@ func anyToColumns(rows []map[string]interface{}, validDataMap map[string][]bool,
},
},
}
case schemapb.DataType_Geometry:
colData.Field = &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: column.([][]byte),
},
},
},
}
case schemapb.DataType_FloatVector:
dim := nameDims[name]
arr, err := convertFloatVectorToArray(column.([][]float32), dim)
@ -1273,6 +1309,8 @@ func buildQueryResp(rowsNum int64, needFields []string, fieldDataList []*schemap
rowsNum = int64(len(fieldDataList[0].GetScalars().GetArrayData().Data))
case schemapb.DataType_JSON:
rowsNum = int64(len(fieldDataList[0].GetScalars().GetJsonData().Data))
case schemapb.DataType_Geometry:
rowsNum = int64(len(fieldDataList[0].GetScalars().GetGeometryData().Data))
case schemapb.DataType_BinaryVector:
rowsNum = int64(len(fieldDataList[0].GetVectors().GetBinaryVector())*8) / fieldDataList[0].GetVectors().GetDim()
case schemapb.DataType_FloatVector:
@ -1423,6 +1461,12 @@ func buildQueryResp(rowsNum int64, needFields []string, fieldDataList []*schemap
}
}
}
case schemapb.DataType_Geometry:
if len(fieldDataList[j].ValidData) != 0 && !fieldDataList[j].ValidData[i] {
row[fieldDataList[j].FieldName] = nil
continue
}
row[fieldDataList[j].FieldName] = fieldDataList[j].GetScalars().GetGeometryData().Data[i]
default:
row[fieldDataList[j].FieldName] = ""
}

View File

@ -1229,6 +1229,12 @@ func compareRow(m1 map[string]interface{}, m2 map[string]interface{}) bool {
if arr1 != string(arr2) {
return false
}
} else if key == "field-geometry" {
arr1 := value.([]uint8)
arr2 := string(m2[key].([]byte))
if arr2 != (string)(arr1) {
return false
}
} else if strings.HasPrefix(key, "array-") {
continue
} else if value != m2[key] {
@ -1237,7 +1243,7 @@ func compareRow(m1 map[string]interface{}, m2 map[string]interface{}) bool {
}
for key, value := range m2 {
if (key == FieldBookIntro) || (key == "field-json") || (key == "field-array") {
if (key == FieldBookIntro) || (key == "field-json") || (key == "field-geometry") || (key == "field-array") {
continue
} else if strings.HasPrefix(key, "array-") {
continue
@ -1337,6 +1343,12 @@ func newCollectionSchema(coll *schemapb.CollectionSchema) *schemapb.CollectionSc
}
coll.Fields = append(coll.Fields, &fieldSchema10)
fieldSchema11 := schemapb.FieldSchema{
Name: "field-geometry",
DataType: schemapb.DataType_Geometry,
IsDynamic: false,
}
coll.Fields = append(coll.Fields, &fieldSchema11)
return coll
}
@ -1583,6 +1595,28 @@ func newFieldData(fieldDatas []*schemapb.FieldData, firstFieldType schemapb.Data
}
fieldDatas = append(fieldDatas, &fieldData11)
fieldData12 := schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: "field-geometry",
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
// WKT: POINT (30.123 -10.456)
Data: [][]byte{
[]byte(`POINT (30.123 -10.456)`),
[]byte(`POINT (30.123 -10.456)`),
[]byte(`POINT (30.123 -10.456)`),
// wkb:{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x4},
},
},
},
},
},
IsDynamic: false,
}
fieldDatas = append(fieldDatas, &fieldData12)
switch firstFieldType {
case schemapb.DataType_None:
return fieldDatas
@ -1618,6 +1652,8 @@ func newFieldData(fieldDatas []*schemapb.FieldData, firstFieldType schemapb.Data
return []*schemapb.FieldData{&fieldData10}
case schemapb.DataType_JSON:
return []*schemapb.FieldData{&fieldData9}
case schemapb.DataType_Geometry:
return []*schemapb.FieldData{&fieldData12}
case schemapb.DataType_SparseFloatVector:
vectorField := generateVectorFieldData(firstFieldType)
return []*schemapb.FieldData{&vectorField}
@ -1883,6 +1919,7 @@ func newSearchResult(results []map[string]interface{}) []map[string]interface{}
result["field-varchar"] = strconv.Itoa(i)
result["field-string"] = strconv.Itoa(i)
result["field-json"] = []byte(`{"XXX": 0}`)
result["field-geometry"] = []byte(`POINT (30.123 -10.456)`)
result["field-array"] = []bool{true}
result["array-bool"] = []bool{true}
result["array-int8"] = []int32{0}
@ -2175,6 +2212,7 @@ func TestBuildQueryResps(t *testing.T) {
schemapb.DataType_Float, schemapb.DataType_Double,
schemapb.DataType_String, schemapb.DataType_VarChar,
schemapb.DataType_JSON, schemapb.DataType_Array,
schemapb.DataType_Geometry,
}
for _, dateType := range dataTypes {
_, err := buildQueryResp(int64(0), outputFields, newFieldData([]*schemapb.FieldData{}, dateType), generateIDs(schemapb.DataType_Int64, 3), DefaultScores, true, nil)

View File

@ -25,6 +25,13 @@ expr:
| (JSONContains | ArrayContains)'('expr',' expr')' # JSONContains
| (JSONContainsAll | ArrayContainsAll)'('expr',' expr')' # JSONContainsAll
| (JSONContainsAny | ArrayContainsAny)'('expr',' expr')' # JSONContainsAny
| STEuqals'('Identifier','StringLiteral')' # STEuqals
| STTouches'('Identifier','StringLiteral')' # STTouches
| STOverlaps'('Identifier','StringLiteral')' # STOverlaps
| STCrosses'('Identifier','StringLiteral')' # STCrosses
| STContains'('Identifier','StringLiteral')' # STContains
| STIntersects'('Identifier','StringLiteral')' # STIntersects
| STWithin'('Identifier','StringLiteral')' # STWithin
| ArrayLength'('(Identifier | JSONIdentifier)')' # ArrayLength
| Identifier '(' ( expr (',' expr )* ','? )? ')' # Call
| expr op1 = (LT | LE) (Identifier | JSONIdentifier) op2 = (LT | LE) expr # Range
@ -96,6 +103,14 @@ ArrayContainsAll: 'array_contains_all' | 'ARRAY_CONTAINS_ALL';
ArrayContainsAny: 'array_contains_any' | 'ARRAY_CONTAINS_ANY';
ArrayLength: 'array_length' | 'ARRAY_LENGTH';
STEuqals:'st_equals' | 'ST_EQUALS';
STTouches:'st_touches' | 'ST_TOUCHES';
STOverlaps: 'st_overlaps' | 'ST_OVERLAPS';
STCrosses: 'st_crosses' | 'ST_CROSSES';
STContains: 'st_contains' | 'ST_CONTAINS';
STIntersects : 'st_intersects' | 'ST_INTERSECTS';
STWithin :'st_within' | 'ST_WITHIN';
BooleanConstant: 'true' | 'True' | 'TRUE' | 'false' | 'False' | 'FALSE';
IntegerConstant:

File diff suppressed because one or more lines are too long

View File

@ -41,15 +41,22 @@ ArrayContains=40
ArrayContainsAll=41
ArrayContainsAny=42
ArrayLength=43
BooleanConstant=44
IntegerConstant=45
FloatingConstant=46
Identifier=47
Meta=48
StringLiteral=49
JSONIdentifier=50
Whitespace=51
Newline=52
STEuqals=44
STTouches=45
STOverlaps=46
STCrosses=47
STContains=48
STIntersects=49
STWithin=50
BooleanConstant=51
IntegerConstant=52
FloatingConstant=53
Identifier=54
Meta=55
StringLiteral=56
JSONIdentifier=57
Whitespace=58
Newline=59
'('=1
')'=2
'['=3
@ -75,4 +82,4 @@ Newline=52
'|'=27
'^'=28
'~'=33
'$meta'=48
'$meta'=55

File diff suppressed because one or more lines are too long

View File

@ -41,15 +41,22 @@ ArrayContains=40
ArrayContainsAll=41
ArrayContainsAny=42
ArrayLength=43
BooleanConstant=44
IntegerConstant=45
FloatingConstant=46
Identifier=47
Meta=48
StringLiteral=49
JSONIdentifier=50
Whitespace=51
Newline=52
STEuqals=44
STTouches=45
STOverlaps=46
STCrosses=47
STContains=48
STIntersects=49
STWithin=50
BooleanConstant=51
IntegerConstant=52
FloatingConstant=53
Identifier=54
Meta=55
StringLiteral=56
JSONIdentifier=57
Whitespace=58
Newline=59
'('=1
')'=2
'['=3
@ -75,4 +82,4 @@ Newline=52
'|'=27
'^'=28
'~'=33
'$meta'=48
'$meta'=55

View File

@ -43,6 +43,10 @@ func (v *BasePlanVisitor) VisitIdentifier(ctx *IdentifierContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitSTIntersects(ctx *STIntersectsContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitLike(ctx *LikeContext) interface{} {
return v.VisitChildren(ctx)
}
@ -71,6 +75,10 @@ func (v *BasePlanVisitor) VisitCall(ctx *CallContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitSTCrosses(ctx *STCrossesContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitReverseRange(ctx *ReverseRangeContext) interface{} {
return v.VisitChildren(ctx)
}
@ -103,6 +111,14 @@ func (v *BasePlanVisitor) VisitTextMatch(ctx *TextMatchContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitSTTouches(ctx *STTouchesContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitSTContains(ctx *STContainsContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitTerm(ctx *TermContext) interface{} {
return v.VisitChildren(ctx)
}
@ -111,6 +127,10 @@ func (v *BasePlanVisitor) VisitJSONContains(ctx *JSONContainsContext) interface{
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitSTWithin(ctx *STWithinContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitRange(ctx *RangeContext) interface{} {
return v.VisitChildren(ctx)
}
@ -143,6 +163,10 @@ func (v *BasePlanVisitor) VisitBitAnd(ctx *BitAndContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitSTEuqals(ctx *STEuqalsContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitIsNull(ctx *IsNullContext) interface{} {
return v.VisitChildren(ctx)
}
@ -150,3 +174,7 @@ func (v *BasePlanVisitor) VisitIsNull(ctx *IsNullContext) interface{} {
func (v *BasePlanVisitor) VisitPower(ctx *PowerContext) interface{} {
return v.VisitChildren(ctx)
}
func (v *BasePlanVisitor) VisitSTOverlaps(ctx *STOverlapsContext) interface{} {
return v.VisitChildren(ctx)
}

View File

@ -46,7 +46,8 @@ func planlexerLexerInit() {
"", "'('", "')'", "'['", "','", "']'", "'{'", "'}'", "'<'", "'<='",
"'>'", "'>='", "'=='", "'!='", "", "", "", "", "'+'", "'-'", "'*'",
"'/'", "'%'", "'**'", "'<<'", "'>>'", "'&'", "'|'", "'^'", "", "", "",
"", "'~'", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "'$meta'",
"", "'~'", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",
"", "", "", "", "", "", "'$meta'",
}
staticData.SymbolicNames = []string{
"", "", "", "", "", "", "LBRACE", "RBRACE", "LT", "LE", "GT", "GE",
@ -54,9 +55,10 @@ func planlexerLexerInit() {
"MUL", "DIV", "MOD", "POW", "SHL", "SHR", "BAND", "BOR", "BXOR", "AND",
"OR", "ISNULL", "ISNOTNULL", "BNOT", "NOT", "IN", "EmptyArray", "JSONContains",
"JSONContainsAll", "JSONContainsAny", "ArrayContains", "ArrayContainsAll",
"ArrayContainsAny", "ArrayLength", "BooleanConstant", "IntegerConstant",
"FloatingConstant", "Identifier", "Meta", "StringLiteral", "JSONIdentifier",
"Whitespace", "Newline",
"ArrayContainsAny", "ArrayLength", "STEuqals", "STTouches", "STOverlaps",
"STCrosses", "STContains", "STIntersects", "STWithin", "BooleanConstant",
"IntegerConstant", "FloatingConstant", "Identifier", "Meta", "StringLiteral",
"JSONIdentifier", "Whitespace", "Newline",
}
staticData.RuleNames = []string{
"T__0", "T__1", "T__2", "T__3", "T__4", "LBRACE", "RBRACE", "LT", "LE",
@ -64,408 +66,487 @@ func planlexerLexerInit() {
"ADD", "SUB", "MUL", "DIV", "MOD", "POW", "SHL", "SHR", "BAND", "BOR",
"BXOR", "AND", "OR", "ISNULL", "ISNOTNULL", "BNOT", "NOT", "IN", "EmptyArray",
"JSONContains", "JSONContainsAll", "JSONContainsAny", "ArrayContains",
"ArrayContainsAll", "ArrayContainsAny", "ArrayLength", "BooleanConstant",
"IntegerConstant", "FloatingConstant", "Identifier", "Meta", "StringLiteral",
"JSONIdentifier", "EncodingPrefix", "DoubleSCharSequence", "SingleSCharSequence",
"DoubleSChar", "SingleSChar", "Nondigit", "Digit", "BinaryConstant",
"DecimalConstant", "OctalConstant", "HexadecimalConstant", "NonzeroDigit",
"OctalDigit", "HexadecimalDigit", "HexQuad", "UniversalCharacterName",
"ArrayContainsAll", "ArrayContainsAny", "ArrayLength", "STEuqals", "STTouches",
"STOverlaps", "STCrosses", "STContains", "STIntersects", "STWithin",
"BooleanConstant", "IntegerConstant", "FloatingConstant", "Identifier",
"Meta", "StringLiteral", "JSONIdentifier", "EncodingPrefix", "DoubleSCharSequence",
"SingleSCharSequence", "DoubleSChar", "SingleSChar", "Nondigit", "Digit",
"BinaryConstant", "DecimalConstant", "OctalConstant", "HexadecimalConstant",
"NonzeroDigit", "OctalDigit", "HexadecimalDigit", "HexQuad", "UniversalCharacterName",
"DecimalFloatingConstant", "HexadecimalFloatingConstant", "FractionalConstant",
"ExponentPart", "DigitSequence", "HexadecimalFractionalConstant", "HexadecimalDigitSequence",
"BinaryExponentPart", "EscapeSequence", "Whitespace", "Newline",
}
staticData.PredictionContextCache = antlr.NewPredictionContextCache()
staticData.serializedATN = []int32{
4, 0, 52, 862, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2,
4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2,
10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15,
7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7,
20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25,
2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2,
31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36,
7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7,
41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46,
2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2,
52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57,
7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7,
62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67,
2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2,
73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 1, 0, 1, 0, 1, 1,
1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 7,
1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10, 1, 10, 1, 11, 1, 11,
1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1,
13, 1, 13, 3, 13, 194, 8, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14,
1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 208, 8, 14, 1, 15, 1,
4, 0, 59, 1036, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3,
2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9,
2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2,
15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20,
7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7,
25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30,
2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2,
36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41,
7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7,
46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51,
2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2,
57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62,
7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7,
67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72,
2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2,
78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83,
7, 83, 1, 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 5,
1, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 1, 9, 1, 9, 1, 10, 1, 10,
1, 10, 1, 11, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 13, 1, 13, 1, 13, 1,
13, 1, 13, 1, 13, 1, 13, 1, 13, 3, 13, 208, 8, 13, 1, 14, 1, 14, 1, 14,
1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 3, 14, 222,
8, 14, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1,
15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15,
1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 1, 15, 3, 15, 230, 8,
15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16,
1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1,
16, 1, 16, 1, 16, 1, 16, 3, 16, 256, 8, 16, 1, 17, 1, 17, 1, 18, 1, 18,
1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22, 1, 22, 1, 23, 1,
23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1, 26, 1, 27, 1, 27,
1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 3, 28, 291, 8,
28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 3, 29, 299, 8, 29, 1, 30,
1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1,
30, 1, 30, 1, 30, 3, 30, 315, 8, 30, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31,
3, 15, 244, 8, 15, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1,
16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16,
1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 1, 16, 3, 16, 270, 8, 16, 1, 17, 1,
17, 1, 18, 1, 18, 1, 19, 1, 19, 1, 20, 1, 20, 1, 21, 1, 21, 1, 22, 1, 22,
1, 22, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 26, 1,
26, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28, 1, 28,
3, 28, 305, 8, 28, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 1, 29, 3, 29, 313,
8, 29, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1, 30, 1,
30, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 329, 8, 30, 1, 31, 1, 31, 1, 31,
1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1,
31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 3, 31, 339, 8, 31, 1, 32,
1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 3, 33, 350, 8,
33, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 356, 8, 34, 1, 35, 1, 35, 1, 35,
5, 35, 361, 8, 35, 10, 35, 12, 35, 364, 9, 35, 1, 35, 1, 35, 1, 36, 1,
36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36,
31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 3, 31, 353,
8, 31, 1, 32, 1, 32, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 1, 33, 3,
33, 364, 8, 33, 1, 34, 1, 34, 1, 34, 1, 34, 3, 34, 370, 8, 34, 1, 35, 1,
35, 1, 35, 5, 35, 375, 8, 35, 10, 35, 12, 35, 378, 9, 35, 1, 35, 1, 35,
1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1,
36, 1, 36, 1, 36, 1, 36, 3, 36, 394, 8, 36, 1, 37, 1, 37, 1, 37, 1, 37,
36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 1, 36,
1, 36, 1, 36, 1, 36, 1, 36, 1, 36, 3, 36, 408, 8, 36, 1, 37, 1, 37, 1,
37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37,
1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1,
37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37,
1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 3, 37, 430,
8, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1,
3, 37, 444, 8, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1,
38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38,
1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1,
38, 1, 38, 1, 38, 1, 38, 3, 38, 466, 8, 38, 1, 39, 1, 39, 1, 39, 1, 39,
38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 3, 38, 480, 8, 38, 1, 39, 1, 39,
1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1,
39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39,
1, 39, 1, 39, 1, 39, 3, 39, 496, 8, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1,
1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 3, 39, 510, 8, 39, 1, 40, 1, 40, 1,
40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40,
1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1,
40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40,
3, 40, 534, 8, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1,
1, 40, 1, 40, 3, 40, 548, 8, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1,
41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41,
1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1,
41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41, 572, 8, 41,
1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1,
41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 3, 41,
586, 8, 41, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1,
42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 1, 42,
1, 42, 1, 42, 1, 42, 3, 42, 598, 8, 42, 1, 43, 1, 43, 1, 43, 1, 43, 1,
1, 42, 1, 42, 1, 42, 1, 42, 1, 42, 3, 42, 612, 8, 42, 1, 43, 1, 43, 1,
43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43,
1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 1,
43, 1, 43, 3, 43, 627, 8, 43, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 633, 8,
44, 1, 45, 1, 45, 3, 45, 637, 8, 45, 1, 46, 1, 46, 1, 46, 5, 46, 642, 8,
46, 10, 46, 12, 46, 645, 9, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47,
1, 48, 3, 48, 654, 8, 48, 1, 48, 1, 48, 3, 48, 658, 8, 48, 1, 48, 1, 48,
1, 48, 3, 48, 663, 8, 48, 1, 48, 3, 48, 666, 8, 48, 1, 49, 1, 49, 3, 49,
670, 8, 49, 1, 49, 1, 49, 1, 49, 3, 49, 675, 8, 49, 1, 49, 1, 49, 4, 49,
679, 8, 49, 11, 49, 12, 49, 680, 1, 50, 1, 50, 1, 50, 3, 50, 686, 8, 50,
1, 51, 4, 51, 689, 8, 51, 11, 51, 12, 51, 690, 1, 52, 4, 52, 694, 8, 52,
11, 52, 12, 52, 695, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 1, 53, 3,
53, 705, 8, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 3, 54,
714, 8, 54, 1, 55, 1, 55, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 4, 57, 723,
8, 57, 11, 57, 12, 57, 724, 1, 58, 1, 58, 5, 58, 729, 8, 58, 10, 58, 12,
58, 732, 9, 58, 1, 58, 3, 58, 735, 8, 58, 1, 59, 1, 59, 5, 59, 739, 8,
59, 10, 59, 12, 59, 742, 9, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61,
1, 62, 1, 62, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1,
65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 3, 65, 769,
8, 65, 1, 66, 1, 66, 3, 66, 773, 8, 66, 1, 66, 1, 66, 1, 66, 3, 66, 778,
8, 66, 1, 67, 1, 67, 1, 67, 1, 67, 3, 67, 784, 8, 67, 1, 67, 1, 67, 1,
68, 3, 68, 789, 8, 68, 1, 68, 1, 68, 1, 68, 1, 68, 1, 68, 3, 68, 796, 8,
68, 1, 69, 1, 69, 3, 69, 800, 8, 69, 1, 69, 1, 69, 1, 70, 4, 70, 805, 8,
70, 11, 70, 12, 70, 806, 1, 71, 3, 71, 810, 8, 71, 1, 71, 1, 71, 1, 71,
1, 71, 1, 71, 3, 71, 817, 8, 71, 1, 72, 4, 72, 820, 8, 72, 11, 72, 12,
72, 821, 1, 73, 1, 73, 3, 73, 826, 8, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1,
74, 1, 74, 1, 74, 3, 74, 835, 8, 74, 1, 74, 3, 74, 838, 8, 74, 1, 74, 1,
74, 1, 74, 1, 74, 1, 74, 3, 74, 845, 8, 74, 1, 75, 4, 75, 848, 8, 75, 11,
75, 12, 75, 849, 1, 75, 1, 75, 1, 76, 1, 76, 3, 76, 856, 8, 76, 1, 76,
3, 76, 859, 8, 76, 1, 76, 1, 76, 0, 0, 77, 1, 1, 3, 2, 5, 3, 7, 4, 9, 5,
11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12, 25, 13, 27, 14, 29,
15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21, 43, 22, 45, 23, 47,
24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30, 61, 31, 63, 32, 65,
33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39, 79, 40, 81, 41, 83,
42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48, 97, 49, 99, 50, 101,
0, 103, 0, 105, 0, 107, 0, 109, 0, 111, 0, 113, 0, 115, 0, 117, 0, 119,
0, 121, 0, 123, 0, 125, 0, 127, 0, 129, 0, 131, 0, 133, 0, 135, 0, 137,
0, 139, 0, 141, 0, 143, 0, 145, 0, 147, 0, 149, 0, 151, 51, 153, 52, 1,
0, 16, 3, 0, 76, 76, 85, 85, 117, 117, 4, 0, 10, 10, 13, 13, 34, 34, 92,
92, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 3, 0, 65, 90, 95, 95, 97, 122,
1, 0, 48, 57, 2, 0, 66, 66, 98, 98, 1, 0, 48, 49, 2, 0, 88, 88, 120, 120,
1, 0, 49, 57, 1, 0, 48, 55, 3, 0, 48, 57, 65, 70, 97, 102, 2, 0, 69, 69,
101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 80, 80, 112, 112, 10, 0, 34, 34,
39, 39, 63, 63, 92, 92, 97, 98, 102, 102, 110, 110, 114, 114, 116, 116,
118, 118, 2, 0, 9, 9, 32, 32, 909, 0, 1, 1, 0, 0, 0, 0, 3, 1, 0, 0, 0,
0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1, 0, 0, 0,
0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19, 1, 0, 0,
0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0, 27, 1, 0,
0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0, 0, 35, 1,
0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0, 0, 0, 43,
1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0, 0, 0, 0,
51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1, 0, 0, 0,
0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65, 1, 0, 0,
0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0, 73, 1, 0,
0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0, 0, 81, 1,
0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0, 0, 0, 89,
1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0, 0, 0, 0,
97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 151, 1, 0, 0, 0, 0, 153, 1, 0, 0,
0, 1, 155, 1, 0, 0, 0, 3, 157, 1, 0, 0, 0, 5, 159, 1, 0, 0, 0, 7, 161,
1, 0, 0, 0, 9, 163, 1, 0, 0, 0, 11, 165, 1, 0, 0, 0, 13, 167, 1, 0, 0,
0, 15, 169, 1, 0, 0, 0, 17, 171, 1, 0, 0, 0, 19, 174, 1, 0, 0, 0, 21, 176,
1, 0, 0, 0, 23, 179, 1, 0, 0, 0, 25, 182, 1, 0, 0, 0, 27, 193, 1, 0, 0,
0, 29, 207, 1, 0, 0, 0, 31, 229, 1, 0, 0, 0, 33, 255, 1, 0, 0, 0, 35, 257,
1, 0, 0, 0, 37, 259, 1, 0, 0, 0, 39, 261, 1, 0, 0, 0, 41, 263, 1, 0, 0,
0, 43, 265, 1, 0, 0, 0, 45, 267, 1, 0, 0, 0, 47, 270, 1, 0, 0, 0, 49, 273,
1, 0, 0, 0, 51, 276, 1, 0, 0, 0, 53, 278, 1, 0, 0, 0, 55, 280, 1, 0, 0,
0, 57, 290, 1, 0, 0, 0, 59, 298, 1, 0, 0, 0, 61, 314, 1, 0, 0, 0, 63, 338,
1, 0, 0, 0, 65, 340, 1, 0, 0, 0, 67, 349, 1, 0, 0, 0, 69, 355, 1, 0, 0,
0, 71, 357, 1, 0, 0, 0, 73, 393, 1, 0, 0, 0, 75, 429, 1, 0, 0, 0, 77, 465,
1, 0, 0, 0, 79, 495, 1, 0, 0, 0, 81, 533, 1, 0, 0, 0, 83, 571, 1, 0, 0,
0, 85, 597, 1, 0, 0, 0, 87, 626, 1, 0, 0, 0, 89, 632, 1, 0, 0, 0, 91, 636,
1, 0, 0, 0, 93, 638, 1, 0, 0, 0, 95, 646, 1, 0, 0, 0, 97, 653, 1, 0, 0,
0, 99, 669, 1, 0, 0, 0, 101, 685, 1, 0, 0, 0, 103, 688, 1, 0, 0, 0, 105,
693, 1, 0, 0, 0, 107, 704, 1, 0, 0, 0, 109, 713, 1, 0, 0, 0, 111, 715,
1, 0, 0, 0, 113, 717, 1, 0, 0, 0, 115, 719, 1, 0, 0, 0, 117, 734, 1, 0,
0, 0, 119, 736, 1, 0, 0, 0, 121, 743, 1, 0, 0, 0, 123, 747, 1, 0, 0, 0,
125, 749, 1, 0, 0, 0, 127, 751, 1, 0, 0, 0, 129, 753, 1, 0, 0, 0, 131,
768, 1, 0, 0, 0, 133, 777, 1, 0, 0, 0, 135, 779, 1, 0, 0, 0, 137, 795,
1, 0, 0, 0, 139, 797, 1, 0, 0, 0, 141, 804, 1, 0, 0, 0, 143, 816, 1, 0,
0, 0, 145, 819, 1, 0, 0, 0, 147, 823, 1, 0, 0, 0, 149, 844, 1, 0, 0, 0,
151, 847, 1, 0, 0, 0, 153, 858, 1, 0, 0, 0, 155, 156, 5, 40, 0, 0, 156,
2, 1, 0, 0, 0, 157, 158, 5, 41, 0, 0, 158, 4, 1, 0, 0, 0, 159, 160, 5,
91, 0, 0, 160, 6, 1, 0, 0, 0, 161, 162, 5, 44, 0, 0, 162, 8, 1, 0, 0, 0,
163, 164, 5, 93, 0, 0, 164, 10, 1, 0, 0, 0, 165, 166, 5, 123, 0, 0, 166,
12, 1, 0, 0, 0, 167, 168, 5, 125, 0, 0, 168, 14, 1, 0, 0, 0, 169, 170,
5, 60, 0, 0, 170, 16, 1, 0, 0, 0, 171, 172, 5, 60, 0, 0, 172, 173, 5, 61,
0, 0, 173, 18, 1, 0, 0, 0, 174, 175, 5, 62, 0, 0, 175, 20, 1, 0, 0, 0,
176, 177, 5, 62, 0, 0, 177, 178, 5, 61, 0, 0, 178, 22, 1, 0, 0, 0, 179,
180, 5, 61, 0, 0, 180, 181, 5, 61, 0, 0, 181, 24, 1, 0, 0, 0, 182, 183,
5, 33, 0, 0, 183, 184, 5, 61, 0, 0, 184, 26, 1, 0, 0, 0, 185, 186, 5, 108,
0, 0, 186, 187, 5, 105, 0, 0, 187, 188, 5, 107, 0, 0, 188, 194, 5, 101,
0, 0, 189, 190, 5, 76, 0, 0, 190, 191, 5, 73, 0, 0, 191, 192, 5, 75, 0,
0, 192, 194, 5, 69, 0, 0, 193, 185, 1, 0, 0, 0, 193, 189, 1, 0, 0, 0, 194,
28, 1, 0, 0, 0, 195, 196, 5, 101, 0, 0, 196, 197, 5, 120, 0, 0, 197, 198,
5, 105, 0, 0, 198, 199, 5, 115, 0, 0, 199, 200, 5, 116, 0, 0, 200, 208,
5, 115, 0, 0, 201, 202, 5, 69, 0, 0, 202, 203, 5, 88, 0, 0, 203, 204, 5,
73, 0, 0, 204, 205, 5, 83, 0, 0, 205, 206, 5, 84, 0, 0, 206, 208, 5, 83,
0, 0, 207, 195, 1, 0, 0, 0, 207, 201, 1, 0, 0, 0, 208, 30, 1, 0, 0, 0,
209, 210, 5, 116, 0, 0, 210, 211, 5, 101, 0, 0, 211, 212, 5, 120, 0, 0,
212, 213, 5, 116, 0, 0, 213, 214, 5, 95, 0, 0, 214, 215, 5, 109, 0, 0,
215, 216, 5, 97, 0, 0, 216, 217, 5, 116, 0, 0, 217, 218, 5, 99, 0, 0, 218,
230, 5, 104, 0, 0, 219, 220, 5, 84, 0, 0, 220, 221, 5, 69, 0, 0, 221, 222,
5, 88, 0, 0, 222, 223, 5, 84, 0, 0, 223, 224, 5, 95, 0, 0, 224, 225, 5,
77, 0, 0, 225, 226, 5, 65, 0, 0, 226, 227, 5, 84, 0, 0, 227, 228, 5, 67,
0, 0, 228, 230, 5, 72, 0, 0, 229, 209, 1, 0, 0, 0, 229, 219, 1, 0, 0, 0,
230, 32, 1, 0, 0, 0, 231, 232, 5, 112, 0, 0, 232, 233, 5, 104, 0, 0, 233,
234, 5, 114, 0, 0, 234, 235, 5, 97, 0, 0, 235, 236, 5, 115, 0, 0, 236,
237, 5, 101, 0, 0, 237, 238, 5, 95, 0, 0, 238, 239, 5, 109, 0, 0, 239,
240, 5, 97, 0, 0, 240, 241, 5, 116, 0, 0, 241, 242, 5, 99, 0, 0, 242, 256,
5, 104, 0, 0, 243, 244, 5, 80, 0, 0, 244, 245, 5, 72, 0, 0, 245, 246, 5,
82, 0, 0, 246, 247, 5, 65, 0, 0, 247, 248, 5, 83, 0, 0, 248, 249, 5, 69,
0, 0, 249, 250, 5, 95, 0, 0, 250, 251, 5, 77, 0, 0, 251, 252, 5, 65, 0,
0, 252, 253, 5, 84, 0, 0, 253, 254, 5, 67, 0, 0, 254, 256, 5, 72, 0, 0,
255, 231, 1, 0, 0, 0, 255, 243, 1, 0, 0, 0, 256, 34, 1, 0, 0, 0, 257, 258,
5, 43, 0, 0, 258, 36, 1, 0, 0, 0, 259, 260, 5, 45, 0, 0, 260, 38, 1, 0,
0, 0, 261, 262, 5, 42, 0, 0, 262, 40, 1, 0, 0, 0, 263, 264, 5, 47, 0, 0,
264, 42, 1, 0, 0, 0, 265, 266, 5, 37, 0, 0, 266, 44, 1, 0, 0, 0, 267, 268,
5, 42, 0, 0, 268, 269, 5, 42, 0, 0, 269, 46, 1, 0, 0, 0, 270, 271, 5, 60,
0, 0, 271, 272, 5, 60, 0, 0, 272, 48, 1, 0, 0, 0, 273, 274, 5, 62, 0, 0,
274, 275, 5, 62, 0, 0, 275, 50, 1, 0, 0, 0, 276, 277, 5, 38, 0, 0, 277,
52, 1, 0, 0, 0, 278, 279, 5, 124, 0, 0, 279, 54, 1, 0, 0, 0, 280, 281,
5, 94, 0, 0, 281, 56, 1, 0, 0, 0, 282, 283, 5, 38, 0, 0, 283, 291, 5, 38,
0, 0, 284, 285, 5, 97, 0, 0, 285, 286, 5, 110, 0, 0, 286, 291, 5, 100,
0, 0, 287, 288, 5, 65, 0, 0, 288, 289, 5, 78, 0, 0, 289, 291, 5, 68, 0,
0, 290, 282, 1, 0, 0, 0, 290, 284, 1, 0, 0, 0, 290, 287, 1, 0, 0, 0, 291,
58, 1, 0, 0, 0, 292, 293, 5, 124, 0, 0, 293, 299, 5, 124, 0, 0, 294, 295,
5, 111, 0, 0, 295, 299, 5, 114, 0, 0, 296, 297, 5, 79, 0, 0, 297, 299,
5, 82, 0, 0, 298, 292, 1, 0, 0, 0, 298, 294, 1, 0, 0, 0, 298, 296, 1, 0,
0, 0, 299, 60, 1, 0, 0, 0, 300, 301, 5, 105, 0, 0, 301, 302, 5, 115, 0,
0, 302, 303, 5, 32, 0, 0, 303, 304, 5, 110, 0, 0, 304, 305, 5, 117, 0,
0, 305, 306, 5, 108, 0, 0, 306, 315, 5, 108, 0, 0, 307, 308, 5, 73, 0,
0, 308, 309, 5, 83, 0, 0, 309, 310, 5, 32, 0, 0, 310, 311, 5, 78, 0, 0,
311, 312, 5, 85, 0, 0, 312, 313, 5, 76, 0, 0, 313, 315, 5, 76, 0, 0, 314,
300, 1, 0, 0, 0, 314, 307, 1, 0, 0, 0, 315, 62, 1, 0, 0, 0, 316, 317, 5,
105, 0, 0, 317, 318, 5, 115, 0, 0, 318, 319, 5, 32, 0, 0, 319, 320, 5,
110, 0, 0, 320, 321, 5, 111, 0, 0, 321, 322, 5, 116, 0, 0, 322, 323, 5,
32, 0, 0, 323, 324, 5, 110, 0, 0, 324, 325, 5, 117, 0, 0, 325, 326, 5,
108, 0, 0, 326, 339, 5, 108, 0, 0, 327, 328, 5, 73, 0, 0, 328, 329, 5,
83, 0, 0, 329, 330, 5, 32, 0, 0, 330, 331, 5, 78, 0, 0, 331, 332, 5, 79,
0, 0, 332, 333, 5, 84, 0, 0, 333, 334, 5, 32, 0, 0, 334, 335, 5, 78, 0,
0, 335, 336, 5, 85, 0, 0, 336, 337, 5, 76, 0, 0, 337, 339, 5, 76, 0, 0,
338, 316, 1, 0, 0, 0, 338, 327, 1, 0, 0, 0, 339, 64, 1, 0, 0, 0, 340, 341,
5, 126, 0, 0, 341, 66, 1, 0, 0, 0, 342, 350, 5, 33, 0, 0, 343, 344, 5,
110, 0, 0, 344, 345, 5, 111, 0, 0, 345, 350, 5, 116, 0, 0, 346, 347, 5,
78, 0, 0, 347, 348, 5, 79, 0, 0, 348, 350, 5, 84, 0, 0, 349, 342, 1, 0,
0, 0, 349, 343, 1, 0, 0, 0, 349, 346, 1, 0, 0, 0, 350, 68, 1, 0, 0, 0,
351, 352, 5, 105, 0, 0, 352, 356, 5, 110, 0, 0, 353, 354, 5, 73, 0, 0,
354, 356, 5, 78, 0, 0, 355, 351, 1, 0, 0, 0, 355, 353, 1, 0, 0, 0, 356,
70, 1, 0, 0, 0, 357, 362, 5, 91, 0, 0, 358, 361, 3, 151, 75, 0, 359, 361,
3, 153, 76, 0, 360, 358, 1, 0, 0, 0, 360, 359, 1, 0, 0, 0, 361, 364, 1,
0, 0, 0, 362, 360, 1, 0, 0, 0, 362, 363, 1, 0, 0, 0, 363, 365, 1, 0, 0,
0, 364, 362, 1, 0, 0, 0, 365, 366, 5, 93, 0, 0, 366, 72, 1, 0, 0, 0, 367,
368, 5, 106, 0, 0, 368, 369, 5, 115, 0, 0, 369, 370, 5, 111, 0, 0, 370,
371, 5, 110, 0, 0, 371, 372, 5, 95, 0, 0, 372, 373, 5, 99, 0, 0, 373, 374,
5, 111, 0, 0, 374, 375, 5, 110, 0, 0, 375, 376, 5, 116, 0, 0, 376, 377,
5, 97, 0, 0, 377, 378, 5, 105, 0, 0, 378, 379, 5, 110, 0, 0, 379, 394,
5, 115, 0, 0, 380, 381, 5, 74, 0, 0, 381, 382, 5, 83, 0, 0, 382, 383, 5,
79, 0, 0, 383, 384, 5, 78, 0, 0, 384, 385, 5, 95, 0, 0, 385, 386, 5, 67,
0, 0, 386, 387, 5, 79, 0, 0, 387, 388, 5, 78, 0, 0, 388, 389, 5, 84, 0,
0, 389, 390, 5, 65, 0, 0, 390, 391, 5, 73, 0, 0, 391, 392, 5, 78, 0, 0,
392, 394, 5, 83, 0, 0, 393, 367, 1, 0, 0, 0, 393, 380, 1, 0, 0, 0, 394,
74, 1, 0, 0, 0, 395, 396, 5, 106, 0, 0, 396, 397, 5, 115, 0, 0, 397, 398,
5, 111, 0, 0, 398, 399, 5, 110, 0, 0, 399, 400, 5, 95, 0, 0, 400, 401,
5, 99, 0, 0, 401, 402, 5, 111, 0, 0, 402, 403, 5, 110, 0, 0, 403, 404,
5, 116, 0, 0, 404, 405, 5, 97, 0, 0, 405, 406, 5, 105, 0, 0, 406, 407,
5, 110, 0, 0, 407, 408, 5, 115, 0, 0, 408, 409, 5, 95, 0, 0, 409, 410,
5, 97, 0, 0, 410, 411, 5, 108, 0, 0, 411, 430, 5, 108, 0, 0, 412, 413,
5, 74, 0, 0, 413, 414, 5, 83, 0, 0, 414, 415, 5, 79, 0, 0, 415, 416, 5,
78, 0, 0, 416, 417, 5, 95, 0, 0, 417, 418, 5, 67, 0, 0, 418, 419, 5, 79,
0, 0, 419, 420, 5, 78, 0, 0, 420, 421, 5, 84, 0, 0, 421, 422, 5, 65, 0,
0, 422, 423, 5, 73, 0, 0, 423, 424, 5, 78, 0, 0, 424, 425, 5, 83, 0, 0,
425, 426, 5, 95, 0, 0, 426, 427, 5, 65, 0, 0, 427, 428, 5, 76, 0, 0, 428,
430, 5, 76, 0, 0, 429, 395, 1, 0, 0, 0, 429, 412, 1, 0, 0, 0, 430, 76,
1, 0, 0, 0, 431, 432, 5, 106, 0, 0, 432, 433, 5, 115, 0, 0, 433, 434, 5,
111, 0, 0, 434, 435, 5, 110, 0, 0, 435, 436, 5, 95, 0, 0, 436, 437, 5,
99, 0, 0, 437, 438, 5, 111, 0, 0, 438, 439, 5, 110, 0, 0, 439, 440, 5,
116, 0, 0, 440, 441, 5, 97, 0, 0, 441, 442, 5, 105, 0, 0, 442, 443, 5,
110, 0, 0, 443, 444, 5, 115, 0, 0, 444, 445, 5, 95, 0, 0, 445, 446, 5,
97, 0, 0, 446, 447, 5, 110, 0, 0, 447, 466, 5, 121, 0, 0, 448, 449, 5,
74, 0, 0, 449, 450, 5, 83, 0, 0, 450, 451, 5, 79, 0, 0, 451, 452, 5, 78,
0, 0, 452, 453, 5, 95, 0, 0, 453, 454, 5, 67, 0, 0, 454, 455, 5, 79, 0,
0, 455, 456, 5, 78, 0, 0, 456, 457, 5, 84, 0, 0, 457, 458, 5, 65, 0, 0,
458, 459, 5, 73, 0, 0, 459, 460, 5, 78, 0, 0, 460, 461, 5, 83, 0, 0, 461,
462, 5, 95, 0, 0, 462, 463, 5, 65, 0, 0, 463, 464, 5, 78, 0, 0, 464, 466,
5, 89, 0, 0, 465, 431, 1, 0, 0, 0, 465, 448, 1, 0, 0, 0, 466, 78, 1, 0,
0, 0, 467, 468, 5, 97, 0, 0, 468, 469, 5, 114, 0, 0, 469, 470, 5, 114,
0, 0, 470, 471, 5, 97, 0, 0, 471, 472, 5, 121, 0, 0, 472, 473, 5, 95, 0,
0, 473, 474, 5, 99, 0, 0, 474, 475, 5, 111, 0, 0, 475, 476, 5, 110, 0,
0, 476, 477, 5, 116, 0, 0, 477, 478, 5, 97, 0, 0, 478, 479, 5, 105, 0,
0, 479, 480, 5, 110, 0, 0, 480, 496, 5, 115, 0, 0, 481, 482, 5, 65, 0,
0, 482, 483, 5, 82, 0, 0, 483, 484, 5, 82, 0, 0, 484, 485, 5, 65, 0, 0,
485, 486, 5, 89, 0, 0, 486, 487, 5, 95, 0, 0, 487, 488, 5, 67, 0, 0, 488,
489, 5, 79, 0, 0, 489, 490, 5, 78, 0, 0, 490, 491, 5, 84, 0, 0, 491, 492,
5, 65, 0, 0, 492, 493, 5, 73, 0, 0, 493, 494, 5, 78, 0, 0, 494, 496, 5,
83, 0, 0, 495, 467, 1, 0, 0, 0, 495, 481, 1, 0, 0, 0, 496, 80, 1, 0, 0,
0, 497, 498, 5, 97, 0, 0, 498, 499, 5, 114, 0, 0, 499, 500, 5, 114, 0,
0, 500, 501, 5, 97, 0, 0, 501, 502, 5, 121, 0, 0, 502, 503, 5, 95, 0, 0,
503, 504, 5, 99, 0, 0, 504, 505, 5, 111, 0, 0, 505, 506, 5, 110, 0, 0,
506, 507, 5, 116, 0, 0, 507, 508, 5, 97, 0, 0, 508, 509, 5, 105, 0, 0,
509, 510, 5, 110, 0, 0, 510, 511, 5, 115, 0, 0, 511, 512, 5, 95, 0, 0,
512, 513, 5, 97, 0, 0, 513, 514, 5, 108, 0, 0, 514, 534, 5, 108, 0, 0,
515, 516, 5, 65, 0, 0, 516, 517, 5, 82, 0, 0, 517, 518, 5, 82, 0, 0, 518,
519, 5, 65, 0, 0, 519, 520, 5, 89, 0, 0, 520, 521, 5, 95, 0, 0, 521, 522,
5, 67, 0, 0, 522, 523, 5, 79, 0, 0, 523, 524, 5, 78, 0, 0, 524, 525, 5,
84, 0, 0, 525, 526, 5, 65, 0, 0, 526, 527, 5, 73, 0, 0, 527, 528, 5, 78,
0, 0, 528, 529, 5, 83, 0, 0, 529, 530, 5, 95, 0, 0, 530, 531, 5, 65, 0,
0, 531, 532, 5, 76, 0, 0, 532, 534, 5, 76, 0, 0, 533, 497, 1, 0, 0, 0,
533, 515, 1, 0, 0, 0, 534, 82, 1, 0, 0, 0, 535, 536, 5, 97, 0, 0, 536,
537, 5, 114, 0, 0, 537, 538, 5, 114, 0, 0, 538, 539, 5, 97, 0, 0, 539,
540, 5, 121, 0, 0, 540, 541, 5, 95, 0, 0, 541, 542, 5, 99, 0, 0, 542, 543,
5, 111, 0, 0, 543, 544, 5, 110, 0, 0, 544, 545, 5, 116, 0, 0, 545, 546,
5, 97, 0, 0, 546, 547, 5, 105, 0, 0, 547, 548, 5, 110, 0, 0, 548, 549,
5, 115, 0, 0, 549, 550, 5, 95, 0, 0, 550, 551, 5, 97, 0, 0, 551, 552, 5,
110, 0, 0, 552, 572, 5, 121, 0, 0, 553, 554, 5, 65, 0, 0, 554, 555, 5,
82, 0, 0, 555, 556, 5, 82, 0, 0, 556, 557, 5, 65, 0, 0, 557, 558, 5, 89,
0, 0, 558, 559, 5, 95, 0, 0, 559, 560, 5, 67, 0, 0, 560, 561, 5, 79, 0,
0, 561, 562, 5, 78, 0, 0, 562, 563, 5, 84, 0, 0, 563, 564, 5, 65, 0, 0,
564, 565, 5, 73, 0, 0, 565, 566, 5, 78, 0, 0, 566, 567, 5, 83, 0, 0, 567,
568, 5, 95, 0, 0, 568, 569, 5, 65, 0, 0, 569, 570, 5, 78, 0, 0, 570, 572,
5, 89, 0, 0, 571, 535, 1, 0, 0, 0, 571, 553, 1, 0, 0, 0, 572, 84, 1, 0,
0, 0, 573, 574, 5, 97, 0, 0, 574, 575, 5, 114, 0, 0, 575, 576, 5, 114,
0, 0, 576, 577, 5, 97, 0, 0, 577, 578, 5, 121, 0, 0, 578, 579, 5, 95, 0,
0, 579, 580, 5, 108, 0, 0, 580, 581, 5, 101, 0, 0, 581, 582, 5, 110, 0,
0, 582, 583, 5, 103, 0, 0, 583, 584, 5, 116, 0, 0, 584, 598, 5, 104, 0,
0, 585, 586, 5, 65, 0, 0, 586, 587, 5, 82, 0, 0, 587, 588, 5, 82, 0, 0,
588, 589, 5, 65, 0, 0, 589, 590, 5, 89, 0, 0, 590, 591, 5, 95, 0, 0, 591,
592, 5, 76, 0, 0, 592, 593, 5, 69, 0, 0, 593, 594, 5, 78, 0, 0, 594, 595,
5, 71, 0, 0, 595, 596, 5, 84, 0, 0, 596, 598, 5, 72, 0, 0, 597, 573, 1,
0, 0, 0, 597, 585, 1, 0, 0, 0, 598, 86, 1, 0, 0, 0, 599, 600, 5, 116, 0,
0, 600, 601, 5, 114, 0, 0, 601, 602, 5, 117, 0, 0, 602, 627, 5, 101, 0,
0, 603, 604, 5, 84, 0, 0, 604, 605, 5, 114, 0, 0, 605, 606, 5, 117, 0,
0, 606, 627, 5, 101, 0, 0, 607, 608, 5, 84, 0, 0, 608, 609, 5, 82, 0, 0,
609, 610, 5, 85, 0, 0, 610, 627, 5, 69, 0, 0, 611, 612, 5, 102, 0, 0, 612,
613, 5, 97, 0, 0, 613, 614, 5, 108, 0, 0, 614, 615, 5, 115, 0, 0, 615,
627, 5, 101, 0, 0, 616, 617, 5, 70, 0, 0, 617, 618, 5, 97, 0, 0, 618, 619,
5, 108, 0, 0, 619, 620, 5, 115, 0, 0, 620, 627, 5, 101, 0, 0, 621, 622,
5, 70, 0, 0, 622, 623, 5, 65, 0, 0, 623, 624, 5, 76, 0, 0, 624, 625, 5,
83, 0, 0, 625, 627, 5, 69, 0, 0, 626, 599, 1, 0, 0, 0, 626, 603, 1, 0,
0, 0, 626, 607, 1, 0, 0, 0, 626, 611, 1, 0, 0, 0, 626, 616, 1, 0, 0, 0,
626, 621, 1, 0, 0, 0, 627, 88, 1, 0, 0, 0, 628, 633, 3, 117, 58, 0, 629,
633, 3, 119, 59, 0, 630, 633, 3, 121, 60, 0, 631, 633, 3, 115, 57, 0, 632,
628, 1, 0, 0, 0, 632, 629, 1, 0, 0, 0, 632, 630, 1, 0, 0, 0, 632, 631,
1, 0, 0, 0, 633, 90, 1, 0, 0, 0, 634, 637, 3, 133, 66, 0, 635, 637, 3,
135, 67, 0, 636, 634, 1, 0, 0, 0, 636, 635, 1, 0, 0, 0, 637, 92, 1, 0,
0, 0, 638, 643, 3, 111, 55, 0, 639, 642, 3, 111, 55, 0, 640, 642, 3, 113,
56, 0, 641, 639, 1, 0, 0, 0, 641, 640, 1, 0, 0, 0, 642, 645, 1, 0, 0, 0,
643, 641, 1, 0, 0, 0, 643, 644, 1, 0, 0, 0, 644, 94, 1, 0, 0, 0, 645, 643,
1, 0, 0, 0, 646, 647, 5, 36, 0, 0, 647, 648, 5, 109, 0, 0, 648, 649, 5,
101, 0, 0, 649, 650, 5, 116, 0, 0, 650, 651, 5, 97, 0, 0, 651, 96, 1, 0,
0, 0, 652, 654, 3, 101, 50, 0, 653, 652, 1, 0, 0, 0, 653, 654, 1, 0, 0,
0, 654, 665, 1, 0, 0, 0, 655, 657, 5, 34, 0, 0, 656, 658, 3, 103, 51, 0,
657, 656, 1, 0, 0, 0, 657, 658, 1, 0, 0, 0, 658, 659, 1, 0, 0, 0, 659,
666, 5, 34, 0, 0, 660, 662, 5, 39, 0, 0, 661, 663, 3, 105, 52, 0, 662,
661, 1, 0, 0, 0, 662, 663, 1, 0, 0, 0, 663, 664, 1, 0, 0, 0, 664, 666,
5, 39, 0, 0, 665, 655, 1, 0, 0, 0, 665, 660, 1, 0, 0, 0, 666, 98, 1, 0,
0, 0, 667, 670, 3, 93, 46, 0, 668, 670, 3, 95, 47, 0, 669, 667, 1, 0, 0,
0, 669, 668, 1, 0, 0, 0, 670, 678, 1, 0, 0, 0, 671, 674, 5, 91, 0, 0, 672,
675, 3, 97, 48, 0, 673, 675, 3, 117, 58, 0, 674, 672, 1, 0, 0, 0, 674,
673, 1, 0, 0, 0, 675, 676, 1, 0, 0, 0, 676, 677, 5, 93, 0, 0, 677, 679,
1, 0, 0, 0, 678, 671, 1, 0, 0, 0, 679, 680, 1, 0, 0, 0, 680, 678, 1, 0,
0, 0, 680, 681, 1, 0, 0, 0, 681, 100, 1, 0, 0, 0, 682, 683, 5, 117, 0,
0, 683, 686, 5, 56, 0, 0, 684, 686, 7, 0, 0, 0, 685, 682, 1, 0, 0, 0, 685,
684, 1, 0, 0, 0, 686, 102, 1, 0, 0, 0, 687, 689, 3, 107, 53, 0, 688, 687,
1, 0, 0, 0, 689, 690, 1, 0, 0, 0, 690, 688, 1, 0, 0, 0, 690, 691, 1, 0,
0, 0, 691, 104, 1, 0, 0, 0, 692, 694, 3, 109, 54, 0, 693, 692, 1, 0, 0,
0, 694, 695, 1, 0, 0, 0, 695, 693, 1, 0, 0, 0, 695, 696, 1, 0, 0, 0, 696,
106, 1, 0, 0, 0, 697, 705, 8, 1, 0, 0, 698, 705, 3, 149, 74, 0, 699, 700,
5, 92, 0, 0, 700, 705, 5, 10, 0, 0, 701, 702, 5, 92, 0, 0, 702, 703, 5,
13, 0, 0, 703, 705, 5, 10, 0, 0, 704, 697, 1, 0, 0, 0, 704, 698, 1, 0,
0, 0, 704, 699, 1, 0, 0, 0, 704, 701, 1, 0, 0, 0, 705, 108, 1, 0, 0, 0,
706, 714, 8, 2, 0, 0, 707, 714, 3, 149, 74, 0, 708, 709, 5, 92, 0, 0, 709,
714, 5, 10, 0, 0, 710, 711, 5, 92, 0, 0, 711, 712, 5, 13, 0, 0, 712, 714,
5, 10, 0, 0, 713, 706, 1, 0, 0, 0, 713, 707, 1, 0, 0, 0, 713, 708, 1, 0,
0, 0, 713, 710, 1, 0, 0, 0, 714, 110, 1, 0, 0, 0, 715, 716, 7, 3, 0, 0,
716, 112, 1, 0, 0, 0, 717, 718, 7, 4, 0, 0, 718, 114, 1, 0, 0, 0, 719,
720, 5, 48, 0, 0, 720, 722, 7, 5, 0, 0, 721, 723, 7, 6, 0, 0, 722, 721,
1, 0, 0, 0, 723, 724, 1, 0, 0, 0, 724, 722, 1, 0, 0, 0, 724, 725, 1, 0,
0, 0, 725, 116, 1, 0, 0, 0, 726, 730, 3, 123, 61, 0, 727, 729, 3, 113,
56, 0, 728, 727, 1, 0, 0, 0, 729, 732, 1, 0, 0, 0, 730, 728, 1, 0, 0, 0,
730, 731, 1, 0, 0, 0, 731, 735, 1, 0, 0, 0, 732, 730, 1, 0, 0, 0, 733,
735, 5, 48, 0, 0, 734, 726, 1, 0, 0, 0, 734, 733, 1, 0, 0, 0, 735, 118,
1, 0, 0, 0, 736, 740, 5, 48, 0, 0, 737, 739, 3, 125, 62, 0, 738, 737, 1,
0, 0, 0, 739, 742, 1, 0, 0, 0, 740, 738, 1, 0, 0, 0, 740, 741, 1, 0, 0,
0, 741, 120, 1, 0, 0, 0, 742, 740, 1, 0, 0, 0, 743, 744, 5, 48, 0, 0, 744,
745, 7, 7, 0, 0, 745, 746, 3, 145, 72, 0, 746, 122, 1, 0, 0, 0, 747, 748,
7, 8, 0, 0, 748, 124, 1, 0, 0, 0, 749, 750, 7, 9, 0, 0, 750, 126, 1, 0,
0, 0, 751, 752, 7, 10, 0, 0, 752, 128, 1, 0, 0, 0, 753, 754, 3, 127, 63,
0, 754, 755, 3, 127, 63, 0, 755, 756, 3, 127, 63, 0, 756, 757, 3, 127,
63, 0, 757, 130, 1, 0, 0, 0, 758, 759, 5, 92, 0, 0, 759, 760, 5, 117, 0,
0, 760, 761, 1, 0, 0, 0, 761, 769, 3, 129, 64, 0, 762, 763, 5, 92, 0, 0,
763, 764, 5, 85, 0, 0, 764, 765, 1, 0, 0, 0, 765, 766, 3, 129, 64, 0, 766,
767, 3, 129, 64, 0, 767, 769, 1, 0, 0, 0, 768, 758, 1, 0, 0, 0, 768, 762,
1, 0, 0, 0, 769, 132, 1, 0, 0, 0, 770, 772, 3, 137, 68, 0, 771, 773, 3,
139, 69, 0, 772, 771, 1, 0, 0, 0, 772, 773, 1, 0, 0, 0, 773, 778, 1, 0,
0, 0, 774, 775, 3, 141, 70, 0, 775, 776, 3, 139, 69, 0, 776, 778, 1, 0,
0, 0, 777, 770, 1, 0, 0, 0, 777, 774, 1, 0, 0, 0, 778, 134, 1, 0, 0, 0,
779, 780, 5, 48, 0, 0, 780, 783, 7, 7, 0, 0, 781, 784, 3, 143, 71, 0, 782,
784, 3, 145, 72, 0, 783, 781, 1, 0, 0, 0, 783, 782, 1, 0, 0, 0, 784, 785,
1, 0, 0, 0, 785, 786, 3, 147, 73, 0, 786, 136, 1, 0, 0, 0, 787, 789, 3,
141, 70, 0, 788, 787, 1, 0, 0, 0, 788, 789, 1, 0, 0, 0, 789, 790, 1, 0,
0, 0, 790, 791, 5, 46, 0, 0, 791, 796, 3, 141, 70, 0, 792, 793, 3, 141,
70, 0, 793, 794, 5, 46, 0, 0, 794, 796, 1, 0, 0, 0, 795, 788, 1, 0, 0,
0, 795, 792, 1, 0, 0, 0, 796, 138, 1, 0, 0, 0, 797, 799, 7, 11, 0, 0, 798,
800, 7, 12, 0, 0, 799, 798, 1, 0, 0, 0, 799, 800, 1, 0, 0, 0, 800, 801,
1, 0, 0, 0, 801, 802, 3, 141, 70, 0, 802, 140, 1, 0, 0, 0, 803, 805, 3,
113, 56, 0, 804, 803, 1, 0, 0, 0, 805, 806, 1, 0, 0, 0, 806, 804, 1, 0,
0, 0, 806, 807, 1, 0, 0, 0, 807, 142, 1, 0, 0, 0, 808, 810, 3, 145, 72,
0, 809, 808, 1, 0, 0, 0, 809, 810, 1, 0, 0, 0, 810, 811, 1, 0, 0, 0, 811,
812, 5, 46, 0, 0, 812, 817, 3, 145, 72, 0, 813, 814, 3, 145, 72, 0, 814,
815, 5, 46, 0, 0, 815, 817, 1, 0, 0, 0, 816, 809, 1, 0, 0, 0, 816, 813,
1, 0, 0, 0, 817, 144, 1, 0, 0, 0, 818, 820, 3, 127, 63, 0, 819, 818, 1,
0, 0, 0, 820, 821, 1, 0, 0, 0, 821, 819, 1, 0, 0, 0, 821, 822, 1, 0, 0,
0, 822, 146, 1, 0, 0, 0, 823, 825, 7, 13, 0, 0, 824, 826, 7, 12, 0, 0,
825, 824, 1, 0, 0, 0, 825, 826, 1, 0, 0, 0, 826, 827, 1, 0, 0, 0, 827,
828, 3, 141, 70, 0, 828, 148, 1, 0, 0, 0, 829, 830, 5, 92, 0, 0, 830, 845,
7, 14, 0, 0, 831, 832, 5, 92, 0, 0, 832, 834, 3, 125, 62, 0, 833, 835,
3, 125, 62, 0, 834, 833, 1, 0, 0, 0, 834, 835, 1, 0, 0, 0, 835, 837, 1,
0, 0, 0, 836, 838, 3, 125, 62, 0, 837, 836, 1, 0, 0, 0, 837, 838, 1, 0,
0, 0, 838, 845, 1, 0, 0, 0, 839, 840, 5, 92, 0, 0, 840, 841, 5, 120, 0,
0, 841, 842, 1, 0, 0, 0, 842, 845, 3, 145, 72, 0, 843, 845, 3, 131, 65,
0, 844, 829, 1, 0, 0, 0, 844, 831, 1, 0, 0, 0, 844, 839, 1, 0, 0, 0, 844,
843, 1, 0, 0, 0, 845, 150, 1, 0, 0, 0, 846, 848, 7, 15, 0, 0, 847, 846,
1, 0, 0, 0, 848, 849, 1, 0, 0, 0, 849, 847, 1, 0, 0, 0, 849, 850, 1, 0,
0, 0, 850, 851, 1, 0, 0, 0, 851, 852, 6, 75, 0, 0, 852, 152, 1, 0, 0, 0,
853, 855, 5, 13, 0, 0, 854, 856, 5, 10, 0, 0, 855, 854, 1, 0, 0, 0, 855,
856, 1, 0, 0, 0, 856, 859, 1, 0, 0, 0, 857, 859, 5, 10, 0, 0, 858, 853,
1, 0, 0, 0, 858, 857, 1, 0, 0, 0, 859, 860, 1, 0, 0, 0, 860, 861, 6, 76,
0, 0, 861, 154, 1, 0, 0, 0, 59, 0, 193, 207, 229, 255, 290, 298, 314, 338,
349, 355, 360, 362, 393, 429, 465, 495, 533, 571, 597, 626, 632, 636, 641,
643, 653, 657, 662, 665, 669, 674, 680, 685, 690, 695, 704, 713, 724, 730,
734, 740, 768, 772, 777, 783, 788, 795, 799, 806, 809, 816, 821, 825, 834,
837, 844, 849, 855, 858, 1, 6, 0, 0,
1, 43, 1, 43, 1, 43, 1, 43, 1, 43, 3, 43, 632, 8, 43, 1, 44, 1, 44, 1,
44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44,
1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 1, 44, 3, 44, 654, 8, 44, 1,
45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45,
1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1, 45, 1,
45, 3, 45, 678, 8, 45, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46,
1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1, 46, 1,
46, 1, 46, 1, 46, 3, 46, 700, 8, 46, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47,
1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1,
47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 1, 47, 3, 47, 724, 8, 47, 1, 48,
1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1,
48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48, 1, 48,
1, 48, 1, 48, 1, 48, 1, 48, 3, 48, 752, 8, 48, 1, 49, 1, 49, 1, 49, 1,
49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49,
1, 49, 1, 49, 1, 49, 1, 49, 3, 49, 772, 8, 49, 1, 50, 1, 50, 1, 50, 1,
50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50,
1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1, 50, 1,
50, 1, 50, 1, 50, 3, 50, 801, 8, 50, 1, 51, 1, 51, 1, 51, 1, 51, 3, 51,
807, 8, 51, 1, 52, 1, 52, 3, 52, 811, 8, 52, 1, 53, 1, 53, 1, 53, 5, 53,
816, 8, 53, 10, 53, 12, 53, 819, 9, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1,
54, 1, 54, 1, 55, 3, 55, 828, 8, 55, 1, 55, 1, 55, 3, 55, 832, 8, 55, 1,
55, 1, 55, 1, 55, 3, 55, 837, 8, 55, 1, 55, 3, 55, 840, 8, 55, 1, 56, 1,
56, 3, 56, 844, 8, 56, 1, 56, 1, 56, 1, 56, 3, 56, 849, 8, 56, 1, 56, 1,
56, 4, 56, 853, 8, 56, 11, 56, 12, 56, 854, 1, 57, 1, 57, 1, 57, 3, 57,
860, 8, 57, 1, 58, 4, 58, 863, 8, 58, 11, 58, 12, 58, 864, 1, 59, 4, 59,
868, 8, 59, 11, 59, 12, 59, 869, 1, 60, 1, 60, 1, 60, 1, 60, 1, 60, 1,
60, 1, 60, 3, 60, 879, 8, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61, 1, 61,
1, 61, 3, 61, 888, 8, 61, 1, 62, 1, 62, 1, 63, 1, 63, 1, 64, 1, 64, 1,
64, 4, 64, 897, 8, 64, 11, 64, 12, 64, 898, 1, 65, 1, 65, 5, 65, 903, 8,
65, 10, 65, 12, 65, 906, 9, 65, 1, 65, 3, 65, 909, 8, 65, 1, 66, 1, 66,
5, 66, 913, 8, 66, 10, 66, 12, 66, 916, 9, 66, 1, 67, 1, 67, 1, 67, 1,
67, 1, 68, 1, 68, 1, 69, 1, 69, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71,
1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1,
72, 3, 72, 943, 8, 72, 1, 73, 1, 73, 3, 73, 947, 8, 73, 1, 73, 1, 73, 1,
73, 3, 73, 952, 8, 73, 1, 74, 1, 74, 1, 74, 1, 74, 3, 74, 958, 8, 74, 1,
74, 1, 74, 1, 75, 3, 75, 963, 8, 75, 1, 75, 1, 75, 1, 75, 1, 75, 1, 75,
3, 75, 970, 8, 75, 1, 76, 1, 76, 3, 76, 974, 8, 76, 1, 76, 1, 76, 1, 77,
4, 77, 979, 8, 77, 11, 77, 12, 77, 980, 1, 78, 3, 78, 984, 8, 78, 1, 78,
1, 78, 1, 78, 1, 78, 1, 78, 3, 78, 991, 8, 78, 1, 79, 4, 79, 994, 8, 79,
11, 79, 12, 79, 995, 1, 80, 1, 80, 3, 80, 1000, 8, 80, 1, 80, 1, 80, 1,
81, 1, 81, 1, 81, 1, 81, 1, 81, 3, 81, 1009, 8, 81, 1, 81, 3, 81, 1012,
8, 81, 1, 81, 1, 81, 1, 81, 1, 81, 1, 81, 3, 81, 1019, 8, 81, 1, 82, 4,
82, 1022, 8, 82, 11, 82, 12, 82, 1023, 1, 82, 1, 82, 1, 83, 1, 83, 3, 83,
1030, 8, 83, 1, 83, 3, 83, 1033, 8, 83, 1, 83, 1, 83, 0, 0, 84, 1, 1, 3,
2, 5, 3, 7, 4, 9, 5, 11, 6, 13, 7, 15, 8, 17, 9, 19, 10, 21, 11, 23, 12,
25, 13, 27, 14, 29, 15, 31, 16, 33, 17, 35, 18, 37, 19, 39, 20, 41, 21,
43, 22, 45, 23, 47, 24, 49, 25, 51, 26, 53, 27, 55, 28, 57, 29, 59, 30,
61, 31, 63, 32, 65, 33, 67, 34, 69, 35, 71, 36, 73, 37, 75, 38, 77, 39,
79, 40, 81, 41, 83, 42, 85, 43, 87, 44, 89, 45, 91, 46, 93, 47, 95, 48,
97, 49, 99, 50, 101, 51, 103, 52, 105, 53, 107, 54, 109, 55, 111, 56, 113,
57, 115, 0, 117, 0, 119, 0, 121, 0, 123, 0, 125, 0, 127, 0, 129, 0, 131,
0, 133, 0, 135, 0, 137, 0, 139, 0, 141, 0, 143, 0, 145, 0, 147, 0, 149,
0, 151, 0, 153, 0, 155, 0, 157, 0, 159, 0, 161, 0, 163, 0, 165, 58, 167,
59, 1, 0, 16, 3, 0, 76, 76, 85, 85, 117, 117, 4, 0, 10, 10, 13, 13, 34,
34, 92, 92, 4, 0, 10, 10, 13, 13, 39, 39, 92, 92, 3, 0, 65, 90, 95, 95,
97, 122, 1, 0, 48, 57, 2, 0, 66, 66, 98, 98, 1, 0, 48, 49, 2, 0, 88, 88,
120, 120, 1, 0, 49, 57, 1, 0, 48, 55, 3, 0, 48, 57, 65, 70, 97, 102, 2,
0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 80, 80, 112, 112, 10,
0, 34, 34, 39, 39, 63, 63, 92, 92, 97, 98, 102, 102, 110, 110, 114, 114,
116, 116, 118, 118, 2, 0, 9, 9, 32, 32, 1090, 0, 1, 1, 0, 0, 0, 0, 3, 1,
0, 0, 0, 0, 5, 1, 0, 0, 0, 0, 7, 1, 0, 0, 0, 0, 9, 1, 0, 0, 0, 0, 11, 1,
0, 0, 0, 0, 13, 1, 0, 0, 0, 0, 15, 1, 0, 0, 0, 0, 17, 1, 0, 0, 0, 0, 19,
1, 0, 0, 0, 0, 21, 1, 0, 0, 0, 0, 23, 1, 0, 0, 0, 0, 25, 1, 0, 0, 0, 0,
27, 1, 0, 0, 0, 0, 29, 1, 0, 0, 0, 0, 31, 1, 0, 0, 0, 0, 33, 1, 0, 0, 0,
0, 35, 1, 0, 0, 0, 0, 37, 1, 0, 0, 0, 0, 39, 1, 0, 0, 0, 0, 41, 1, 0, 0,
0, 0, 43, 1, 0, 0, 0, 0, 45, 1, 0, 0, 0, 0, 47, 1, 0, 0, 0, 0, 49, 1, 0,
0, 0, 0, 51, 1, 0, 0, 0, 0, 53, 1, 0, 0, 0, 0, 55, 1, 0, 0, 0, 0, 57, 1,
0, 0, 0, 0, 59, 1, 0, 0, 0, 0, 61, 1, 0, 0, 0, 0, 63, 1, 0, 0, 0, 0, 65,
1, 0, 0, 0, 0, 67, 1, 0, 0, 0, 0, 69, 1, 0, 0, 0, 0, 71, 1, 0, 0, 0, 0,
73, 1, 0, 0, 0, 0, 75, 1, 0, 0, 0, 0, 77, 1, 0, 0, 0, 0, 79, 1, 0, 0, 0,
0, 81, 1, 0, 0, 0, 0, 83, 1, 0, 0, 0, 0, 85, 1, 0, 0, 0, 0, 87, 1, 0, 0,
0, 0, 89, 1, 0, 0, 0, 0, 91, 1, 0, 0, 0, 0, 93, 1, 0, 0, 0, 0, 95, 1, 0,
0, 0, 0, 97, 1, 0, 0, 0, 0, 99, 1, 0, 0, 0, 0, 101, 1, 0, 0, 0, 0, 103,
1, 0, 0, 0, 0, 105, 1, 0, 0, 0, 0, 107, 1, 0, 0, 0, 0, 109, 1, 0, 0, 0,
0, 111, 1, 0, 0, 0, 0, 113, 1, 0, 0, 0, 0, 165, 1, 0, 0, 0, 0, 167, 1,
0, 0, 0, 1, 169, 1, 0, 0, 0, 3, 171, 1, 0, 0, 0, 5, 173, 1, 0, 0, 0, 7,
175, 1, 0, 0, 0, 9, 177, 1, 0, 0, 0, 11, 179, 1, 0, 0, 0, 13, 181, 1, 0,
0, 0, 15, 183, 1, 0, 0, 0, 17, 185, 1, 0, 0, 0, 19, 188, 1, 0, 0, 0, 21,
190, 1, 0, 0, 0, 23, 193, 1, 0, 0, 0, 25, 196, 1, 0, 0, 0, 27, 207, 1,
0, 0, 0, 29, 221, 1, 0, 0, 0, 31, 243, 1, 0, 0, 0, 33, 269, 1, 0, 0, 0,
35, 271, 1, 0, 0, 0, 37, 273, 1, 0, 0, 0, 39, 275, 1, 0, 0, 0, 41, 277,
1, 0, 0, 0, 43, 279, 1, 0, 0, 0, 45, 281, 1, 0, 0, 0, 47, 284, 1, 0, 0,
0, 49, 287, 1, 0, 0, 0, 51, 290, 1, 0, 0, 0, 53, 292, 1, 0, 0, 0, 55, 294,
1, 0, 0, 0, 57, 304, 1, 0, 0, 0, 59, 312, 1, 0, 0, 0, 61, 328, 1, 0, 0,
0, 63, 352, 1, 0, 0, 0, 65, 354, 1, 0, 0, 0, 67, 363, 1, 0, 0, 0, 69, 369,
1, 0, 0, 0, 71, 371, 1, 0, 0, 0, 73, 407, 1, 0, 0, 0, 75, 443, 1, 0, 0,
0, 77, 479, 1, 0, 0, 0, 79, 509, 1, 0, 0, 0, 81, 547, 1, 0, 0, 0, 83, 585,
1, 0, 0, 0, 85, 611, 1, 0, 0, 0, 87, 631, 1, 0, 0, 0, 89, 653, 1, 0, 0,
0, 91, 677, 1, 0, 0, 0, 93, 699, 1, 0, 0, 0, 95, 723, 1, 0, 0, 0, 97, 751,
1, 0, 0, 0, 99, 771, 1, 0, 0, 0, 101, 800, 1, 0, 0, 0, 103, 806, 1, 0,
0, 0, 105, 810, 1, 0, 0, 0, 107, 812, 1, 0, 0, 0, 109, 820, 1, 0, 0, 0,
111, 827, 1, 0, 0, 0, 113, 843, 1, 0, 0, 0, 115, 859, 1, 0, 0, 0, 117,
862, 1, 0, 0, 0, 119, 867, 1, 0, 0, 0, 121, 878, 1, 0, 0, 0, 123, 887,
1, 0, 0, 0, 125, 889, 1, 0, 0, 0, 127, 891, 1, 0, 0, 0, 129, 893, 1, 0,
0, 0, 131, 908, 1, 0, 0, 0, 133, 910, 1, 0, 0, 0, 135, 917, 1, 0, 0, 0,
137, 921, 1, 0, 0, 0, 139, 923, 1, 0, 0, 0, 141, 925, 1, 0, 0, 0, 143,
927, 1, 0, 0, 0, 145, 942, 1, 0, 0, 0, 147, 951, 1, 0, 0, 0, 149, 953,
1, 0, 0, 0, 151, 969, 1, 0, 0, 0, 153, 971, 1, 0, 0, 0, 155, 978, 1, 0,
0, 0, 157, 990, 1, 0, 0, 0, 159, 993, 1, 0, 0, 0, 161, 997, 1, 0, 0, 0,
163, 1018, 1, 0, 0, 0, 165, 1021, 1, 0, 0, 0, 167, 1032, 1, 0, 0, 0, 169,
170, 5, 40, 0, 0, 170, 2, 1, 0, 0, 0, 171, 172, 5, 41, 0, 0, 172, 4, 1,
0, 0, 0, 173, 174, 5, 91, 0, 0, 174, 6, 1, 0, 0, 0, 175, 176, 5, 44, 0,
0, 176, 8, 1, 0, 0, 0, 177, 178, 5, 93, 0, 0, 178, 10, 1, 0, 0, 0, 179,
180, 5, 123, 0, 0, 180, 12, 1, 0, 0, 0, 181, 182, 5, 125, 0, 0, 182, 14,
1, 0, 0, 0, 183, 184, 5, 60, 0, 0, 184, 16, 1, 0, 0, 0, 185, 186, 5, 60,
0, 0, 186, 187, 5, 61, 0, 0, 187, 18, 1, 0, 0, 0, 188, 189, 5, 62, 0, 0,
189, 20, 1, 0, 0, 0, 190, 191, 5, 62, 0, 0, 191, 192, 5, 61, 0, 0, 192,
22, 1, 0, 0, 0, 193, 194, 5, 61, 0, 0, 194, 195, 5, 61, 0, 0, 195, 24,
1, 0, 0, 0, 196, 197, 5, 33, 0, 0, 197, 198, 5, 61, 0, 0, 198, 26, 1, 0,
0, 0, 199, 200, 5, 108, 0, 0, 200, 201, 5, 105, 0, 0, 201, 202, 5, 107,
0, 0, 202, 208, 5, 101, 0, 0, 203, 204, 5, 76, 0, 0, 204, 205, 5, 73, 0,
0, 205, 206, 5, 75, 0, 0, 206, 208, 5, 69, 0, 0, 207, 199, 1, 0, 0, 0,
207, 203, 1, 0, 0, 0, 208, 28, 1, 0, 0, 0, 209, 210, 5, 101, 0, 0, 210,
211, 5, 120, 0, 0, 211, 212, 5, 105, 0, 0, 212, 213, 5, 115, 0, 0, 213,
214, 5, 116, 0, 0, 214, 222, 5, 115, 0, 0, 215, 216, 5, 69, 0, 0, 216,
217, 5, 88, 0, 0, 217, 218, 5, 73, 0, 0, 218, 219, 5, 83, 0, 0, 219, 220,
5, 84, 0, 0, 220, 222, 5, 83, 0, 0, 221, 209, 1, 0, 0, 0, 221, 215, 1,
0, 0, 0, 222, 30, 1, 0, 0, 0, 223, 224, 5, 116, 0, 0, 224, 225, 5, 101,
0, 0, 225, 226, 5, 120, 0, 0, 226, 227, 5, 116, 0, 0, 227, 228, 5, 95,
0, 0, 228, 229, 5, 109, 0, 0, 229, 230, 5, 97, 0, 0, 230, 231, 5, 116,
0, 0, 231, 232, 5, 99, 0, 0, 232, 244, 5, 104, 0, 0, 233, 234, 5, 84, 0,
0, 234, 235, 5, 69, 0, 0, 235, 236, 5, 88, 0, 0, 236, 237, 5, 84, 0, 0,
237, 238, 5, 95, 0, 0, 238, 239, 5, 77, 0, 0, 239, 240, 5, 65, 0, 0, 240,
241, 5, 84, 0, 0, 241, 242, 5, 67, 0, 0, 242, 244, 5, 72, 0, 0, 243, 223,
1, 0, 0, 0, 243, 233, 1, 0, 0, 0, 244, 32, 1, 0, 0, 0, 245, 246, 5, 112,
0, 0, 246, 247, 5, 104, 0, 0, 247, 248, 5, 114, 0, 0, 248, 249, 5, 97,
0, 0, 249, 250, 5, 115, 0, 0, 250, 251, 5, 101, 0, 0, 251, 252, 5, 95,
0, 0, 252, 253, 5, 109, 0, 0, 253, 254, 5, 97, 0, 0, 254, 255, 5, 116,
0, 0, 255, 256, 5, 99, 0, 0, 256, 270, 5, 104, 0, 0, 257, 258, 5, 80, 0,
0, 258, 259, 5, 72, 0, 0, 259, 260, 5, 82, 0, 0, 260, 261, 5, 65, 0, 0,
261, 262, 5, 83, 0, 0, 262, 263, 5, 69, 0, 0, 263, 264, 5, 95, 0, 0, 264,
265, 5, 77, 0, 0, 265, 266, 5, 65, 0, 0, 266, 267, 5, 84, 0, 0, 267, 268,
5, 67, 0, 0, 268, 270, 5, 72, 0, 0, 269, 245, 1, 0, 0, 0, 269, 257, 1,
0, 0, 0, 270, 34, 1, 0, 0, 0, 271, 272, 5, 43, 0, 0, 272, 36, 1, 0, 0,
0, 273, 274, 5, 45, 0, 0, 274, 38, 1, 0, 0, 0, 275, 276, 5, 42, 0, 0, 276,
40, 1, 0, 0, 0, 277, 278, 5, 47, 0, 0, 278, 42, 1, 0, 0, 0, 279, 280, 5,
37, 0, 0, 280, 44, 1, 0, 0, 0, 281, 282, 5, 42, 0, 0, 282, 283, 5, 42,
0, 0, 283, 46, 1, 0, 0, 0, 284, 285, 5, 60, 0, 0, 285, 286, 5, 60, 0, 0,
286, 48, 1, 0, 0, 0, 287, 288, 5, 62, 0, 0, 288, 289, 5, 62, 0, 0, 289,
50, 1, 0, 0, 0, 290, 291, 5, 38, 0, 0, 291, 52, 1, 0, 0, 0, 292, 293, 5,
124, 0, 0, 293, 54, 1, 0, 0, 0, 294, 295, 5, 94, 0, 0, 295, 56, 1, 0, 0,
0, 296, 297, 5, 38, 0, 0, 297, 305, 5, 38, 0, 0, 298, 299, 5, 97, 0, 0,
299, 300, 5, 110, 0, 0, 300, 305, 5, 100, 0, 0, 301, 302, 5, 65, 0, 0,
302, 303, 5, 78, 0, 0, 303, 305, 5, 68, 0, 0, 304, 296, 1, 0, 0, 0, 304,
298, 1, 0, 0, 0, 304, 301, 1, 0, 0, 0, 305, 58, 1, 0, 0, 0, 306, 307, 5,
124, 0, 0, 307, 313, 5, 124, 0, 0, 308, 309, 5, 111, 0, 0, 309, 313, 5,
114, 0, 0, 310, 311, 5, 79, 0, 0, 311, 313, 5, 82, 0, 0, 312, 306, 1, 0,
0, 0, 312, 308, 1, 0, 0, 0, 312, 310, 1, 0, 0, 0, 313, 60, 1, 0, 0, 0,
314, 315, 5, 105, 0, 0, 315, 316, 5, 115, 0, 0, 316, 317, 5, 32, 0, 0,
317, 318, 5, 110, 0, 0, 318, 319, 5, 117, 0, 0, 319, 320, 5, 108, 0, 0,
320, 329, 5, 108, 0, 0, 321, 322, 5, 73, 0, 0, 322, 323, 5, 83, 0, 0, 323,
324, 5, 32, 0, 0, 324, 325, 5, 78, 0, 0, 325, 326, 5, 85, 0, 0, 326, 327,
5, 76, 0, 0, 327, 329, 5, 76, 0, 0, 328, 314, 1, 0, 0, 0, 328, 321, 1,
0, 0, 0, 329, 62, 1, 0, 0, 0, 330, 331, 5, 105, 0, 0, 331, 332, 5, 115,
0, 0, 332, 333, 5, 32, 0, 0, 333, 334, 5, 110, 0, 0, 334, 335, 5, 111,
0, 0, 335, 336, 5, 116, 0, 0, 336, 337, 5, 32, 0, 0, 337, 338, 5, 110,
0, 0, 338, 339, 5, 117, 0, 0, 339, 340, 5, 108, 0, 0, 340, 353, 5, 108,
0, 0, 341, 342, 5, 73, 0, 0, 342, 343, 5, 83, 0, 0, 343, 344, 5, 32, 0,
0, 344, 345, 5, 78, 0, 0, 345, 346, 5, 79, 0, 0, 346, 347, 5, 84, 0, 0,
347, 348, 5, 32, 0, 0, 348, 349, 5, 78, 0, 0, 349, 350, 5, 85, 0, 0, 350,
351, 5, 76, 0, 0, 351, 353, 5, 76, 0, 0, 352, 330, 1, 0, 0, 0, 352, 341,
1, 0, 0, 0, 353, 64, 1, 0, 0, 0, 354, 355, 5, 126, 0, 0, 355, 66, 1, 0,
0, 0, 356, 364, 5, 33, 0, 0, 357, 358, 5, 110, 0, 0, 358, 359, 5, 111,
0, 0, 359, 364, 5, 116, 0, 0, 360, 361, 5, 78, 0, 0, 361, 362, 5, 79, 0,
0, 362, 364, 5, 84, 0, 0, 363, 356, 1, 0, 0, 0, 363, 357, 1, 0, 0, 0, 363,
360, 1, 0, 0, 0, 364, 68, 1, 0, 0, 0, 365, 366, 5, 105, 0, 0, 366, 370,
5, 110, 0, 0, 367, 368, 5, 73, 0, 0, 368, 370, 5, 78, 0, 0, 369, 365, 1,
0, 0, 0, 369, 367, 1, 0, 0, 0, 370, 70, 1, 0, 0, 0, 371, 376, 5, 91, 0,
0, 372, 375, 3, 165, 82, 0, 373, 375, 3, 167, 83, 0, 374, 372, 1, 0, 0,
0, 374, 373, 1, 0, 0, 0, 375, 378, 1, 0, 0, 0, 376, 374, 1, 0, 0, 0, 376,
377, 1, 0, 0, 0, 377, 379, 1, 0, 0, 0, 378, 376, 1, 0, 0, 0, 379, 380,
5, 93, 0, 0, 380, 72, 1, 0, 0, 0, 381, 382, 5, 106, 0, 0, 382, 383, 5,
115, 0, 0, 383, 384, 5, 111, 0, 0, 384, 385, 5, 110, 0, 0, 385, 386, 5,
95, 0, 0, 386, 387, 5, 99, 0, 0, 387, 388, 5, 111, 0, 0, 388, 389, 5, 110,
0, 0, 389, 390, 5, 116, 0, 0, 390, 391, 5, 97, 0, 0, 391, 392, 5, 105,
0, 0, 392, 393, 5, 110, 0, 0, 393, 408, 5, 115, 0, 0, 394, 395, 5, 74,
0, 0, 395, 396, 5, 83, 0, 0, 396, 397, 5, 79, 0, 0, 397, 398, 5, 78, 0,
0, 398, 399, 5, 95, 0, 0, 399, 400, 5, 67, 0, 0, 400, 401, 5, 79, 0, 0,
401, 402, 5, 78, 0, 0, 402, 403, 5, 84, 0, 0, 403, 404, 5, 65, 0, 0, 404,
405, 5, 73, 0, 0, 405, 406, 5, 78, 0, 0, 406, 408, 5, 83, 0, 0, 407, 381,
1, 0, 0, 0, 407, 394, 1, 0, 0, 0, 408, 74, 1, 0, 0, 0, 409, 410, 5, 106,
0, 0, 410, 411, 5, 115, 0, 0, 411, 412, 5, 111, 0, 0, 412, 413, 5, 110,
0, 0, 413, 414, 5, 95, 0, 0, 414, 415, 5, 99, 0, 0, 415, 416, 5, 111, 0,
0, 416, 417, 5, 110, 0, 0, 417, 418, 5, 116, 0, 0, 418, 419, 5, 97, 0,
0, 419, 420, 5, 105, 0, 0, 420, 421, 5, 110, 0, 0, 421, 422, 5, 115, 0,
0, 422, 423, 5, 95, 0, 0, 423, 424, 5, 97, 0, 0, 424, 425, 5, 108, 0, 0,
425, 444, 5, 108, 0, 0, 426, 427, 5, 74, 0, 0, 427, 428, 5, 83, 0, 0, 428,
429, 5, 79, 0, 0, 429, 430, 5, 78, 0, 0, 430, 431, 5, 95, 0, 0, 431, 432,
5, 67, 0, 0, 432, 433, 5, 79, 0, 0, 433, 434, 5, 78, 0, 0, 434, 435, 5,
84, 0, 0, 435, 436, 5, 65, 0, 0, 436, 437, 5, 73, 0, 0, 437, 438, 5, 78,
0, 0, 438, 439, 5, 83, 0, 0, 439, 440, 5, 95, 0, 0, 440, 441, 5, 65, 0,
0, 441, 442, 5, 76, 0, 0, 442, 444, 5, 76, 0, 0, 443, 409, 1, 0, 0, 0,
443, 426, 1, 0, 0, 0, 444, 76, 1, 0, 0, 0, 445, 446, 5, 106, 0, 0, 446,
447, 5, 115, 0, 0, 447, 448, 5, 111, 0, 0, 448, 449, 5, 110, 0, 0, 449,
450, 5, 95, 0, 0, 450, 451, 5, 99, 0, 0, 451, 452, 5, 111, 0, 0, 452, 453,
5, 110, 0, 0, 453, 454, 5, 116, 0, 0, 454, 455, 5, 97, 0, 0, 455, 456,
5, 105, 0, 0, 456, 457, 5, 110, 0, 0, 457, 458, 5, 115, 0, 0, 458, 459,
5, 95, 0, 0, 459, 460, 5, 97, 0, 0, 460, 461, 5, 110, 0, 0, 461, 480, 5,
121, 0, 0, 462, 463, 5, 74, 0, 0, 463, 464, 5, 83, 0, 0, 464, 465, 5, 79,
0, 0, 465, 466, 5, 78, 0, 0, 466, 467, 5, 95, 0, 0, 467, 468, 5, 67, 0,
0, 468, 469, 5, 79, 0, 0, 469, 470, 5, 78, 0, 0, 470, 471, 5, 84, 0, 0,
471, 472, 5, 65, 0, 0, 472, 473, 5, 73, 0, 0, 473, 474, 5, 78, 0, 0, 474,
475, 5, 83, 0, 0, 475, 476, 5, 95, 0, 0, 476, 477, 5, 65, 0, 0, 477, 478,
5, 78, 0, 0, 478, 480, 5, 89, 0, 0, 479, 445, 1, 0, 0, 0, 479, 462, 1,
0, 0, 0, 480, 78, 1, 0, 0, 0, 481, 482, 5, 97, 0, 0, 482, 483, 5, 114,
0, 0, 483, 484, 5, 114, 0, 0, 484, 485, 5, 97, 0, 0, 485, 486, 5, 121,
0, 0, 486, 487, 5, 95, 0, 0, 487, 488, 5, 99, 0, 0, 488, 489, 5, 111, 0,
0, 489, 490, 5, 110, 0, 0, 490, 491, 5, 116, 0, 0, 491, 492, 5, 97, 0,
0, 492, 493, 5, 105, 0, 0, 493, 494, 5, 110, 0, 0, 494, 510, 5, 115, 0,
0, 495, 496, 5, 65, 0, 0, 496, 497, 5, 82, 0, 0, 497, 498, 5, 82, 0, 0,
498, 499, 5, 65, 0, 0, 499, 500, 5, 89, 0, 0, 500, 501, 5, 95, 0, 0, 501,
502, 5, 67, 0, 0, 502, 503, 5, 79, 0, 0, 503, 504, 5, 78, 0, 0, 504, 505,
5, 84, 0, 0, 505, 506, 5, 65, 0, 0, 506, 507, 5, 73, 0, 0, 507, 508, 5,
78, 0, 0, 508, 510, 5, 83, 0, 0, 509, 481, 1, 0, 0, 0, 509, 495, 1, 0,
0, 0, 510, 80, 1, 0, 0, 0, 511, 512, 5, 97, 0, 0, 512, 513, 5, 114, 0,
0, 513, 514, 5, 114, 0, 0, 514, 515, 5, 97, 0, 0, 515, 516, 5, 121, 0,
0, 516, 517, 5, 95, 0, 0, 517, 518, 5, 99, 0, 0, 518, 519, 5, 111, 0, 0,
519, 520, 5, 110, 0, 0, 520, 521, 5, 116, 0, 0, 521, 522, 5, 97, 0, 0,
522, 523, 5, 105, 0, 0, 523, 524, 5, 110, 0, 0, 524, 525, 5, 115, 0, 0,
525, 526, 5, 95, 0, 0, 526, 527, 5, 97, 0, 0, 527, 528, 5, 108, 0, 0, 528,
548, 5, 108, 0, 0, 529, 530, 5, 65, 0, 0, 530, 531, 5, 82, 0, 0, 531, 532,
5, 82, 0, 0, 532, 533, 5, 65, 0, 0, 533, 534, 5, 89, 0, 0, 534, 535, 5,
95, 0, 0, 535, 536, 5, 67, 0, 0, 536, 537, 5, 79, 0, 0, 537, 538, 5, 78,
0, 0, 538, 539, 5, 84, 0, 0, 539, 540, 5, 65, 0, 0, 540, 541, 5, 73, 0,
0, 541, 542, 5, 78, 0, 0, 542, 543, 5, 83, 0, 0, 543, 544, 5, 95, 0, 0,
544, 545, 5, 65, 0, 0, 545, 546, 5, 76, 0, 0, 546, 548, 5, 76, 0, 0, 547,
511, 1, 0, 0, 0, 547, 529, 1, 0, 0, 0, 548, 82, 1, 0, 0, 0, 549, 550, 5,
97, 0, 0, 550, 551, 5, 114, 0, 0, 551, 552, 5, 114, 0, 0, 552, 553, 5,
97, 0, 0, 553, 554, 5, 121, 0, 0, 554, 555, 5, 95, 0, 0, 555, 556, 5, 99,
0, 0, 556, 557, 5, 111, 0, 0, 557, 558, 5, 110, 0, 0, 558, 559, 5, 116,
0, 0, 559, 560, 5, 97, 0, 0, 560, 561, 5, 105, 0, 0, 561, 562, 5, 110,
0, 0, 562, 563, 5, 115, 0, 0, 563, 564, 5, 95, 0, 0, 564, 565, 5, 97, 0,
0, 565, 566, 5, 110, 0, 0, 566, 586, 5, 121, 0, 0, 567, 568, 5, 65, 0,
0, 568, 569, 5, 82, 0, 0, 569, 570, 5, 82, 0, 0, 570, 571, 5, 65, 0, 0,
571, 572, 5, 89, 0, 0, 572, 573, 5, 95, 0, 0, 573, 574, 5, 67, 0, 0, 574,
575, 5, 79, 0, 0, 575, 576, 5, 78, 0, 0, 576, 577, 5, 84, 0, 0, 577, 578,
5, 65, 0, 0, 578, 579, 5, 73, 0, 0, 579, 580, 5, 78, 0, 0, 580, 581, 5,
83, 0, 0, 581, 582, 5, 95, 0, 0, 582, 583, 5, 65, 0, 0, 583, 584, 5, 78,
0, 0, 584, 586, 5, 89, 0, 0, 585, 549, 1, 0, 0, 0, 585, 567, 1, 0, 0, 0,
586, 84, 1, 0, 0, 0, 587, 588, 5, 97, 0, 0, 588, 589, 5, 114, 0, 0, 589,
590, 5, 114, 0, 0, 590, 591, 5, 97, 0, 0, 591, 592, 5, 121, 0, 0, 592,
593, 5, 95, 0, 0, 593, 594, 5, 108, 0, 0, 594, 595, 5, 101, 0, 0, 595,
596, 5, 110, 0, 0, 596, 597, 5, 103, 0, 0, 597, 598, 5, 116, 0, 0, 598,
612, 5, 104, 0, 0, 599, 600, 5, 65, 0, 0, 600, 601, 5, 82, 0, 0, 601, 602,
5, 82, 0, 0, 602, 603, 5, 65, 0, 0, 603, 604, 5, 89, 0, 0, 604, 605, 5,
95, 0, 0, 605, 606, 5, 76, 0, 0, 606, 607, 5, 69, 0, 0, 607, 608, 5, 78,
0, 0, 608, 609, 5, 71, 0, 0, 609, 610, 5, 84, 0, 0, 610, 612, 5, 72, 0,
0, 611, 587, 1, 0, 0, 0, 611, 599, 1, 0, 0, 0, 612, 86, 1, 0, 0, 0, 613,
614, 5, 115, 0, 0, 614, 615, 5, 116, 0, 0, 615, 616, 5, 95, 0, 0, 616,
617, 5, 101, 0, 0, 617, 618, 5, 113, 0, 0, 618, 619, 5, 117, 0, 0, 619,
620, 5, 97, 0, 0, 620, 621, 5, 108, 0, 0, 621, 632, 5, 115, 0, 0, 622,
623, 5, 83, 0, 0, 623, 624, 5, 84, 0, 0, 624, 625, 5, 95, 0, 0, 625, 626,
5, 69, 0, 0, 626, 627, 5, 81, 0, 0, 627, 628, 5, 85, 0, 0, 628, 629, 5,
65, 0, 0, 629, 630, 5, 76, 0, 0, 630, 632, 5, 83, 0, 0, 631, 613, 1, 0,
0, 0, 631, 622, 1, 0, 0, 0, 632, 88, 1, 0, 0, 0, 633, 634, 5, 115, 0, 0,
634, 635, 5, 116, 0, 0, 635, 636, 5, 95, 0, 0, 636, 637, 5, 116, 0, 0,
637, 638, 5, 111, 0, 0, 638, 639, 5, 117, 0, 0, 639, 640, 5, 99, 0, 0,
640, 641, 5, 104, 0, 0, 641, 642, 5, 101, 0, 0, 642, 654, 5, 115, 0, 0,
643, 644, 5, 83, 0, 0, 644, 645, 5, 84, 0, 0, 645, 646, 5, 95, 0, 0, 646,
647, 5, 84, 0, 0, 647, 648, 5, 79, 0, 0, 648, 649, 5, 85, 0, 0, 649, 650,
5, 67, 0, 0, 650, 651, 5, 72, 0, 0, 651, 652, 5, 69, 0, 0, 652, 654, 5,
83, 0, 0, 653, 633, 1, 0, 0, 0, 653, 643, 1, 0, 0, 0, 654, 90, 1, 0, 0,
0, 655, 656, 5, 115, 0, 0, 656, 657, 5, 116, 0, 0, 657, 658, 5, 95, 0,
0, 658, 659, 5, 111, 0, 0, 659, 660, 5, 118, 0, 0, 660, 661, 5, 101, 0,
0, 661, 662, 5, 114, 0, 0, 662, 663, 5, 108, 0, 0, 663, 664, 5, 97, 0,
0, 664, 665, 5, 112, 0, 0, 665, 678, 5, 115, 0, 0, 666, 667, 5, 83, 0,
0, 667, 668, 5, 84, 0, 0, 668, 669, 5, 95, 0, 0, 669, 670, 5, 79, 0, 0,
670, 671, 5, 86, 0, 0, 671, 672, 5, 69, 0, 0, 672, 673, 5, 82, 0, 0, 673,
674, 5, 76, 0, 0, 674, 675, 5, 65, 0, 0, 675, 676, 5, 80, 0, 0, 676, 678,
5, 83, 0, 0, 677, 655, 1, 0, 0, 0, 677, 666, 1, 0, 0, 0, 678, 92, 1, 0,
0, 0, 679, 680, 5, 115, 0, 0, 680, 681, 5, 116, 0, 0, 681, 682, 5, 95,
0, 0, 682, 683, 5, 99, 0, 0, 683, 684, 5, 114, 0, 0, 684, 685, 5, 111,
0, 0, 685, 686, 5, 115, 0, 0, 686, 687, 5, 115, 0, 0, 687, 688, 5, 101,
0, 0, 688, 700, 5, 115, 0, 0, 689, 690, 5, 83, 0, 0, 690, 691, 5, 84, 0,
0, 691, 692, 5, 95, 0, 0, 692, 693, 5, 67, 0, 0, 693, 694, 5, 82, 0, 0,
694, 695, 5, 79, 0, 0, 695, 696, 5, 83, 0, 0, 696, 697, 5, 83, 0, 0, 697,
698, 5, 69, 0, 0, 698, 700, 5, 83, 0, 0, 699, 679, 1, 0, 0, 0, 699, 689,
1, 0, 0, 0, 700, 94, 1, 0, 0, 0, 701, 702, 5, 115, 0, 0, 702, 703, 5, 116,
0, 0, 703, 704, 5, 95, 0, 0, 704, 705, 5, 99, 0, 0, 705, 706, 5, 111, 0,
0, 706, 707, 5, 110, 0, 0, 707, 708, 5, 116, 0, 0, 708, 709, 5, 97, 0,
0, 709, 710, 5, 105, 0, 0, 710, 711, 5, 110, 0, 0, 711, 724, 5, 115, 0,
0, 712, 713, 5, 83, 0, 0, 713, 714, 5, 84, 0, 0, 714, 715, 5, 95, 0, 0,
715, 716, 5, 67, 0, 0, 716, 717, 5, 79, 0, 0, 717, 718, 5, 78, 0, 0, 718,
719, 5, 84, 0, 0, 719, 720, 5, 65, 0, 0, 720, 721, 5, 73, 0, 0, 721, 722,
5, 78, 0, 0, 722, 724, 5, 83, 0, 0, 723, 701, 1, 0, 0, 0, 723, 712, 1,
0, 0, 0, 724, 96, 1, 0, 0, 0, 725, 726, 5, 115, 0, 0, 726, 727, 5, 116,
0, 0, 727, 728, 5, 95, 0, 0, 728, 729, 5, 105, 0, 0, 729, 730, 5, 110,
0, 0, 730, 731, 5, 116, 0, 0, 731, 732, 5, 101, 0, 0, 732, 733, 5, 114,
0, 0, 733, 734, 5, 115, 0, 0, 734, 735, 5, 101, 0, 0, 735, 736, 5, 99,
0, 0, 736, 737, 5, 116, 0, 0, 737, 752, 5, 115, 0, 0, 738, 739, 5, 83,
0, 0, 739, 740, 5, 84, 0, 0, 740, 741, 5, 95, 0, 0, 741, 742, 5, 73, 0,
0, 742, 743, 5, 78, 0, 0, 743, 744, 5, 84, 0, 0, 744, 745, 5, 69, 0, 0,
745, 746, 5, 82, 0, 0, 746, 747, 5, 83, 0, 0, 747, 748, 5, 69, 0, 0, 748,
749, 5, 67, 0, 0, 749, 750, 5, 84, 0, 0, 750, 752, 5, 83, 0, 0, 751, 725,
1, 0, 0, 0, 751, 738, 1, 0, 0, 0, 752, 98, 1, 0, 0, 0, 753, 754, 5, 115,
0, 0, 754, 755, 5, 116, 0, 0, 755, 756, 5, 95, 0, 0, 756, 757, 5, 119,
0, 0, 757, 758, 5, 105, 0, 0, 758, 759, 5, 116, 0, 0, 759, 760, 5, 104,
0, 0, 760, 761, 5, 105, 0, 0, 761, 772, 5, 110, 0, 0, 762, 763, 5, 83,
0, 0, 763, 764, 5, 84, 0, 0, 764, 765, 5, 95, 0, 0, 765, 766, 5, 87, 0,
0, 766, 767, 5, 73, 0, 0, 767, 768, 5, 84, 0, 0, 768, 769, 5, 72, 0, 0,
769, 770, 5, 73, 0, 0, 770, 772, 5, 78, 0, 0, 771, 753, 1, 0, 0, 0, 771,
762, 1, 0, 0, 0, 772, 100, 1, 0, 0, 0, 773, 774, 5, 116, 0, 0, 774, 775,
5, 114, 0, 0, 775, 776, 5, 117, 0, 0, 776, 801, 5, 101, 0, 0, 777, 778,
5, 84, 0, 0, 778, 779, 5, 114, 0, 0, 779, 780, 5, 117, 0, 0, 780, 801,
5, 101, 0, 0, 781, 782, 5, 84, 0, 0, 782, 783, 5, 82, 0, 0, 783, 784, 5,
85, 0, 0, 784, 801, 5, 69, 0, 0, 785, 786, 5, 102, 0, 0, 786, 787, 5, 97,
0, 0, 787, 788, 5, 108, 0, 0, 788, 789, 5, 115, 0, 0, 789, 801, 5, 101,
0, 0, 790, 791, 5, 70, 0, 0, 791, 792, 5, 97, 0, 0, 792, 793, 5, 108, 0,
0, 793, 794, 5, 115, 0, 0, 794, 801, 5, 101, 0, 0, 795, 796, 5, 70, 0,
0, 796, 797, 5, 65, 0, 0, 797, 798, 5, 76, 0, 0, 798, 799, 5, 83, 0, 0,
799, 801, 5, 69, 0, 0, 800, 773, 1, 0, 0, 0, 800, 777, 1, 0, 0, 0, 800,
781, 1, 0, 0, 0, 800, 785, 1, 0, 0, 0, 800, 790, 1, 0, 0, 0, 800, 795,
1, 0, 0, 0, 801, 102, 1, 0, 0, 0, 802, 807, 3, 131, 65, 0, 803, 807, 3,
133, 66, 0, 804, 807, 3, 135, 67, 0, 805, 807, 3, 129, 64, 0, 806, 802,
1, 0, 0, 0, 806, 803, 1, 0, 0, 0, 806, 804, 1, 0, 0, 0, 806, 805, 1, 0,
0, 0, 807, 104, 1, 0, 0, 0, 808, 811, 3, 147, 73, 0, 809, 811, 3, 149,
74, 0, 810, 808, 1, 0, 0, 0, 810, 809, 1, 0, 0, 0, 811, 106, 1, 0, 0, 0,
812, 817, 3, 125, 62, 0, 813, 816, 3, 125, 62, 0, 814, 816, 3, 127, 63,
0, 815, 813, 1, 0, 0, 0, 815, 814, 1, 0, 0, 0, 816, 819, 1, 0, 0, 0, 817,
815, 1, 0, 0, 0, 817, 818, 1, 0, 0, 0, 818, 108, 1, 0, 0, 0, 819, 817,
1, 0, 0, 0, 820, 821, 5, 36, 0, 0, 821, 822, 5, 109, 0, 0, 822, 823, 5,
101, 0, 0, 823, 824, 5, 116, 0, 0, 824, 825, 5, 97, 0, 0, 825, 110, 1,
0, 0, 0, 826, 828, 3, 115, 57, 0, 827, 826, 1, 0, 0, 0, 827, 828, 1, 0,
0, 0, 828, 839, 1, 0, 0, 0, 829, 831, 5, 34, 0, 0, 830, 832, 3, 117, 58,
0, 831, 830, 1, 0, 0, 0, 831, 832, 1, 0, 0, 0, 832, 833, 1, 0, 0, 0, 833,
840, 5, 34, 0, 0, 834, 836, 5, 39, 0, 0, 835, 837, 3, 119, 59, 0, 836,
835, 1, 0, 0, 0, 836, 837, 1, 0, 0, 0, 837, 838, 1, 0, 0, 0, 838, 840,
5, 39, 0, 0, 839, 829, 1, 0, 0, 0, 839, 834, 1, 0, 0, 0, 840, 112, 1, 0,
0, 0, 841, 844, 3, 107, 53, 0, 842, 844, 3, 109, 54, 0, 843, 841, 1, 0,
0, 0, 843, 842, 1, 0, 0, 0, 844, 852, 1, 0, 0, 0, 845, 848, 5, 91, 0, 0,
846, 849, 3, 111, 55, 0, 847, 849, 3, 131, 65, 0, 848, 846, 1, 0, 0, 0,
848, 847, 1, 0, 0, 0, 849, 850, 1, 0, 0, 0, 850, 851, 5, 93, 0, 0, 851,
853, 1, 0, 0, 0, 852, 845, 1, 0, 0, 0, 853, 854, 1, 0, 0, 0, 854, 852,
1, 0, 0, 0, 854, 855, 1, 0, 0, 0, 855, 114, 1, 0, 0, 0, 856, 857, 5, 117,
0, 0, 857, 860, 5, 56, 0, 0, 858, 860, 7, 0, 0, 0, 859, 856, 1, 0, 0, 0,
859, 858, 1, 0, 0, 0, 860, 116, 1, 0, 0, 0, 861, 863, 3, 121, 60, 0, 862,
861, 1, 0, 0, 0, 863, 864, 1, 0, 0, 0, 864, 862, 1, 0, 0, 0, 864, 865,
1, 0, 0, 0, 865, 118, 1, 0, 0, 0, 866, 868, 3, 123, 61, 0, 867, 866, 1,
0, 0, 0, 868, 869, 1, 0, 0, 0, 869, 867, 1, 0, 0, 0, 869, 870, 1, 0, 0,
0, 870, 120, 1, 0, 0, 0, 871, 879, 8, 1, 0, 0, 872, 879, 3, 163, 81, 0,
873, 874, 5, 92, 0, 0, 874, 879, 5, 10, 0, 0, 875, 876, 5, 92, 0, 0, 876,
877, 5, 13, 0, 0, 877, 879, 5, 10, 0, 0, 878, 871, 1, 0, 0, 0, 878, 872,
1, 0, 0, 0, 878, 873, 1, 0, 0, 0, 878, 875, 1, 0, 0, 0, 879, 122, 1, 0,
0, 0, 880, 888, 8, 2, 0, 0, 881, 888, 3, 163, 81, 0, 882, 883, 5, 92, 0,
0, 883, 888, 5, 10, 0, 0, 884, 885, 5, 92, 0, 0, 885, 886, 5, 13, 0, 0,
886, 888, 5, 10, 0, 0, 887, 880, 1, 0, 0, 0, 887, 881, 1, 0, 0, 0, 887,
882, 1, 0, 0, 0, 887, 884, 1, 0, 0, 0, 888, 124, 1, 0, 0, 0, 889, 890,
7, 3, 0, 0, 890, 126, 1, 0, 0, 0, 891, 892, 7, 4, 0, 0, 892, 128, 1, 0,
0, 0, 893, 894, 5, 48, 0, 0, 894, 896, 7, 5, 0, 0, 895, 897, 7, 6, 0, 0,
896, 895, 1, 0, 0, 0, 897, 898, 1, 0, 0, 0, 898, 896, 1, 0, 0, 0, 898,
899, 1, 0, 0, 0, 899, 130, 1, 0, 0, 0, 900, 904, 3, 137, 68, 0, 901, 903,
3, 127, 63, 0, 902, 901, 1, 0, 0, 0, 903, 906, 1, 0, 0, 0, 904, 902, 1,
0, 0, 0, 904, 905, 1, 0, 0, 0, 905, 909, 1, 0, 0, 0, 906, 904, 1, 0, 0,
0, 907, 909, 5, 48, 0, 0, 908, 900, 1, 0, 0, 0, 908, 907, 1, 0, 0, 0, 909,
132, 1, 0, 0, 0, 910, 914, 5, 48, 0, 0, 911, 913, 3, 139, 69, 0, 912, 911,
1, 0, 0, 0, 913, 916, 1, 0, 0, 0, 914, 912, 1, 0, 0, 0, 914, 915, 1, 0,
0, 0, 915, 134, 1, 0, 0, 0, 916, 914, 1, 0, 0, 0, 917, 918, 5, 48, 0, 0,
918, 919, 7, 7, 0, 0, 919, 920, 3, 159, 79, 0, 920, 136, 1, 0, 0, 0, 921,
922, 7, 8, 0, 0, 922, 138, 1, 0, 0, 0, 923, 924, 7, 9, 0, 0, 924, 140,
1, 0, 0, 0, 925, 926, 7, 10, 0, 0, 926, 142, 1, 0, 0, 0, 927, 928, 3, 141,
70, 0, 928, 929, 3, 141, 70, 0, 929, 930, 3, 141, 70, 0, 930, 931, 3, 141,
70, 0, 931, 144, 1, 0, 0, 0, 932, 933, 5, 92, 0, 0, 933, 934, 5, 117, 0,
0, 934, 935, 1, 0, 0, 0, 935, 943, 3, 143, 71, 0, 936, 937, 5, 92, 0, 0,
937, 938, 5, 85, 0, 0, 938, 939, 1, 0, 0, 0, 939, 940, 3, 143, 71, 0, 940,
941, 3, 143, 71, 0, 941, 943, 1, 0, 0, 0, 942, 932, 1, 0, 0, 0, 942, 936,
1, 0, 0, 0, 943, 146, 1, 0, 0, 0, 944, 946, 3, 151, 75, 0, 945, 947, 3,
153, 76, 0, 946, 945, 1, 0, 0, 0, 946, 947, 1, 0, 0, 0, 947, 952, 1, 0,
0, 0, 948, 949, 3, 155, 77, 0, 949, 950, 3, 153, 76, 0, 950, 952, 1, 0,
0, 0, 951, 944, 1, 0, 0, 0, 951, 948, 1, 0, 0, 0, 952, 148, 1, 0, 0, 0,
953, 954, 5, 48, 0, 0, 954, 957, 7, 7, 0, 0, 955, 958, 3, 157, 78, 0, 956,
958, 3, 159, 79, 0, 957, 955, 1, 0, 0, 0, 957, 956, 1, 0, 0, 0, 958, 959,
1, 0, 0, 0, 959, 960, 3, 161, 80, 0, 960, 150, 1, 0, 0, 0, 961, 963, 3,
155, 77, 0, 962, 961, 1, 0, 0, 0, 962, 963, 1, 0, 0, 0, 963, 964, 1, 0,
0, 0, 964, 965, 5, 46, 0, 0, 965, 970, 3, 155, 77, 0, 966, 967, 3, 155,
77, 0, 967, 968, 5, 46, 0, 0, 968, 970, 1, 0, 0, 0, 969, 962, 1, 0, 0,
0, 969, 966, 1, 0, 0, 0, 970, 152, 1, 0, 0, 0, 971, 973, 7, 11, 0, 0, 972,
974, 7, 12, 0, 0, 973, 972, 1, 0, 0, 0, 973, 974, 1, 0, 0, 0, 974, 975,
1, 0, 0, 0, 975, 976, 3, 155, 77, 0, 976, 154, 1, 0, 0, 0, 977, 979, 3,
127, 63, 0, 978, 977, 1, 0, 0, 0, 979, 980, 1, 0, 0, 0, 980, 978, 1, 0,
0, 0, 980, 981, 1, 0, 0, 0, 981, 156, 1, 0, 0, 0, 982, 984, 3, 159, 79,
0, 983, 982, 1, 0, 0, 0, 983, 984, 1, 0, 0, 0, 984, 985, 1, 0, 0, 0, 985,
986, 5, 46, 0, 0, 986, 991, 3, 159, 79, 0, 987, 988, 3, 159, 79, 0, 988,
989, 5, 46, 0, 0, 989, 991, 1, 0, 0, 0, 990, 983, 1, 0, 0, 0, 990, 987,
1, 0, 0, 0, 991, 158, 1, 0, 0, 0, 992, 994, 3, 141, 70, 0, 993, 992, 1,
0, 0, 0, 994, 995, 1, 0, 0, 0, 995, 993, 1, 0, 0, 0, 995, 996, 1, 0, 0,
0, 996, 160, 1, 0, 0, 0, 997, 999, 7, 13, 0, 0, 998, 1000, 7, 12, 0, 0,
999, 998, 1, 0, 0, 0, 999, 1000, 1, 0, 0, 0, 1000, 1001, 1, 0, 0, 0, 1001,
1002, 3, 155, 77, 0, 1002, 162, 1, 0, 0, 0, 1003, 1004, 5, 92, 0, 0, 1004,
1019, 7, 14, 0, 0, 1005, 1006, 5, 92, 0, 0, 1006, 1008, 3, 139, 69, 0,
1007, 1009, 3, 139, 69, 0, 1008, 1007, 1, 0, 0, 0, 1008, 1009, 1, 0, 0,
0, 1009, 1011, 1, 0, 0, 0, 1010, 1012, 3, 139, 69, 0, 1011, 1010, 1, 0,
0, 0, 1011, 1012, 1, 0, 0, 0, 1012, 1019, 1, 0, 0, 0, 1013, 1014, 5, 92,
0, 0, 1014, 1015, 5, 120, 0, 0, 1015, 1016, 1, 0, 0, 0, 1016, 1019, 3,
159, 79, 0, 1017, 1019, 3, 145, 72, 0, 1018, 1003, 1, 0, 0, 0, 1018, 1005,
1, 0, 0, 0, 1018, 1013, 1, 0, 0, 0, 1018, 1017, 1, 0, 0, 0, 1019, 164,
1, 0, 0, 0, 1020, 1022, 7, 15, 0, 0, 1021, 1020, 1, 0, 0, 0, 1022, 1023,
1, 0, 0, 0, 1023, 1021, 1, 0, 0, 0, 1023, 1024, 1, 0, 0, 0, 1024, 1025,
1, 0, 0, 0, 1025, 1026, 6, 82, 0, 0, 1026, 166, 1, 0, 0, 0, 1027, 1029,
5, 13, 0, 0, 1028, 1030, 5, 10, 0, 0, 1029, 1028, 1, 0, 0, 0, 1029, 1030,
1, 0, 0, 0, 1030, 1033, 1, 0, 0, 0, 1031, 1033, 5, 10, 0, 0, 1032, 1027,
1, 0, 0, 0, 1032, 1031, 1, 0, 0, 0, 1033, 1034, 1, 0, 0, 0, 1034, 1035,
6, 83, 0, 0, 1035, 168, 1, 0, 0, 0, 66, 0, 207, 221, 243, 269, 304, 312,
328, 352, 363, 369, 374, 376, 407, 443, 479, 509, 547, 585, 611, 631, 653,
677, 699, 723, 751, 771, 800, 806, 810, 815, 817, 827, 831, 836, 839, 843,
848, 854, 859, 864, 869, 878, 887, 898, 904, 908, 914, 942, 946, 951, 957,
962, 969, 973, 980, 983, 990, 995, 999, 1008, 1011, 1018, 1023, 1029, 1032,
1, 6, 0, 0,
}
deserializer := antlr.NewATNDeserializer(nil)
staticData.atn = deserializer.Deserialize(staticData.serializedATN)
@ -549,13 +630,20 @@ const (
PlanLexerArrayContainsAll = 41
PlanLexerArrayContainsAny = 42
PlanLexerArrayLength = 43
PlanLexerBooleanConstant = 44
PlanLexerIntegerConstant = 45
PlanLexerFloatingConstant = 46
PlanLexerIdentifier = 47
PlanLexerMeta = 48
PlanLexerStringLiteral = 49
PlanLexerJSONIdentifier = 50
PlanLexerWhitespace = 51
PlanLexerNewline = 52
PlanLexerSTEuqals = 44
PlanLexerSTTouches = 45
PlanLexerSTOverlaps = 46
PlanLexerSTCrosses = 47
PlanLexerSTContains = 48
PlanLexerSTIntersects = 49
PlanLexerSTWithin = 50
PlanLexerBooleanConstant = 51
PlanLexerIntegerConstant = 52
PlanLexerFloatingConstant = 53
PlanLexerIdentifier = 54
PlanLexerMeta = 55
PlanLexerStringLiteral = 56
PlanLexerJSONIdentifier = 57
PlanLexerWhitespace = 58
PlanLexerNewline = 59
)

File diff suppressed because it is too large Load Diff

View File

@ -34,6 +34,9 @@ type PlanVisitor interface {
// Visit a parse tree produced by PlanParser#Identifier.
VisitIdentifier(ctx *IdentifierContext) interface{}
// Visit a parse tree produced by PlanParser#STIntersects.
VisitSTIntersects(ctx *STIntersectsContext) interface{}
// Visit a parse tree produced by PlanParser#Like.
VisitLike(ctx *LikeContext) interface{}
@ -55,6 +58,9 @@ type PlanVisitor interface {
// Visit a parse tree produced by PlanParser#Call.
VisitCall(ctx *CallContext) interface{}
// Visit a parse tree produced by PlanParser#STCrosses.
VisitSTCrosses(ctx *STCrossesContext) interface{}
// Visit a parse tree produced by PlanParser#ReverseRange.
VisitReverseRange(ctx *ReverseRangeContext) interface{}
@ -79,12 +85,21 @@ type PlanVisitor interface {
// Visit a parse tree produced by PlanParser#TextMatch.
VisitTextMatch(ctx *TextMatchContext) interface{}
// Visit a parse tree produced by PlanParser#STTouches.
VisitSTTouches(ctx *STTouchesContext) interface{}
// Visit a parse tree produced by PlanParser#STContains.
VisitSTContains(ctx *STContainsContext) interface{}
// Visit a parse tree produced by PlanParser#Term.
VisitTerm(ctx *TermContext) interface{}
// Visit a parse tree produced by PlanParser#JSONContains.
VisitJSONContains(ctx *JSONContainsContext) interface{}
// Visit a parse tree produced by PlanParser#STWithin.
VisitSTWithin(ctx *STWithinContext) interface{}
// Visit a parse tree produced by PlanParser#Range.
VisitRange(ctx *RangeContext) interface{}
@ -109,9 +124,15 @@ type PlanVisitor interface {
// Visit a parse tree produced by PlanParser#BitAnd.
VisitBitAnd(ctx *BitAndContext) interface{}
// Visit a parse tree produced by PlanParser#STEuqals.
VisitSTEuqals(ctx *STEuqalsContext) interface{}
// Visit a parse tree produced by PlanParser#IsNull.
VisitIsNull(ctx *IsNullContext) interface{}
// Visit a parse tree produced by PlanParser#Power.
VisitPower(ctx *PowerContext) interface{}
// Visit a parse tree produced by PlanParser#STOverlaps.
VisitSTOverlaps(ctx *STOverlapsContext) interface{}
}

View File

@ -1535,3 +1535,218 @@ func (v *ParserVisitor) VisitTemplateVariable(ctx *parser.TemplateVariableContex
},
}
}
func (v *ParserVisitor) VisitSTEuqals(ctx *parser.STEuqalsContext) interface{} {
childExpr, err := v.translateIdentifier(ctx.Identifier().GetText())
if err != nil {
return err
}
columnInfo := toColumnInfo(childExpr)
if columnInfo == nil ||
(!typeutil.IsGeometryType(columnInfo.GetDataType())) {
return fmt.Errorf(
"STEuqals operation are only supported on geometry fields now, got: %s", ctx.GetText())
}
element := ctx.StringLiteral().GetText()
if err := getError(element); err != nil {
return err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_GisfunctionFilterExpr{
GisfunctionFilterExpr: &planpb.GISFunctionFilterExpr{
ColumnInfo: columnInfo,
WktString: element[1 : len(element)-1],
Op: planpb.GISFunctionFilterExpr_Equals,
},
},
}
return &ExprWithType{
expr: expr,
dataType: schemapb.DataType_Bool,
}
}
func (v *ParserVisitor) VisitSTTouches(ctx *parser.STTouchesContext) interface{} {
childExpr, err := v.translateIdentifier(ctx.Identifier().GetText())
if err != nil {
return err
}
columnInfo := toColumnInfo(childExpr)
if columnInfo == nil ||
(!typeutil.IsGeometryType(columnInfo.GetDataType())) {
return fmt.Errorf(
"STTouches operation are only supported on geometry fields now, got: %s", ctx.GetText())
}
element := ctx.StringLiteral().GetText()
if err := getError(element); err != nil {
return err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_GisfunctionFilterExpr{
GisfunctionFilterExpr: &planpb.GISFunctionFilterExpr{
ColumnInfo: columnInfo,
WktString: element[1 : len(element)-1],
Op: planpb.GISFunctionFilterExpr_Touches,
},
},
}
return &ExprWithType{
expr: expr,
dataType: schemapb.DataType_Bool,
}
}
func (v *ParserVisitor) VisitSTOverlaps(ctx *parser.STOverlapsContext) interface{} {
childExpr, err := v.translateIdentifier(ctx.Identifier().GetText())
if err != nil {
return err
}
columnInfo := toColumnInfo(childExpr)
if columnInfo == nil ||
(!typeutil.IsGeometryType(columnInfo.GetDataType())) {
return fmt.Errorf(
"STOverlaps operation are only supported on geometry fields now, got: %s", ctx.GetText())
}
element := ctx.StringLiteral().GetText()
// log.Warn(element)
if err := getError(element); err != nil {
return err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_GisfunctionFilterExpr{
GisfunctionFilterExpr: &planpb.GISFunctionFilterExpr{
ColumnInfo: columnInfo,
WktString: element[1 : len(element)-1],
Op: planpb.GISFunctionFilterExpr_Overlaps,
},
},
}
return &ExprWithType{
expr: expr,
dataType: schemapb.DataType_Bool,
}
}
func (v *ParserVisitor) VisitSTCrosses(ctx *parser.STCrossesContext) interface{} {
childExpr, err := v.translateIdentifier(ctx.Identifier().GetText())
if err != nil {
return err
}
columnInfo := toColumnInfo(childExpr)
if columnInfo == nil ||
(!typeutil.IsGeometryType(columnInfo.GetDataType())) {
return fmt.Errorf(
"STCrosses operation are only supported on geometry fields now, got: %s", ctx.GetText())
}
element := ctx.StringLiteral().GetText()
// log.Warn(element)
if err := getError(element); err != nil {
return err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_GisfunctionFilterExpr{
GisfunctionFilterExpr: &planpb.GISFunctionFilterExpr{
ColumnInfo: columnInfo,
WktString: element[1 : len(element)-1],
Op: planpb.GISFunctionFilterExpr_Crosses,
},
},
}
return &ExprWithType{
expr: expr,
dataType: schemapb.DataType_Bool,
}
}
func (v *ParserVisitor) VisitSTContains(ctx *parser.STContainsContext) interface{} {
childExpr, err := v.translateIdentifier(ctx.Identifier().GetText())
if err != nil {
return err
}
columnInfo := toColumnInfo(childExpr)
if columnInfo == nil ||
(!typeutil.IsGeometryType(columnInfo.GetDataType())) {
return fmt.Errorf(
"STContains operation are only supported on geometry fields now, got: %s", ctx.GetText())
}
element := ctx.StringLiteral().GetText() // the wkt input
// log.Warn(element)
if err := getError(element); err != nil {
return err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_GisfunctionFilterExpr{
GisfunctionFilterExpr: &planpb.GISFunctionFilterExpr{
ColumnInfo: columnInfo,
WktString: element[1 : len(element)-1],
Op: planpb.GISFunctionFilterExpr_Contains,
},
},
}
return &ExprWithType{
expr: expr,
dataType: schemapb.DataType_Bool,
}
}
func (v *ParserVisitor) VisitSTIntersects(ctx *parser.STIntersectsContext) interface{} {
childExpr, err := v.translateIdentifier(ctx.Identifier().GetText())
if err != nil {
return err
}
columnInfo := toColumnInfo(childExpr)
if columnInfo == nil ||
(!typeutil.IsGeometryType(columnInfo.GetDataType())) {
return fmt.Errorf(
"STIntersects operation are only supported on geometry fields now, got: %s", ctx.GetText())
}
element := ctx.StringLiteral().GetText() // the wkt input
// log.Warn(element)
if err := getError(element); err != nil {
return err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_GisfunctionFilterExpr{
GisfunctionFilterExpr: &planpb.GISFunctionFilterExpr{
ColumnInfo: columnInfo,
WktString: element[1 : len(element)-1],
Op: planpb.GISFunctionFilterExpr_Intersects,
},
},
}
return &ExprWithType{
expr: expr,
dataType: schemapb.DataType_Bool,
}
}
func (v *ParserVisitor) VisitSTWithin(ctx *parser.STWithinContext) interface{} {
childExpr, err := v.translateIdentifier(ctx.Identifier().GetText())
if err != nil {
return err
}
columnInfo := toColumnInfo(childExpr)
if columnInfo == nil ||
(!typeutil.IsGeometryType(columnInfo.GetDataType())) {
return fmt.Errorf(
"STWithin operation are only supported on geometry fields now, got: %s", ctx.GetText())
}
element := ctx.StringLiteral().GetText() // the wkt input
// log.Warn(element)
if err := getError(element); err != nil {
return err
}
expr := &planpb.Expr{
Expr: &planpb.Expr_GisfunctionFilterExpr{
GisfunctionFilterExpr: &planpb.GISFunctionFilterExpr{
ColumnInfo: columnInfo,
WktString: element[1 : len(element)-1],
Op: planpb.GISFunctionFilterExpr_Within,
},
},
}
return &ExprWithType{
expr: expr,
dataType: schemapb.DataType_Bool,
}
}

View File

@ -156,6 +156,11 @@ func getTargetType(lDataType, rDataType schemapb.DataType) (schemapb.DataType, e
return schemapb.DataType_Int64, nil
}
}
if typeutil.IsGeometryType(lDataType) {
if typeutil.IsGeometryType(rDataType) || typeutil.IsJSONType(rDataType) {
return schemapb.DataType_Geometry, nil
}
}
if typeutil.IsFloatingType(lDataType) {
if typeutil.IsJSONType(rDataType) || typeutil.IsArithmetic(rDataType) {
return schemapb.DataType_Double, nil

View File

@ -47,6 +47,7 @@ func TestInsertTask_CheckAligned(t *testing.T) {
float16VectorFieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_Float16Vector}
bfloat16VectorFieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_BFloat16Vector}
varCharFieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_VarChar}
geometryFieldSchema := &schemapb.FieldSchema{DataType: schemapb.DataType_Geometry}
numRows := 20
dim := 128
@ -78,6 +79,7 @@ func TestInsertTask_CheckAligned(t *testing.T) {
float16VectorFieldSchema,
bfloat16VectorFieldSchema,
varCharFieldSchema,
geometryFieldSchema,
},
},
}
@ -97,6 +99,7 @@ func TestInsertTask_CheckAligned(t *testing.T) {
newFloat16VectorFieldData("Float16Vector", numRows, dim),
newBFloat16VectorFieldData("BFloat16Vector", numRows, dim),
newScalarFieldData(varCharFieldSchema, "VarChar", numRows),
newScalarFieldData(geometryFieldSchema, "Geometry", numRows),
}
err = case2.insertMsg.CheckAligned()
assert.NoError(t, err)

View File

@ -568,6 +568,10 @@ func (t *queryTask) PostExecute(ctx context.Context) error {
log.Warn("fail to reduce query result", zap.Error(err))
return err
}
if err := validateGeometryFieldSearchResult(&t.result.FieldsData); err != nil {
log.Warn("fail to validate geometry field search result", zap.Error(err))
return err
}
t.result.OutputFields = t.userOutputFields
primaryFieldSchema, err := t.schema.GetPkField()
if err != nil {

View File

@ -790,6 +790,10 @@ func (t *searchTask) PostExecute(ctx context.Context) error {
}
}
if err := validateGeometryFieldSearchResult(&t.result.Results.FieldsData); err != nil {
log.Warn("fail to validate geometry field search result", zap.Error(err))
return err
}
// reduce done, get final result
limit := t.SearchRequest.GetTopk() - t.SearchRequest.GetOffset()
resultSizeInsufficient := false

View File

@ -70,6 +70,7 @@ const (
testBinaryVecField = "bvec"
testFloat16VecField = "f16vec"
testBFloat16VecField = "bf16vec"
testGeometryField = "geometry"
testVecDim = 128
testMaxVarCharLength = 100
)
@ -85,6 +86,7 @@ func genCollectionSchema(collectionName string) *schemapb.CollectionSchema {
testBinaryVecField,
testFloat16VecField,
testBFloat16VecField,
testGeometryField,
testVecDim,
collectionName)
}
@ -233,6 +235,7 @@ func constructCollectionSchemaByDataType(collectionName string, fieldName2DataTy
func constructCollectionSchemaWithAllType(
boolField, int32Field, int64Field, floatField, doubleField string,
floatVecField, binaryVecField, float16VecField, bfloat16VecField string,
geometryField string,
dim int,
collectionName string,
) *schemapb.CollectionSchema {
@ -346,6 +349,16 @@ func constructCollectionSchemaWithAllType(
IndexParams: nil,
AutoID: false,
}
g := &schemapb.FieldSchema{
FieldID: 0,
Name: geometryField,
IsPrimaryKey: false,
Description: "",
DataType: schemapb.DataType_Geometry,
TypeParams: nil,
IndexParams: nil,
AutoID: false,
}
if enableMultipleVectorFields {
return &schemapb.CollectionSchema{
@ -362,6 +375,7 @@ func constructCollectionSchemaWithAllType(
bVec,
f16Vec,
bf16Vec,
g,
},
}
}
@ -378,6 +392,7 @@ func constructCollectionSchemaWithAllType(
d,
fVec,
// bVec,
g,
},
}
}

View File

@ -5,6 +5,8 @@ import (
"math"
"reflect"
"github.com/twpayne/go-geom/encoding/wkb"
"github.com/twpayne/go-geom/encoding/wkt"
"go.uber.org/zap"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
@ -51,6 +53,52 @@ func withMaxCapCheck() validateOption {
}
}
func validateGeometryFieldSearchResult(array *[]*schemapb.FieldData) error {
if array == nil {
log.Warn("geometry field search result is nil")
return nil
}
for idx, fieldData := range *array {
if fieldData.Type == schemapb.DataType_Geometry {
wkbArray := fieldData.GetScalars().GetGeometryData().GetData()
wktArray := make([]string, len(wkbArray))
for i, data := range wkbArray {
geomT, err := wkb.Unmarshal(data)
if err != nil {
log.Warn("translate the wkb format search result into geometry failed")
return err
}
// now remove MaxDecimalDigits limit
wktStr, err := wkt.Marshal(geomT)
if err != nil {
log.Warn("translate the geomery into its wkt failed")
return err
}
wktArray[i] = wktStr
}
// modify the field data
(*array)[idx] = &schemapb.FieldData{
Type: fieldData.GetType(),
FieldName: fieldData.GetFieldName(),
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryWktData{
GeometryWktData: &schemapb.GeometryWktArray{
Data: wktArray,
},
},
},
},
FieldId: fieldData.GetFieldId(),
IsDynamic: fieldData.GetIsDynamic(),
}
}
}
return nil
}
func (v *validateUtil) apply(opts ...validateOption) {
for _, opt := range opts {
opt(v)
@ -92,6 +140,10 @@ func (v *validateUtil) Validate(data []*schemapb.FieldData, helper *typeutil.Sch
if err := v.checkVarCharFieldData(field, fieldSchema); err != nil {
return err
}
case schemapb.DataType_Geometry:
if err := v.checkGeometryFieldData(field, fieldSchema); err != nil {
return err
}
case schemapb.DataType_JSON:
if err := v.checkJSONFieldData(field, fieldSchema); err != nil {
return err
@ -368,6 +420,13 @@ func (v *validateUtil) fillWithNullValue(field *schemapb.FieldData, fieldSchema
}
}
case *schemapb.ScalarField_GeometryData:
if fieldSchema.GetNullable() {
sd.GeometryData.Data, err = fillWithNullValueImpl(sd.GeometryData.Data, field.GetValidData())
if err != nil {
return err
}
}
default:
return merr.WrapErrParameterInvalidMsg(fmt.Sprintf("undefined data type:%s", field.Type.String()))
}
@ -467,6 +526,17 @@ func (v *validateUtil) fillWithDefaultValue(field *schemapb.FieldData, fieldSche
return err
}
case *schemapb.ScalarField_GeometryData:
if len(field.GetValidData()) != numRows {
msg := fmt.Sprintf("the length of valid_data of field(%s) is wrong", field.GetFieldName())
return merr.WrapErrParameterInvalid(numRows, len(field.GetValidData()), msg)
}
defaultValue := fieldSchema.GetDefaultValue().GetBytesData()
sd.GeometryData.Data, err = fillWithDefaultValueImpl(sd.GeometryData.Data, defaultValue, field.GetValidData())
if err != nil {
return err
}
default:
return merr.WrapErrParameterInvalidMsg(fmt.Sprintf("undefined data type:%s", field.Type.String()))
}
@ -636,6 +706,44 @@ func (v *validateUtil) checkVarCharFieldData(field *schemapb.FieldData, fieldSch
return nil
}
func (v *validateUtil) checkGeometryFieldData(field *schemapb.FieldData, fieldSchema *schemapb.FieldSchema) error {
geometryArray := field.GetScalars().GetGeometryWktData().GetData()
wkbArray := make([][]byte, len(geometryArray))
if geometryArray == nil && fieldSchema.GetDefaultValue() == nil && !fieldSchema.GetNullable() {
msg := fmt.Sprintf("geometry field '%v' is illegal, array type mismatch", field.GetFieldName())
return merr.WrapErrParameterInvalid("need geometry array", "got nil", msg)
}
for index, wktdata := range geometryArray {
// ignore parsed geom, the check is during insert task pre execute,so geo data became wkb
// fmt.Println(strings.Trim(string(wktdata), "\""))
geomT, err := wkt.Unmarshal(wktdata)
if err != nil {
log.Warn("insert invalid Geometry data!! The wkt data has errors", zap.Error(err))
return merr.WrapErrIoFailedReason(err.Error())
}
wkbArray[index], err = wkb.Marshal(geomT, wkb.NDR)
if err != nil {
log.Warn("insert invalid Geometry data!! Transform to wkb failed, has errors", zap.Error(err))
return merr.WrapErrIoFailedReason(err.Error())
}
}
// replace the field data with wkb data array
*field = schemapb.FieldData{
Type: field.GetType(),
FieldName: field.GetFieldName(),
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{GeometryData: &schemapb.GeometryArray{Data: wkbArray}},
},
},
FieldId: field.GetFieldId(),
IsDynamic: field.GetIsDynamic(),
ValidData: field.GetValidData(),
}
return nil
}
func (v *validateUtil) checkJSONFieldData(field *schemapb.FieldData, fieldSchema *schemapb.FieldSchema) error {
jsonArray := field.GetScalars().GetJsonData().GetData()
if jsonArray == nil && fieldSchema.GetDefaultValue() == nil && !fieldSchema.GetNullable() {
@ -896,7 +1004,7 @@ func newValidateUtil(opts ...validateOption) *validateUtil {
}
func ValidateAutoIndexMmapConfig(isVectorField bool, indexParams map[string]string) error {
return common.ValidateAutoIndexMmapConfig(Params.AutoIndexConfig.Enable.GetAsBool(), isVectorField, indexParams)
return common.ValidateAutoIndexMmapConfig(paramtable.Get().AutoIndexConfig.Enable.GetAsBool(), isVectorField, indexParams)
}
func wasBm25FunctionInputField(coll *schemapb.CollectionSchema, field *schemapb.FieldSchema) bool {

View File

@ -368,6 +368,16 @@ func AddFieldDataToPayload(eventWriter *insertEventWriter, dataType schemapb.Dat
return err
}
}
case schemapb.DataType_Geometry:
for i, singleGeometry := range singleData.(*GeometryFieldData).Data {
isValid := true
if len(singleData.(*GeometryFieldData).ValidData) != 0 {
isValid = singleData.(*GeometryFieldData).ValidData[i]
}
if err = eventWriter.AddOneGeometryToPayload(singleGeometry, isValid); err != nil {
return err
}
}
case schemapb.DataType_BinaryVector:
if err = eventWriter.AddBinaryVectorToPayload(singleData.(*BinaryVectorFieldData).Data, singleData.(*BinaryVectorFieldData).Dim); err != nil {
return err
@ -601,6 +611,17 @@ func AddInsertData(dataType schemapb.DataType, data interface{}, insertData *Ins
jsonFieldData.ValidData = append(jsonFieldData.ValidData, validData...)
insertData.Data[fieldID] = jsonFieldData
return len(singleData), nil
case schemapb.DataType_Geometry:
singleData := data.([][]byte)
if fieldData == nil {
fieldData = &GeometryFieldData{Data: make([][]byte, 0, rowNum)}
}
geometryFieldData := fieldData.(*GeometryFieldData)
geometryFieldData.Data = append(geometryFieldData.Data, singleData...)
geometryFieldData.ValidData = append(geometryFieldData.ValidData, validData...)
insertData.Data[fieldID] = geometryFieldData
return len(singleData), nil
case schemapb.DataType_BinaryVector:
singleData := data.([]byte)

View File

@ -114,6 +114,9 @@ func (ds *DataSorter) Swap(i, j int) {
case schemapb.DataType_JSON:
data := singleData.(*JSONFieldData).Data
data[i], data[j] = data[j], data[i]
case schemapb.DataType_Geometry:
data := singleData.(*GeometryFieldData).Data
data[i], data[j] = data[j], data[i]
case schemapb.DataType_SparseFloatVector:
fieldData := singleData.(*SparseFloatVectorFieldData)
fieldData.Contents[i], fieldData.Contents[j] = fieldData.Contents[j], fieldData.Contents[i]

View File

@ -309,6 +309,16 @@ func NewFieldData(dataType schemapb.DataType, fieldSchema *schemapb.FieldSchema,
data.ValidData = make([]bool, 0, cap)
}
return data, nil
case schemapb.DataType_Geometry:
data := &GeometryFieldData{
Data: make([][]byte, 0, cap),
Nullable: fieldSchema.GetNullable(),
}
if fieldSchema.GetNullable() {
data.ValidData = make([]bool, 0, cap)
}
return data, nil
case schemapb.DataType_Array:
data := &ArrayFieldData{
Data: make([]*schemapb.ScalarField, 0, cap),
@ -386,6 +396,11 @@ type JSONFieldData struct {
ValidData []bool
Nullable bool
}
type GeometryFieldData struct {
Data [][]byte
ValidData []bool
Nullable bool
}
type BinaryVectorFieldData struct {
Data []byte
Dim int
@ -428,6 +443,7 @@ func (data *DoubleFieldData) RowNum() int { return len(data.Data) }
func (data *StringFieldData) RowNum() int { return len(data.Data) }
func (data *ArrayFieldData) RowNum() int { return len(data.Data) }
func (data *JSONFieldData) RowNum() int { return len(data.Data) }
func (data *GeometryFieldData) RowNum() int { return len(data.Data) }
func (data *BinaryVectorFieldData) RowNum() int { return len(data.Data) * 8 / data.Dim }
func (data *FloatVectorFieldData) RowNum() int { return len(data.Data) / data.Dim }
func (data *Float16VectorFieldData) RowNum() int { return len(data.Data) / 2 / data.Dim }
@ -507,6 +523,13 @@ func (data *JSONFieldData) GetRow(i int) any {
return data.Data[i]
}
func (data *GeometryFieldData) GetRow(i int) any {
if data.GetNullable() && !data.ValidData[i] {
return nil
}
return data.Data[i]
}
func (data *BinaryVectorFieldData) GetRow(i int) any {
return data.Data[i*data.Dim/8 : (i+1)*data.Dim/8]
}
@ -537,6 +560,7 @@ func (data *DoubleFieldData) GetDataRows() any { return data.Data }
func (data *StringFieldData) GetDataRows() any { return data.Data }
func (data *ArrayFieldData) GetDataRows() any { return data.Data }
func (data *JSONFieldData) GetDataRows() any { return data.Data }
func (data *GeometryFieldData) GetDataRows() any { return data.Data }
func (data *BinaryVectorFieldData) GetDataRows() any { return data.Data }
func (data *FloatVectorFieldData) GetDataRows() any { return data.Data }
func (data *Float16VectorFieldData) GetDataRows() any { return data.Data }
@ -714,6 +738,23 @@ func (data *JSONFieldData) AppendRow(row interface{}) error {
return nil
}
func (data *GeometryFieldData) AppendRow(row interface{}) error {
if data.GetNullable() && row == nil {
data.Data = append(data.Data, make([][]byte, 1)...)
data.ValidData = append(data.ValidData, false)
return nil
}
v, ok := row.([]byte)
if !ok {
return merr.WrapErrParameterInvalid("[]byte", row, "Wrong row type")
}
if data.GetNullable() {
data.ValidData = append(data.ValidData, true)
}
data.Data = append(data.Data, v)
return nil
}
func (data *BinaryVectorFieldData) AppendRow(row interface{}) error {
v, ok := row.([]byte)
if !ok || len(v) != data.Dim/8 {
@ -846,6 +887,14 @@ func (data *JSONFieldData) AppendRows(dataRows interface{}, validDataRows interf
return data.AppendValidDataRows(validDataRows)
}
func (data *GeometryFieldData) AppendRows(dataRows interface{}, validDataRows interface{}) error {
err := data.AppendDataRows(dataRows)
if err != nil {
return err
}
return data.AppendValidDataRows(validDataRows)
}
// AppendDataRows appends FLATTEN vectors to field data.
func (data *BinaryVectorFieldData) AppendRows(dataRows interface{}, validDataRows interface{}) error {
err := data.AppendDataRows(dataRows)
@ -980,6 +1029,15 @@ func (data *JSONFieldData) AppendDataRows(rows interface{}) error {
return nil
}
func (data *GeometryFieldData) AppendDataRows(rows interface{}) error {
v, ok := rows.([][]byte)
if !ok {
return merr.WrapErrParameterInvalid("[][]byte", rows, "Wrong rows type")
}
data.Data = append(data.Data, v...)
return nil
}
// AppendDataRows appends FLATTEN vectors to field data.
func (data *BinaryVectorFieldData) AppendDataRows(rows interface{}) error {
v, ok := rows.([]byte)
@ -1164,6 +1222,18 @@ func (data *JSONFieldData) AppendValidDataRows(rows interface{}) error {
return nil
}
func (data *GeometryFieldData) AppendValidDataRows(rows interface{}) error {
if rows == nil {
return nil
}
v, ok := rows.([]bool)
if !ok {
return merr.WrapErrParameterInvalid("[]bool", rows, "Wrong rows type")
}
data.ValidData = append(data.ValidData, v...)
return nil
}
// AppendValidDataRows appends FLATTEN vectors to field data.
func (data *BinaryVectorFieldData) AppendValidDataRows(rows interface{}) error {
if rows != nil {
@ -1282,6 +1352,10 @@ func (data *DoubleFieldData) GetDataType() schemapb.DataType { return schemapb.D
func (data *StringFieldData) GetDataType() schemapb.DataType { return data.DataType }
func (data *ArrayFieldData) GetDataType() schemapb.DataType { return schemapb.DataType_Array }
func (data *JSONFieldData) GetDataType() schemapb.DataType { return schemapb.DataType_JSON }
func (data *GeometryFieldData) GetDataType() schemapb.DataType {
return schemapb.DataType_Geometry
}
func (data *BinaryVectorFieldData) GetDataType() schemapb.DataType {
return schemapb.DataType_BinaryVector
}
@ -1347,6 +1421,15 @@ func (data *JSONFieldData) GetMemorySize() int {
return size + binary.Size(data.ValidData) + binary.Size(data.Nullable)
}
func (data *GeometryFieldData) GetMemorySize() int {
var size int
// what's the meaning of 16?
for _, val := range data.Data {
size += len(val) + 16
}
return size + binary.Size(data.ValidData) + binary.Size(data.Nullable)
}
func (data *BoolFieldData) GetRowSize(i int) int { return 1 }
func (data *Int8FieldData) GetRowSize(i int) int { return 1 }
func (data *Int16FieldData) GetRowSize(i int) int { return 2 }
@ -1360,6 +1443,7 @@ func (data *Float16VectorFieldData) GetRowSize(i int) int { return data.Dim * 2
func (data *BFloat16VectorFieldData) GetRowSize(i int) int { return data.Dim * 2 }
func (data *StringFieldData) GetRowSize(i int) int { return len(data.Data[i]) + 16 }
func (data *JSONFieldData) GetRowSize(i int) int { return len(data.Data[i]) + 16 }
func (data *GeometryFieldData) GetRowSize(i int) int { return len(data.Data[i]) + 16 }
func (data *ArrayFieldData) GetRowSize(i int) int {
switch data.ElementType {
case schemapb.DataType_Bool:
@ -1445,3 +1529,7 @@ func (data *ArrayFieldData) GetNullable() bool {
func (data *JSONFieldData) GetNullable() bool {
return data.Nullable
}
func (data *GeometryFieldData) GetNullable() bool {
return data.Nullable
}

View File

@ -38,6 +38,7 @@ type PayloadWriterInterface interface {
AddOneStringToPayload(msgs string, isValid bool) error
AddOneArrayToPayload(msg *schemapb.ScalarField, isValid bool) error
AddOneJSONToPayload(msg []byte, isValid bool) error
AddOneGeometryToPayload(msg []byte, isValid bool) error
AddBinaryVectorToPayload(binVec []byte, dim int) error
AddFloatVectorToPayload(binVec []float32, dim int) error
AddFloat16VectorToPayload(binVec []byte, dim int) error
@ -65,6 +66,7 @@ type PayloadReaderInterface interface {
GetStringFromPayload() ([]string, []bool, error)
GetArrayFromPayload() ([]*schemapb.ScalarField, []bool, error)
GetJSONFromPayload() ([][]byte, []bool, error)
GetGeometryFromPayload() ([][]byte, []bool, error)
GetBinaryVectorFromPayload() ([]byte, int, error)
GetFloat16VectorFromPayload() ([]byte, int, error)
GetBFloat16VectorFromPayload() ([]byte, int, error)

View File

@ -98,6 +98,9 @@ func (r *PayloadReader) GetDataFromPayload() (interface{}, []bool, int, error) {
case schemapb.DataType_JSON:
val, validData, err := r.GetJSONFromPayload()
return val, validData, 0, err
case schemapb.DataType_Geometry:
val, validData, err := r.GetGeometryFromPayload()
return val, validData, 0, err
default:
return nil, nil, 0, merr.WrapErrParameterInvalidMsg("unknown type")
}
@ -432,6 +435,25 @@ func (r *PayloadReader) GetJSONFromPayload() ([][]byte, []bool, error) {
return value, nil, nil
}
func (r *PayloadReader) GetGeometryFromPayload() ([][]byte, []bool, error) {
if r.colType != schemapb.DataType_Geometry {
return nil, nil, merr.WrapErrParameterInvalidMsg(fmt.Sprintf("failed to get Geometry from datatype %v", r.colType.String()))
}
if r.nullable {
return readNullableByteAndConvert(r, func(bytes []byte) []byte {
return bytes
})
}
value, err := readByteAndConvert(r, func(bytes parquet.ByteArray) []byte {
return bytes
})
if err != nil {
return nil, nil, err
}
return value, nil, nil
}
func (r *PayloadReader) GetByteArrayDataSet() (*DataSet[parquet.ByteArray, *file.ByteArrayColumnChunkReader], error) {
if r.colType != schemapb.DataType_String && r.colType != schemapb.DataType_VarChar {
return nil, fmt.Errorf("failed to get string from datatype %v", r.colType.String())

View File

@ -206,6 +206,25 @@ func (w *NativePayloadWriter) AddDataToPayload(data interface{}, validData []boo
isValid = validData[0]
}
return w.AddOneJSONToPayload(val, isValid)
case schemapb.DataType_Geometry:
val, ok := data.([]byte)
if !ok {
return merr.WrapErrParameterInvalidMsg("incorrect data type")
}
isValid := true
if len(validData) > 1 {
return merr.WrapErrParameterInvalidMsg("wrong input length when add data to payload")
}
if len(validData) == 0 && w.nullable {
return merr.WrapErrParameterInvalidMsg("need pass valid_data when nullable==true")
}
if len(validData) == 1 {
if !w.nullable {
return merr.WrapErrParameterInvalidMsg("no need pass valid_data when nullable==false")
}
isValid = validData[0]
}
return w.AddOneGeometryToPayload(val, isValid)
case schemapb.DataType_BinaryVector:
val, ok := data.([]byte)
if !ok {
@ -546,6 +565,29 @@ func (w *NativePayloadWriter) AddOneJSONToPayload(data []byte, isValid bool) err
return nil
}
func (w *NativePayloadWriter) AddOneGeometryToPayload(data []byte, isValid bool) error {
if w.finished {
return errors.New("can't append data to finished geometry payload")
}
if !w.nullable && !isValid {
return merr.WrapErrParameterInvalidMsg("not support null when nullable is false")
}
builder, ok := w.builder.(*array.BinaryBuilder)
if !ok {
return errors.New("failed to cast geometryBuilder")
}
if !isValid {
builder.AppendNull()
} else {
builder.Append(data)
}
return nil
}
func (w *NativePayloadWriter) AddBinaryVectorToPayload(data []byte, dim int) error {
if w.finished {
return errors.New("can't append data to finished binary vector payload")
@ -752,6 +794,8 @@ func milvusDataTypeToArrowType(dataType schemapb.DataType, dim int) arrow.DataTy
return &arrow.BinaryType{}
case schemapb.DataType_JSON:
return &arrow.BinaryType{}
case schemapb.DataType_Geometry:
return &arrow.BinaryType{}
case schemapb.DataType_FloatVector:
return &arrow.FixedSizeBinaryType{
ByteWidth: dim * 4,

View File

@ -21,6 +21,8 @@ import (
"os"
"github.com/cockroachdb/errors"
"github.com/twpayne/go-geom/encoding/wkb"
"github.com/twpayne/go-geom/encoding/wkt"
"golang.org/x/exp/mmap"
"google.golang.org/protobuf/proto"
@ -368,6 +370,24 @@ func printPayloadValues(colType schemapb.DataType, reader PayloadReaderInterface
for i, v := range valids {
fmt.Printf("\t\t%d : %v\n", i, v)
}
// print the wkb bytes
case schemapb.DataType_Geometry:
rows, err := reader.GetPayloadLengthFromReader()
if err != nil {
return err
}
val, valids, err := reader.GetGeometryFromPayload()
if err != nil {
return err
}
for i := 0; i < rows; i++ {
geomT, _ := wkb.Unmarshal(val[i])
wktStr, _ := wkt.Marshal(geomT)
fmt.Printf("\t\t%d : %s\n", i, wktStr)
}
for i, v := range valids {
fmt.Printf("\t\t%d : %v\n", i, v)
}
case schemapb.DataType_SparseFloatVector:
sparseData, _, err := reader.GetSparseFloatVectorFromPayload()
if err != nil {

View File

@ -210,6 +210,13 @@ func TestPrintBinlogFiles(t *testing.T) {
{Key: common.DimKey, Value: "4"},
},
},
{
FieldID: 113,
Name: "field_geometry",
IsPrimaryKey: false,
Description: "description_15",
DataType: schemapb.DataType_Geometry,
},
},
},
}
@ -268,6 +275,13 @@ func TestPrintBinlogFiles(t *testing.T) {
Data: []byte("12345678"),
Dim: 4,
},
113: &GeometryFieldData{
Data: [][]byte{
// POINT (30.123 -10.456) and LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
},
},
},
}
@ -325,6 +339,13 @@ func TestPrintBinlogFiles(t *testing.T) {
Data: []byte("abcdefgh"),
Dim: 4,
},
113: &GeometryFieldData{
Data: [][]byte{
// POINT (30.123 -10.456) and LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
},
},
},
}
firstBlobs, err := insertCodec.Serialize(1, 1, insertDataFirst)

View File

@ -416,6 +416,7 @@ var serdeMap = func() map[schemapb.DataType]serdeEntry {
m[schemapb.DataType_Array] = byteEntry
m[schemapb.DataType_JSON] = byteEntry
m[schemapb.DataType_Geometry] = byteEntry
fixedSizeDeserializer := func(a arrow.Array, i int) (any, bool) {
if a.IsNull(i) {

View File

@ -673,6 +673,13 @@ func ColumnBasedInsertMsgToInsertData(msg *msgstream.InsertMsg, collSchema *sche
Data: lo.Map(srcData, func(v []byte, _ int) []byte { return v }),
ValidData: lo.Map(validData, func(v bool, _ int) bool { return v }),
}
case schemapb.DataType_Geometry:
srcData := srcField.GetScalars().GetGeometryData().GetData()
validData := srcField.GetValidData()
fieldData = &GeometryFieldData{
Data: lo.Map(srcData, func(v []byte, _ int) []byte { return v }),
ValidData: lo.Map(validData, func(v bool, _ int) bool { return v }),
}
default:
return nil, merr.WrapErrServiceInternal("data type not handled", field.GetDataType().String())
@ -1193,6 +1200,21 @@ func TransferInsertDataToInsertRecord(insertData *InsertData) (*segcorepb.Insert
},
ValidData: rawData.ValidData,
}
case *GeometryFieldData:
fieldData = &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldId: fieldID,
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: rawData.Data,
},
},
},
},
ValidData: rawData.ValidData,
}
case *FloatVectorFieldData:
fieldData = &schemapb.FieldData{
Type: schemapb.DataType_FloatVector,

View File

@ -1003,7 +1003,7 @@ func genColumnBasedInsertMsg(schema *schemapb.CollectionSchema, numRows, fVecDim
case schemapb.DataType_JSON:
data := testutils.GenerateBytesArray(numRows)
f := &schemapb.FieldData{
Type: schemapb.DataType_Array,
Type: schemapb.DataType_JSON,
FieldName: field.GetName(),
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
@ -1023,6 +1023,29 @@ func genColumnBasedInsertMsg(schema *schemapb.CollectionSchema, numRows, fVecDim
for _, d := range data {
columns[idx] = append(columns[idx], d)
}
case schemapb.DataType_Geometry:
data := testutils.GenerateGeometryWktArray(numRows)
f := &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: field.GetName(),
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: data,
},
},
},
},
FieldId: field.FieldID,
}
if field.GetNullable() {
f.ValidData = testutils.GenerateBoolArray(numRows)
}
msg.FieldsData = append(msg.FieldsData, f)
for _, d := range data {
columns[idx] = append(columns[idx], d)
}
}
}

View File

@ -160,6 +160,12 @@ func (c *FieldReader) Next(count int64) (any, any, error) {
}
data, err := ReadJSONData(c, count)
return data, nil, err
case schemapb.DataType_Geometry:
if c.field.GetNullable() {
return ReadNullableGeometryData(c, count)
}
data, err := ReadGeometryData(c, count)
return data, nil, err
case schemapb.DataType_BinaryVector, schemapb.DataType_Float16Vector, schemapb.DataType_BFloat16Vector:
// vector not support default_value
if c.field.GetNullable() {
@ -704,6 +710,42 @@ func ReadNullableJSONData(pcr *FieldReader, count int64) (any, []bool, error) {
return byteArr, validData, nil
}
func ReadNullableGeometryData(pcr *FieldReader, count int64) (any, []bool, error) {
// Geometry field read data from string array Parquet
data, validData, err := ReadNullableStringData(pcr, count)
if err != nil {
return nil, nil, err
}
if data == nil {
return nil, nil, nil
}
byteArr := make([][]byte, 0)
for i, str := range data.([]string) {
if !validData[i] {
byteArr = append(byteArr, []byte(nil))
continue
}
byteArr = append(byteArr, []byte(str))
}
return byteArr, validData, nil
}
func ReadGeometryData(pcr *FieldReader, count int64) (any, error) {
// Geometry field read data from string array Parquet
data, err := ReadStringData(pcr, count)
if err != nil {
return nil, err
}
if data == nil {
return nil, nil
}
byteArr := make([][]byte, 0)
for _, str := range data.([]string) {
byteArr = append(byteArr, []byte(str))
}
return byteArr, nil
}
func ReadBinaryData(pcr *FieldReader, count int64) (any, error) {
dataType := pcr.field.GetDataType()
chunked, err := pcr.columnReader.NextBatch(count)

View File

@ -529,6 +529,7 @@ func (s *ReaderSuite) TestReadScalarFields() {
s.run(schemapb.DataType_String, schemapb.DataType_None, false, 0)
s.run(schemapb.DataType_VarChar, schemapb.DataType_None, false, 0)
s.run(schemapb.DataType_JSON, schemapb.DataType_None, false, 0)
s.run(schemapb.DataType_Geometry, schemapb.DataType_None, false, 0)
s.run(schemapb.DataType_Array, schemapb.DataType_Bool, false, 0)
s.run(schemapb.DataType_Array, schemapb.DataType_Int8, false, 0)
@ -567,6 +568,7 @@ func (s *ReaderSuite) TestReadScalarFields() {
s.run(schemapb.DataType_String, schemapb.DataType_None, true, 100)
s.run(schemapb.DataType_VarChar, schemapb.DataType_None, true, 100)
s.run(schemapb.DataType_JSON, schemapb.DataType_None, true, 100)
s.run(schemapb.DataType_Geometry, schemapb.DataType_None, true, 100)
s.run(schemapb.DataType_Array, schemapb.DataType_Bool, true, 100)
s.run(schemapb.DataType_Array, schemapb.DataType_Int8, true, 100)

View File

@ -216,6 +216,8 @@ func convertToArrowDataType(field *schemapb.FieldSchema, isArray bool) (arrow.Da
return &arrow.StringType{}, nil
case schemapb.DataType_JSON:
return &arrow.StringType{}, nil
case schemapb.DataType_Geometry:
return &arrow.StringType{}, nil
case schemapb.DataType_Array:
elemType, err := convertToArrowDataType(field, true)
if err != nil {

View File

@ -21,6 +21,7 @@ func Test_INVERTEDIndexChecker(t *testing.T) {
assert.NoError(t, c.CheckValidDataType(IndexINVERTED, &schemapb.FieldSchema{DataType: schemapb.DataType_Array}))
assert.NoError(t, c.CheckValidDataType(IndexINVERTED, &schemapb.FieldSchema{DataType: schemapb.DataType_JSON}))
assert.Error(t, c.CheckValidDataType(IndexINVERTED, &schemapb.FieldSchema{DataType: schemapb.DataType_Geometry}))
assert.Error(t, c.CheckValidDataType(IndexINVERTED, &schemapb.FieldSchema{DataType: schemapb.DataType_FloatVector}))
}

View File

@ -176,6 +176,9 @@ func CreateInsertData(schema *schemapb.CollectionSchema, rows int, nullPercent .
insertData.Data[f.FieldID].AppendDataRows(testutils.GenerateStringArray(rows))
case schemapb.DataType_JSON:
insertData.Data[f.FieldID].AppendDataRows(testutils.GenerateJSONArray(rows))
case schemapb.DataType_Geometry:
// wkb bytes array
insertData.Data[f.FieldID].AppendDataRows(testutils.GenerateGeometryArray(rows))
case schemapb.DataType_Array:
switch f.GetElementType() {
case schemapb.DataType_Bool:
@ -528,6 +531,14 @@ func BuildArrayData(schema *schemapb.CollectionSchema, insertData *storage.Inser
return string(bs)
}), validData)
columns = append(columns, builder.NewStringArray())
case schemapb.DataType_Geometry:
builder := array.NewStringBuilder(mem)
wkbData := insertData.Data[fieldID].(*storage.GeometryFieldData).Data
validData := insertData.Data[fieldID].(*storage.GeometryFieldData).ValidData
builder.AppendValues(lo.Map(wkbData, func(bs []byte, _ int) string {
return string(bs)
}), validData)
columns = append(columns, builder.NewStringArray())
case schemapb.DataType_Array:
data := insertData.Data[fieldID].(*storage.ArrayFieldData).Data
validData := insertData.Data[fieldID].(*storage.ArrayFieldData).ValidData

View File

@ -62,6 +62,11 @@ func ConvertToArrowSchema(fields []*schemapb.FieldSchema) (*arrow.Schema, error)
Name: field.Name,
Type: arrow.BinaryTypes.Binary,
})
case schemapb.DataType_Geometry:
arrowFields = append(arrowFields, arrow.Field{
Name: field.Name,
Type: arrow.BinaryTypes.Binary,
})
case schemapb.DataType_BinaryVector:
dim, err := storage.GetDimFromParams(field.TypeParams)
if err != nil {

View File

@ -77,6 +77,8 @@ func BuildRecord(b *array.RecordBuilder, data *storage.InsertData, fields []*sch
}
case schemapb.DataType_JSON:
fBuilder.(*array.BinaryBuilder).AppendValues(data.Data[field.FieldID].(*storage.JSONFieldData).Data, nil)
case schemapb.DataType_Geometry:
fBuilder.(*array.BinaryBuilder).AppendValues(data.Data[field.FieldID].(*storage.GeometryFieldData).Data, nil)
case schemapb.DataType_BinaryVector:
vecData := data.Data[field.FieldID].(*storage.BinaryVectorFieldData)
for i := 0; i < len(vecData.Data); i += vecData.Dim / 8 {

View File

@ -14,7 +14,7 @@ require (
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0
github.com/json-iterator/go v1.1.12
github.com/klauspost/compress v1.17.7
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786
github.com/nats-io/nats-server/v2 v2.10.12
github.com/nats-io/nats.go v1.34.1
github.com/panjf2000/ants/v2 v2.11.3
@ -22,8 +22,8 @@ require (
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/remeh/sizedwaitgroup v1.0.0
github.com/samber/lo v1.27.0
github.com/shirou/gopsutil/v3 v3.22.9
github.com/sirupsen/logrus v1.9.0
github.com/shirou/gopsutil/v3 v3.24.2
github.com/sirupsen/logrus v1.9.3
github.com/spaolacci/murmur3 v1.1.0
github.com/spf13/cast v1.3.1
github.com/streamnative/pulsarctl v0.5.0
@ -31,6 +31,7 @@ require (
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c
github.com/tidwall/gjson v1.17.0
github.com/tikv/client-go/v2 v2.0.4
github.com/twpayne/go-geom v1.5.7
github.com/uber/jaeger-client-go v2.30.0+incompatible
github.com/x448/float16 v0.8.4
go.etcd.io/etcd/api/v3 v3.5.5
@ -47,9 +48,9 @@ require (
go.uber.org/atomic v1.10.0
go.uber.org/automaxprocs v1.5.3
go.uber.org/zap v1.27.0
golang.org/x/crypto v0.36.0
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2
golang.org/x/net v0.38.0
golang.org/x/crypto v0.25.0
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
golang.org/x/net v0.27.0
golang.org/x/sync v0.12.0
golang.org/x/sys v0.31.0
google.golang.org/grpc v1.65.0
@ -78,7 +79,7 @@ require (
github.com/danieljoos/wincred v1.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.0 // indirect
github.com/dvsekhvalnov/jose2go v1.6.0 // indirect
github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c // indirect
@ -88,7 +89,7 @@ require (
github.com/getsentry/sentry-go v0.12.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect
github.com/godbus/dbus/v5 v5.0.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
@ -109,7 +110,7 @@ require (
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/linkedin/goavro/v2 v2.11.1 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.8 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
@ -130,12 +131,13 @@ require (
github.com/pingcap/log v1.1.1-0.20221015072633-39906604fb81 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/stathat/consistent v1.0.0 // indirect
@ -144,12 +146,12 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tikv/pd/client v0.0.0-20221031025758-80f0d8ca4d07 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/twmb/murmur3 v1.1.3 // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect
go.etcd.io/etcd/client/v2 v2.305.5 // indirect

View File

@ -50,6 +50,8 @@ github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbi
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
github.com/CloudyKit/jet/v3 v3.0.0/go.mod h1:HKQPgSJmdK8hdoAbKUUWajkHyHo4RaU5rMdUywE7VMo=
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
github.com/DATA-DOG/go-sqlmock v1.5.2/go.mod h1:88MAG/4G7SMwSE3CeA0ZKzrT5CiOU3OJ+JlNzwDqpNU=
github.com/DataDog/zstd v1.5.0 h1:+K/VEwIAaPcHiMtQvpLD4lqW7f0Gk3xdYZmI1hD+CXo=
github.com/DataDog/zstd v1.5.0/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
@ -61,6 +63,10 @@ github.com/actgardner/gogen-avro/v10 v10.1.0/go.mod h1:o+ybmVjEa27AAr35FRqU98DJu
github.com/actgardner/gogen-avro/v10 v10.2.1/go.mod h1:QUhjeHPchheYmMDni/Nx7VB0RsT/ee8YIgGY/xpEQgQ=
github.com/actgardner/gogen-avro/v9 v9.1.0/go.mod h1:nyTj6wPqDJoxM3qdnjcLv+EnMDSDFqE0qDpva2QRmKc=
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -159,8 +165,8 @@ github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUn
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/dimfeld/httptreemux v5.0.1+incompatible h1:Qj3gVcDNoOthBAqftuD596rm4wg/adLLz5xh5CmpiCA=
github.com/dimfeld/httptreemux v5.0.1+incompatible/go.mod h1:rbUlSV+CCpv/SuqUTP/8Bk2O3LyUV436/yaRGkhP6Z0=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dvsekhvalnov/jose2go v1.6.0 h1:Y9gnSnP4qEI0+/uQkHvFXeD2PLPJeXEL+ySMEA2EjTY=
@ -224,8 +230,9 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
@ -378,6 +385,8 @@ github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0m
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/heetch/avro v0.3.1/go.mod h1:4xn38Oz/+hiEUTpbVfGVLfvOg0yKLlRP7Q9+gJJILgA=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/hydrogen18/memlistener v0.0.0-20200120041712-dcc25e7acd91/go.mod h1:qEIFzExnS6016fRpRfxrExeVn2gbClQA99gQhnIcdhE=
github.com/iancoleman/orderedmap v0.0.0-20190318233801-ac98e3ecb4b0/go.mod h1:N0Wam8K1arqPXNWjMo21EXnBPOPp36vB07FNRdD2geA=
@ -456,12 +465,13 @@ github.com/linkedin/goavro/v2 v2.10.0/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF
github.com/linkedin/goavro/v2 v2.10.1/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
github.com/linkedin/goavro/v2 v2.11.1 h1:4cuAtbDfqkKnBXp9E+tRkIJGa6W6iAjwonwt8O1f4U0=
github.com/linkedin/goavro/v2 v2.11.1/go.mod h1:UgQUb2N/pmueQYH9bfqFioWxzYCZXSfF8Jw03O5sjqA=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
@ -488,8 +498,8 @@ github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119 h1:9VXijWu
github.com/milvus-io/cgosymbolizer v0.0.0-20240722103217-b7dee0e50119/go.mod h1:DvXTE/K/RtHehxU8/GtDs4vFtfw64jJ3PaCnFri8CRg=
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b h1:TfeY0NxYxZzUfIfYe5qYDBzt4ZYRqzUjTR6CvUzjat8=
github.com/milvus-io/gorocksdb v0.0.0-20220624081344-8c5f4212846b/go.mod h1:iwW+9cWfIzzDseEBCCeDSN5SD16Tidvy8cwQ7ZY8Qj4=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17 h1:LDOodBVtc2AYxcgc51vDwe+gJp96s6yhJLfdGbLrK+0=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786 h1:GspXs2i+sm2GE4n46VRWBjSCQjqtJDIwwcye+gFyxZA=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/pulsar-client-go v0.12.1 h1:O2JZp1tsYiO7C0MQ4hrUY/aJXnn2Gry6hpm7UodghmE=
github.com/milvus-io/pulsar-client-go v0.12.1/go.mod h1:dkutuH4oS2pXiGm+Ti7fQZ4MRjrMPZ8IJeEGAWMeckk=
github.com/minio/highwayhash v1.0.2 h1:Aak5U0nElisjDCfPSG79Tgzkn2gl66NxOMspRrKnA/g=
@ -573,8 +583,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -633,15 +644,19 @@ github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtm
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA=
github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A=
github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y=
github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
@ -670,6 +685,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@ -681,6 +697,7 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
@ -698,15 +715,19 @@ github.com/tikv/client-go/v2 v2.0.4 h1:cPtMXTExqjzk8L40qhrgB/mXiBXKP5LRU0vwjtI2X
github.com/tikv/client-go/v2 v2.0.4/go.mod h1:v52O5zDtv2BBus4lm5yrSQhxGW4Z4RaXWfg0U1Kuyqo=
github.com/tikv/pd/client v0.0.0-20221031025758-80f0d8ca4d07 h1:ckPpxKcl75mO2N6a4cJXiZH43hvcHPpqc9dh1TmH1nc=
github.com/tikv/pd/client v0.0.0-20221031025758-80f0d8ca4d07/go.mod h1:CipBxPfxPUME+BImx9MUYXCnAVLS3VJUr3mnSJwh40A=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/twmb/murmur3 v1.1.3 h1:D83U0XYKcHRYwYIpBKf3Pks91Z0Byda/9SJ8B6EMRcA=
github.com/twmb/murmur3 v1.1.3/go.mod h1:Qq/R7NUyOfr65zD+6Q5IHKsJLwP7exErjN6lyyq3OSQ=
github.com/twpayne/go-geom v1.5.7 h1:7fdceDUr03/MP7rAKOaTV6x9njMiQdxB/D0PDzMTCDc=
github.com/twpayne/go-geom v1.5.7/go.mod h1:y4fTAQtLedXW8eG2Yo4tYrIGN1yIwwKkmA+K3iSHKBA=
github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o=
github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
@ -738,8 +759,8 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
@ -833,8 +854,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -845,8 +866,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -922,8 +943,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8=
golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@ -1018,11 +1039,13 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -167,6 +167,22 @@ message NullExpr {
NullOp op = 2;
}
message GISFunctionFilterExpr{
ColumnInfo column_info = 1;
string wkt_string = 2;
enum GISOp {
Invalid = 0;
Equals = 1;
Touches = 2;
Overlaps = 3;
Crosses = 4;
Contains = 5;
Intersects = 6;
Within = 7;
}
GISOp op = 3;
}
message UnaryExpr {
enum UnaryOp {
Invalid = 0;
@ -228,6 +244,7 @@ message Expr {
JSONContainsExpr json_contains_expr = 13;
CallExpr call_expr = 14;
NullExpr null_expr = 15;
GISFunctionFilterExpr gisfunction_filter_expr = 16;
};
bool is_template = 20;
}

File diff suppressed because it is too large Load Diff

View File

@ -379,6 +379,8 @@ func GetNumRowOfFieldDataWithSchema(fieldData *schemapb.FieldData, helper *typeu
fieldNumRows = getNumRowsOfScalarField(fieldData.GetScalars().GetArrayData().GetData())
case schemapb.DataType_JSON:
fieldNumRows = getNumRowsOfScalarField(fieldData.GetScalars().GetJsonData().GetData())
case schemapb.DataType_Geometry:
fieldNumRows = getNumRowsOfScalarField(fieldData.GetScalars().GetGeometryData().GetData())
case schemapb.DataType_FloatVector:
dim := fieldData.GetVectors().GetDim()
fieldNumRows, err = GetNumRowsOfFloatVectorField(fieldData.GetVectors().GetFloatVector().GetData(), dim)
@ -436,6 +438,8 @@ func GetNumRowOfFieldData(fieldData *schemapb.FieldData) (uint64, error) {
fieldNumRows = getNumRowsOfScalarField(scalarField.GetArrayData().Data)
case *schemapb.ScalarField_JsonData:
fieldNumRows = getNumRowsOfScalarField(scalarField.GetJsonData().Data)
case *schemapb.ScalarField_GeometryData:
fieldNumRows = getNumRowsOfScalarField(scalarField.GetGeometryData().Data)
default:
return 0, fmt.Errorf("%s is not supported now", scalarType)
}

View File

@ -26,6 +26,8 @@ import (
"strconv"
"strings"
"github.com/twpayne/go-geom/encoding/wkb"
"github.com/twpayne/go-geom/encoding/wkt"
"github.com/x448/float16"
"github.com/milvus-io/milvus-proto/go-api/v2/schemapb"
@ -149,6 +151,57 @@ func GenerateJSONArray(numRows int) [][]byte {
return ret
}
// milvus core compoent view geometry as wkb bytes
func GenerateGeometryArray(numRows int) [][]byte {
ret := make([][]byte, 0, numRows)
const (
point = "POINT (30.123 -10.456)"
linestring = "LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)"
polygon = "POLYGON ((30.123 -10.456, 40.678 40.890, 20.345 40.567, 10.123 20.456, 30.123 -10.456))"
multipoint = "MULTIPOINT ((10.111 40.222), (40.333 30.444), (20.555 20.666), (30.777 10.888))"
multilinestring = "MULTILINESTRING ((10.111 10.222, 20.333 20.444), (15.555 15.666, 25.777 25.888), (-30.999 20.000, 40.111 30.222))"
multipolygon = "MULTIPOLYGON (((30.123 -10.456, 40.678 40.890, 20.345 40.567, 10.123 20.456, 30.123 -10.456)),((15.123 5.456, 25.678 5.890, 25.345 15.567, 15.123 15.456, 15.123 5.456)))"
)
wktArray := [6]string{point, linestring, polygon, multipoint, multilinestring, multipolygon}
for i := 0; i < numRows; i++ {
// data of wkt string bytes ,consider to be process by proxy
if i == numRows-1 {
geomT, _ := wkt.Unmarshal("POINT (-84.036 39.997)") // add a special point finally for test
wkbdata, _ := wkb.Marshal(geomT, wkb.NDR)
ret = append(ret, wkbdata)
continue
}
geomT, _ := wkt.Unmarshal(wktArray[i%6])
wkbdata, _ := wkb.Marshal(geomT, wkb.NDR)
ret = append(ret, wkbdata)
}
return ret
}
// milvus client and proxy's insert request input view geometry data as wkt strings
func GenerateGeometryWktArray(numRows int) [][]byte {
ret := make([][]byte, 0, numRows)
const (
point = "POINT (30.123 -10.456)"
linestring = "LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)"
polygon = "POLYGON ((30.123 -10.456, 40.678 40.890, 20.345 40.567, 10.123 20.456, 30.123 -10.456))"
multipoint = "MULTIPOINT ((10.111 40.222), (40.333 30.444), (20.555 20.666), (30.777 10.888))"
multilinestring = "MULTILINESTRING ((10.111 10.222, 20.333 20.444), (15.555 15.666, 25.777 25.888), (-30.999 20.000, 40.111 30.222))"
multipolygon = "MULTIPOLYGON (((30.123 -10.456, 40.678 40.890, 20.345 40.567, 10.123 20.456, 30.123 -10.456)),((15.123 5.456, 25.678 5.890, 25.345 15.567, 15.123 15.456, 15.123 5.456)))"
)
wktArray := [6]string{point, linestring, polygon, multipoint, multilinestring, multipolygon}
for i := 0; i < numRows; i++ {
// data of wkt string bytes ,consider to be process by proxy
if i == numRows-1 {
ret = append(ret, []byte("POINT (-84.036 39.997)"))
continue
}
ret = append(ret, []byte(wktArray[i%6]))
}
return ret
}
func GenerateArrayOfBoolArray(numRows int) []*schemapb.ScalarField {
ret := make([]*schemapb.ScalarField, 0, numRows)
for i := 0; i < numRows; i++ {
@ -715,6 +768,54 @@ func NewArrayFieldDataWithValue(fieldName string, fieldValue interface{}) *schem
}
}
func NewGeometryFieldData(fieldName string, numRows int) *schemapb.FieldData {
return &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: fieldName,
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: GenerateGeometryArray(numRows),
},
},
},
},
}
}
func NewGeometryFieldDataWktFormat(fieldName string, numRows int) *schemapb.FieldData {
return &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: fieldName,
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: GenerateGeometryWktArray(numRows),
},
},
},
},
}
}
func NewGeometryFieldDataWithValue(fieldName string, fieldValue interface{}) *schemapb.FieldData {
return &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: fieldName,
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: fieldValue.([][]byte),
},
},
},
},
}
}
func NewBinaryVectorFieldData(fieldName string, numRows, dim int) *schemapb.FieldData {
return &schemapb.FieldData{
Type: schemapb.DataType_BinaryVector,
@ -882,6 +983,8 @@ func GenerateScalarFieldData(dType schemapb.DataType, fieldName string, numRows
return NewArrayFieldData(fieldName, numRows)
case schemapb.DataType_JSON:
return NewJSONFieldData(fieldName, numRows)
case schemapb.DataType_Geometry:
return NewGeometryFieldData(fieldName, numRows)
default:
panic("unsupported data type")
}
@ -912,6 +1015,8 @@ func GenerateScalarFieldDataWithValue(dType schemapb.DataType, fieldName string,
fieldData = NewArrayFieldDataWithValue(fieldName, fieldValue)
case schemapb.DataType_JSON:
fieldData = NewJSONFieldDataWithValue(fieldName, fieldValue)
case schemapb.DataType_Geometry:
fieldData = NewGeometryFieldDataWithValue(fieldName, fieldValue)
default:
panic("unsupported data type")
}

View File

@ -123,6 +123,20 @@ func genEmptyJSONFieldData(field *schemapb.FieldSchema) *schemapb.FieldData {
}
}
func genEmptyGeometryFieldData(field *schemapb.FieldSchema) *schemapb.FieldData {
return &schemapb.FieldData{
Type: field.GetDataType(),
FieldName: field.GetName(),
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{GeometryData: &schemapb.GeometryArray{Data: nil}},
},
},
FieldId: field.GetFieldID(),
IsDynamic: field.GetIsDynamic(),
}
}
func genEmptyBinaryVectorFieldData(field *schemapb.FieldSchema) (*schemapb.FieldData, error) {
dim, err := GetDim(field)
if err != nil {
@ -246,6 +260,8 @@ func GenEmptyFieldData(field *schemapb.FieldSchema) (*schemapb.FieldData, error)
return genEmptyArrayFieldData(field), nil
case schemapb.DataType_JSON:
return genEmptyJSONFieldData(field), nil
case schemapb.DataType_Geometry:
return genEmptyGeometryFieldData(field), nil
case schemapb.DataType_BinaryVector:
return genEmptyBinaryVectorFieldData(field)
case schemapb.DataType_FloatVector:

View File

@ -82,7 +82,8 @@ func getVarFieldLength(fieldSchema *schemapb.FieldSchema, policy getVariableFiel
default:
return 0, fmt.Errorf("unrecognized getVariableFieldLengthPolicy %v", policy)
}
case schemapb.DataType_Array, schemapb.DataType_JSON:
// geometry field max length now consider the same as json field, which is 512 bytes
case schemapb.DataType_Array, schemapb.DataType_JSON, schemapb.DataType_Geometry:
return DynamicFieldMaxLength, nil
default:
return 0, fmt.Errorf("field %s is not a variable-length type", fieldSchema.DataType.String())
@ -114,7 +115,8 @@ func estimateSizeBy(schema *schemapb.CollectionSchema, policy getVariableFieldLe
res += 4
case schemapb.DataType_Int64, schemapb.DataType_Double:
res += 8
case schemapb.DataType_VarChar, schemapb.DataType_Array, schemapb.DataType_JSON:
// geometry wkb as well as wkt max len now is the same as max varfield lenth ,consider extend it if needed
case schemapb.DataType_VarChar, schemapb.DataType_Array, schemapb.DataType_JSON, schemapb.DataType_Geometry:
maxLengthPerRow, err := getVarFieldLength(fs, policy)
if err != nil {
return 0, err
@ -196,6 +198,10 @@ func CalcColumnSize(column *schemapb.FieldData) int {
for _, str := range column.GetScalars().GetJsonData().GetData() {
res += len(str)
}
case schemapb.DataType_Geometry:
for _, str := range column.GetScalars().GetGeometryData().GetData() {
res += len(str)
}
default:
panic("Unknown data type:" + column.Type.String())
}
@ -233,6 +239,11 @@ func EstimateEntitySize(fieldsData []*schemapb.FieldData, rowOffset int) (int, e
return 0, errors.New("offset out range of field datas")
}
res += len(fs.GetScalars().GetJsonData().GetData()[rowOffset])
case schemapb.DataType_Geometry:
if rowOffset >= len(fs.GetScalars().GetGeometryData().GetData()) {
return 0, fmt.Errorf("offset out range of field datas")
}
res += len(fs.GetScalars().GetGeometryData().GetData()[rowOffset])
case schemapb.DataType_BinaryVector:
res += int(fs.GetVectors().GetDim())
case schemapb.DataType_FloatVector:
@ -521,6 +532,10 @@ func IsJSONType(dataType schemapb.DataType) bool {
return dataType == schemapb.DataType_JSON
}
func IsGeometryType(dataType schemapb.DataType) bool {
return dataType == schemapb.DataType_Geometry
}
func IsArrayType(dataType schemapb.DataType) bool {
return dataType == schemapb.DataType_Array
}
@ -570,7 +585,7 @@ func IsArrayContainStringElementType(dataType schemapb.DataType, elementType sch
}
func IsVariableDataType(dataType schemapb.DataType) bool {
return IsStringType(dataType) || IsArrayType(dataType) || IsJSONType(dataType)
return IsStringType(dataType) || IsArrayType(dataType) || IsJSONType(dataType) || IsGeometryType(dataType)
}
func IsPrimitiveType(dataType schemapb.DataType) bool {
@ -637,6 +652,12 @@ func PrepareResultFieldData(sample []*schemapb.FieldData, topK int64) []*schemap
Data: make([][]byte, 0, topK),
},
}
case *schemapb.ScalarField_GeometryData:
scalar.Scalars.Data = &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: make([][]byte, 0, topK),
},
}
case *schemapb.ScalarField_ArrayData:
scalar.Scalars.Data = &schemapb.ScalarField_ArrayData{
ArrayData: &schemapb.ArrayArray{
@ -808,6 +829,17 @@ func AppendFieldData(dst, src []*schemapb.FieldData, idx int64) (appendSize int6
}
/* #nosec G103 */
appendSize += int64(unsafe.Sizeof(srcScalar.JsonData.Data[idx]))
case *schemapb.ScalarField_GeometryData:
if dstScalar.GetGeometryData() == nil {
dstScalar.Data = &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: [][]byte{srcScalar.GeometryData.Data[idx]},
},
}
} else {
dstScalar.GetGeometryData().Data = append(dstScalar.GetGeometryData().Data, srcScalar.GeometryData.Data[idx])
}
appendSize += int64(unsafe.Sizeof(srcScalar.GeometryData.Data[idx]))
default:
log.Error("Not supported field type", zap.String("field type", fieldData.Type.String()))
}
@ -926,6 +958,8 @@ func DeleteFieldData(dst []*schemapb.FieldData) {
dstScalar.GetStringData().Data = dstScalar.GetStringData().Data[:len(dstScalar.GetStringData().Data)-1]
case *schemapb.ScalarField_JsonData:
dstScalar.GetJsonData().Data = dstScalar.GetJsonData().Data[:len(dstScalar.GetJsonData().Data)-1]
case *schemapb.ScalarField_GeometryData:
dstScalar.GetGeometryData().Data = dstScalar.GetGeometryData().Data[:len(dstScalar.GetGeometryData().Data)-1]
default:
log.Error("wrong field type added", zap.String("field type", fieldData.Type.String()))
}
@ -1063,6 +1097,16 @@ func MergeFieldData(dst []*schemapb.FieldData, src []*schemapb.FieldData) error
} else {
dstScalar.GetJsonData().Data = append(dstScalar.GetJsonData().Data, srcScalar.JsonData.Data...)
}
case *schemapb.ScalarField_GeometryData:
if dstScalar.GetGeometryData() == nil {
dstScalar.Data = &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: srcScalar.GeometryData.Data,
},
}
} else {
dstScalar.GetGeometryData().Data = append(dstScalar.GetGeometryData().Data, srcScalar.GeometryData.Data...)
}
case *schemapb.ScalarField_BytesData:
if dstScalar.GetBytesData() == nil {
dstScalar.Data = &schemapb.ScalarField_BytesData{

View File

@ -166,13 +166,19 @@ func TestSchema(t *testing.T) {
},
},
},
{
FieldID: 113,
Name: "field_geometry",
IsPrimaryKey: false,
DataType: schemapb.DataType_Geometry,
},
// Do not test on sparse float vector field.
},
}
t.Run("EstimateSizePerRecord", func(t *testing.T) {
size, err := EstimateSizePerRecord(schema)
assert.Equal(t, 680+DynamicFieldMaxLength*3, size)
assert.Equal(t, 680+DynamicFieldMaxLength*4, size)
assert.NoError(t, err)
})
@ -991,6 +997,21 @@ func genFieldData(fieldName string, fieldID int64, fieldType schemapb.DataType,
},
FieldId: fieldID,
}
case schemapb.DataType_Geometry:
fieldData = &schemapb.FieldData{
Type: schemapb.DataType_Geometry,
FieldName: fieldName,
Field: &schemapb.FieldData_Scalars{
Scalars: &schemapb.ScalarField{
Data: &schemapb.ScalarField_GeometryData{
GeometryData: &schemapb.GeometryArray{
Data: fieldValue.([][]byte),
},
},
},
},
FieldId: fieldID,
}
default:
log.Error("not supported field type", zap.String("field type", fieldType.String()))
}
@ -1012,6 +1033,7 @@ func TestAppendFieldData(t *testing.T) {
BFloat16VectorFieldName = "BFloat16VectorField"
ArrayFieldName = "ArrayField"
SparseFloatVectorFieldName = "SparseFloatVectorField"
GeometryFieldName = "GeometryField"
BoolFieldID = common.StartOfUserFieldID + 1
Int32FieldID = common.StartOfUserFieldID + 2
Int64FieldID = common.StartOfUserFieldID + 3
@ -1023,6 +1045,7 @@ func TestAppendFieldData(t *testing.T) {
BFloat16VectorFieldID = common.StartOfUserFieldID + 9
ArrayFieldID = common.StartOfUserFieldID + 10
SparseFloatVectorFieldID = common.StartOfUserFieldID + 11
GeometryFieldID = common.StartOfUserFieldID + 12
)
BoolArray := []bool{true, false}
Int32Array := []int32{1, 2}
@ -1062,8 +1085,13 @@ func TestAppendFieldData(t *testing.T) {
CreateSparseFloatRow([]uint32{60, 80, 230}, []float32{2.1, 2.2, 2.3}),
},
}
// POINT (30.123 -10.456) and LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)
GeometryArray := [][]byte{
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
}
result := make([]*schemapb.FieldData, 11)
result := make([]*schemapb.FieldData, 12)
var fieldDataArray1 []*schemapb.FieldData
fieldDataArray1 = append(fieldDataArray1, genFieldData(BoolFieldName, BoolFieldID, schemapb.DataType_Bool, BoolArray[0:1], 1))
fieldDataArray1 = append(fieldDataArray1, genFieldData(Int32FieldName, Int32FieldID, schemapb.DataType_Int32, Int32Array[0:1], 1))
@ -1076,6 +1104,7 @@ func TestAppendFieldData(t *testing.T) {
fieldDataArray1 = append(fieldDataArray1, genFieldData(BFloat16VectorFieldName, BFloat16VectorFieldID, schemapb.DataType_BFloat16Vector, BFloat16Vector[0:Dim*2], Dim))
fieldDataArray1 = append(fieldDataArray1, genFieldData(ArrayFieldName, ArrayFieldID, schemapb.DataType_Array, ArrayArray[0:1], 1))
fieldDataArray1 = append(fieldDataArray1, genFieldData(SparseFloatVectorFieldName, SparseFloatVectorFieldID, schemapb.DataType_SparseFloatVector, SparseFloatVector.Contents[0], SparseFloatVector.Dim))
fieldDataArray1 = append(fieldDataArray1, genFieldData(GeometryFieldName, GeometryFieldID, schemapb.DataType_Geometry, GeometryArray[0:1], 1))
var fieldDataArray2 []*schemapb.FieldData
fieldDataArray2 = append(fieldDataArray2, genFieldData(BoolFieldName, BoolFieldID, schemapb.DataType_Bool, BoolArray[1:2], 1))
@ -1089,6 +1118,7 @@ func TestAppendFieldData(t *testing.T) {
fieldDataArray2 = append(fieldDataArray2, genFieldData(BFloat16VectorFieldName, BFloat16VectorFieldID, schemapb.DataType_BFloat16Vector, BFloat16Vector[2*Dim:4*Dim], Dim))
fieldDataArray2 = append(fieldDataArray2, genFieldData(ArrayFieldName, ArrayFieldID, schemapb.DataType_Array, ArrayArray[1:2], 1))
fieldDataArray2 = append(fieldDataArray2, genFieldData(SparseFloatVectorFieldName, SparseFloatVectorFieldID, schemapb.DataType_SparseFloatVector, SparseFloatVector.Contents[1], SparseFloatVector.Dim))
fieldDataArray2 = append(fieldDataArray2, genFieldData(GeometryFieldName, GeometryFieldID, schemapb.DataType_Geometry, GeometryArray[1:2], 1))
AppendFieldData(result, fieldDataArray1, 0)
AppendFieldData(result, fieldDataArray2, 0)
@ -1104,6 +1134,7 @@ func TestAppendFieldData(t *testing.T) {
assert.Equal(t, BFloat16Vector, result[8].GetVectors().Data.(*schemapb.VectorField_Bfloat16Vector).Bfloat16Vector)
assert.Equal(t, ArrayArray, result[9].GetScalars().GetArrayData().Data)
assert.Equal(t, SparseFloatVector, result[10].GetVectors().GetSparseFloatVector())
assert.Equal(t, GeometryArray, result[11].GetScalars().GetGeometryData().Data)
}
func TestDeleteFieldData(t *testing.T) {
@ -1115,6 +1146,7 @@ func TestDeleteFieldData(t *testing.T) {
FloatFieldName = "FloatField"
DoubleFieldName = "DoubleField"
JSONFieldName = "JSONField"
GeometryFieldName = "GeometryField"
BinaryVectorFieldName = "BinaryVectorField"
FloatVectorFieldName = "FloatVectorField"
Float16VectorFieldName = "Float16VectorField"
@ -1129,6 +1161,7 @@ func TestDeleteFieldData(t *testing.T) {
FloatFieldID
DoubleFieldID
JSONFieldID
GeometryFiledID
BinaryVectorFieldID
FloatVectorFieldID
Float16VectorFieldID
@ -1141,6 +1174,11 @@ func TestDeleteFieldData(t *testing.T) {
FloatArray := []float32{1.0, 2.0}
DoubleArray := []float64{11.0, 22.0}
JSONArray := [][]byte{[]byte("{\"hello\":0}"), []byte("{\"key\":1}")}
// POINT (30.123 -10.456) and LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)
GeometryArray := [][]byte{
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
}
BinaryVector := []byte{0x12, 0x34}
FloatVector := []float32{1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 11.0, 22.0, 33.0, 44.0, 55.0, 66.0, 77.0, 88.0}
Float16Vector := []byte{
@ -1159,8 +1197,8 @@ func TestDeleteFieldData(t *testing.T) {
},
}
result1 := make([]*schemapb.FieldData, 11)
result2 := make([]*schemapb.FieldData, 11)
result1 := make([]*schemapb.FieldData, 12)
result2 := make([]*schemapb.FieldData, 12)
var fieldDataArray1 []*schemapb.FieldData
fieldDataArray1 = append(fieldDataArray1, genFieldData(BoolFieldName, BoolFieldID, schemapb.DataType_Bool, BoolArray[0:1], 1))
fieldDataArray1 = append(fieldDataArray1, genFieldData(Int32FieldName, Int32FieldID, schemapb.DataType_Int32, Int32Array[0:1], 1))
@ -1168,6 +1206,7 @@ func TestDeleteFieldData(t *testing.T) {
fieldDataArray1 = append(fieldDataArray1, genFieldData(FloatFieldName, FloatFieldID, schemapb.DataType_Float, FloatArray[0:1], 1))
fieldDataArray1 = append(fieldDataArray1, genFieldData(DoubleFieldName, DoubleFieldID, schemapb.DataType_Double, DoubleArray[0:1], 1))
fieldDataArray1 = append(fieldDataArray1, genFieldData(JSONFieldName, JSONFieldID, schemapb.DataType_JSON, JSONArray[0:1], 1))
fieldDataArray1 = append(fieldDataArray1, genFieldData(GeometryFieldName, GeometryFiledID, schemapb.DataType_Geometry, GeometryArray[0:1], 1))
fieldDataArray1 = append(fieldDataArray1, genFieldData(BinaryVectorFieldName, BinaryVectorFieldID, schemapb.DataType_BinaryVector, BinaryVector[0:Dim/8], Dim))
fieldDataArray1 = append(fieldDataArray1, genFieldData(FloatVectorFieldName, FloatVectorFieldID, schemapb.DataType_FloatVector, FloatVector[0:Dim], Dim))
fieldDataArray1 = append(fieldDataArray1, genFieldData(Float16VectorFieldName, Float16VectorFieldID, schemapb.DataType_Float16Vector, Float16Vector[0:2*Dim], Dim))
@ -1181,6 +1220,7 @@ func TestDeleteFieldData(t *testing.T) {
fieldDataArray2 = append(fieldDataArray2, genFieldData(FloatFieldName, FloatFieldID, schemapb.DataType_Float, FloatArray[1:2], 1))
fieldDataArray2 = append(fieldDataArray2, genFieldData(DoubleFieldName, DoubleFieldID, schemapb.DataType_Double, DoubleArray[1:2], 1))
fieldDataArray2 = append(fieldDataArray2, genFieldData(JSONFieldName, JSONFieldID, schemapb.DataType_JSON, JSONArray[1:2], 1))
fieldDataArray2 = append(fieldDataArray2, genFieldData(GeometryFieldName, GeometryFiledID, schemapb.DataType_Geometry, GeometryArray[1:2], 1))
fieldDataArray2 = append(fieldDataArray2, genFieldData(BinaryVectorFieldName, BinaryVectorFieldID, schemapb.DataType_BinaryVector, BinaryVector[Dim/8:2*Dim/8], Dim))
fieldDataArray2 = append(fieldDataArray2, genFieldData(FloatVectorFieldName, FloatVectorFieldID, schemapb.DataType_FloatVector, FloatVector[Dim:2*Dim], Dim))
fieldDataArray2 = append(fieldDataArray2, genFieldData(Float16VectorFieldName, Float16VectorFieldID, schemapb.DataType_Float16Vector, Float16Vector[2*Dim:4*Dim], Dim))
@ -1196,6 +1236,7 @@ func TestDeleteFieldData(t *testing.T) {
assert.Equal(t, FloatArray[0:1], result1[FloatFieldID-common.StartOfUserFieldID].GetScalars().GetFloatData().Data)
assert.Equal(t, DoubleArray[0:1], result1[DoubleFieldID-common.StartOfUserFieldID].GetScalars().GetDoubleData().Data)
assert.Equal(t, JSONArray[0:1], result1[JSONFieldID-common.StartOfUserFieldID].GetScalars().GetJsonData().Data)
assert.Equal(t, GeometryArray[0:1], result1[GeometryFiledID-common.StartOfUserFieldID].GetScalars().GetGeometryData().Data)
assert.Equal(t, BinaryVector[0:Dim/8], result1[BinaryVectorFieldID-common.StartOfUserFieldID].GetVectors().Data.(*schemapb.VectorField_BinaryVector).BinaryVector)
assert.Equal(t, FloatVector[0:Dim], result1[FloatVectorFieldID-common.StartOfUserFieldID].GetVectors().GetFloatVector().Data)
assert.Equal(t, Float16Vector[0:2*Dim], result1[Float16VectorFieldID-common.StartOfUserFieldID].GetVectors().Data.(*schemapb.VectorField_Float16Vector).Float16Vector)
@ -1213,6 +1254,7 @@ func TestDeleteFieldData(t *testing.T) {
assert.Equal(t, FloatArray[1:2], result2[FloatFieldID-common.StartOfUserFieldID].GetScalars().GetFloatData().Data)
assert.Equal(t, DoubleArray[1:2], result2[DoubleFieldID-common.StartOfUserFieldID].GetScalars().GetDoubleData().Data)
assert.Equal(t, JSONArray[1:2], result2[JSONFieldID-common.StartOfUserFieldID].GetScalars().GetJsonData().Data)
assert.Equal(t, GeometryArray[1:2], result2[GeometryFiledID-common.StartOfUserFieldID].GetScalars().GetGeometryData().Data)
assert.Equal(t, BinaryVector[Dim/8:2*Dim/8], result2[BinaryVectorFieldID-common.StartOfUserFieldID].GetVectors().Data.(*schemapb.VectorField_BinaryVector).BinaryVector)
assert.Equal(t, FloatVector[Dim:2*Dim], result2[FloatVectorFieldID-common.StartOfUserFieldID].GetVectors().GetFloatVector().Data)
assert.Equal(t, Float16Vector[2*Dim:4*Dim], result2[Float16VectorFieldID-common.StartOfUserFieldID].GetVectors().Data.(*schemapb.VectorField_Float16Vector).Float16Vector)
@ -1502,6 +1544,11 @@ func TestCalcColumnSize(t *testing.T) {
},
},
110: [][]byte{[]byte(`{"key":"value"}`), []byte(`{"hello":"world"}`)},
111: [][]byte{
// POINT (30.123 -10.456) and LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
},
}
schema := &schemapb.CollectionSchema{
Name: "testColl",
@ -1573,6 +1620,11 @@ func TestCalcColumnSize(t *testing.T) {
Name: "field_json",
DataType: schemapb.DataType_JSON,
},
{
FieldID: 111,
Name: "field_geometry",
DataType: schemapb.DataType_Geometry,
},
},
}
@ -1598,6 +1650,11 @@ func TestCalcColumnSize(t *testing.T) {
expected += len(v)
}
case schemapb.DataType_Geometry:
data := values.([][]byte)
for _, v := range data {
expected += len(v)
}
default:
expected = binary.Size(fieldValues[field.GetFieldID()])
}
@ -1765,6 +1822,10 @@ func TestMergeFieldData(t *testing.T) {
},
genFieldData("float16_vector", 111, schemapb.DataType_Float16Vector, []byte("12345678"), 4),
genFieldData("bfloat16_vector", 112, schemapb.DataType_BFloat16Vector, []byte("12345678"), 4),
genFieldData("geometry", 113, schemapb.DataType_Geometry, [][]byte{
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
}, 1),
}
srcFields := []*schemapb.FieldData{
@ -1826,6 +1887,10 @@ func TestMergeFieldData(t *testing.T) {
},
genFieldData("float16_vector", 111, schemapb.DataType_Float16Vector, []byte("abcdefgh"), 4),
genFieldData("bfloat16_vector", 112, schemapb.DataType_BFloat16Vector, []byte("ABCDEFGH"), 4),
genFieldData("geometry", 113, schemapb.DataType_Geometry, [][]byte{
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
}, 1),
}
err := MergeFieldData(dstFields, srcFields)
@ -1894,6 +1959,10 @@ func TestMergeFieldData(t *testing.T) {
},
genFieldData("float16_vector", 111, schemapb.DataType_Float16Vector, []byte("12345678"), 4),
genFieldData("bfloat16_vector", 112, schemapb.DataType_BFloat16Vector, []byte("12345678"), 4),
genFieldData("geometry", 113, schemapb.DataType_Geometry, [][]byte{
{0x01, 0x01, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40},
{0x01, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A, 0x0D, 0x1B, 0x4F, 0x4F, 0x9A, 0x3D, 0x40, 0x03, 0xA6, 0xB4, 0xA6, 0xA4, 0xD2, 0xC5, 0xC0, 0xD2, 0x4A, 0x4D, 0x6A, 0x8B, 0x3C, 0x5C, 0x0A},
}, 1),
}
dstFields := []*schemapb.FieldData{
@ -1904,6 +1973,7 @@ func TestMergeFieldData(t *testing.T) {
{Type: schemapb.DataType_SparseFloatVector, FieldName: "sparseFloat", Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{Data: &schemapb.VectorField_SparseFloatVector{}}}, FieldId: 104},
{Type: schemapb.DataType_Float16Vector, FieldName: "float16_vector", Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{Data: &schemapb.VectorField_Float16Vector{}}}, FieldId: 111},
{Type: schemapb.DataType_BFloat16Vector, FieldName: "bfloat16_vector", Field: &schemapb.FieldData_Vectors{Vectors: &schemapb.VectorField{Data: &schemapb.VectorField_Bfloat16Vector{}}}, FieldId: 112},
{Type: schemapb.DataType_Geometry, FieldName: "geometry", Field: &schemapb.FieldData_Scalars{Scalars: &schemapb.ScalarField{Data: &schemapb.ScalarField_GeometryData{}}}, FieldId: 113},
}
err := MergeFieldData(dstFields, srcFields)

View File

@ -41,7 +41,7 @@ const (
// cost for test cases
const (
RowCount = "row_count"
DefaultTimeout = 120
DefaultTimeout = 600
DefaultDim = 128
DefaultShards = int32(2)
DefaultNb = 3000

View File

@ -9,6 +9,8 @@ import (
"testing"
"github.com/stretchr/testify/require"
// "github.com/twpayne/go-geom/encoding/wkb"
// "github.com/twpayne/go-geom/encoding/wkt"
"go.uber.org/zap"
"github.com/milvus-io/milvus/client/v2/column"
@ -76,6 +78,18 @@ func EqualColumn(t *testing.T, columnA column.Column, columnB column.Column) {
default:
log.Warn("columnA type", zap.String("name", columnB.Name()), zap.Any("type", _v))
}
// case entity.FieldTypeGeometry:
// // currently proxy transform wkb to wkt,the query output wkt has different precision with client input(omit trailing zeros),and omit omissible bracket
// columnAcompData := make([][]byte, 0)
// // simulate proxy replace wkb progress
// for _, bytes := range columnA.(*column.ColumnGeometryBytes).Data() {
// geomT, _ := wkt.Unmarshal(string(bytes))
// wkbBytes, _ := wkb.Marshal(geomT, wkb.NDR)
// geomT, _ = wkb.Unmarshal(wkbBytes)
// realwktstr, _ := wkt.Marshal(geomT)
// columnAcompData = append(columnAcompData, []byte(realwktstr))
// }
// require.ElementsMatch(t, columnAcompData, columnB.(*column.ColumnGeometryBytes).Data())
case entity.FieldTypeFloatVector:
require.ElementsMatch(t, columnA.(*column.ColumnFloatVector).Data(), columnB.(*column.ColumnFloatVector).Data())
case entity.FieldTypeBinaryVector:

View File

@ -8,6 +8,7 @@ require (
github.com/quasilyte/go-ruleguard/dsl v0.3.22
github.com/samber/lo v1.27.0
github.com/stretchr/testify v1.10.0
// github.com/twpayne/go-geom v1.6.1
github.com/x448/float16 v0.8.4
go.uber.org/zap v1.27.0
google.golang.org/grpc v1.65.0
@ -28,13 +29,13 @@ require (
github.com/coreos/go-semver v0.3.0 // indirect
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/form3tech-oss/jwt-go v3.2.3+incompatible // indirect
github.com/getsentry/sentry-go v0.12.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/godbus/dbus/v5 v5.0.4 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
@ -49,22 +50,23 @@ require (
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17 // indirect
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/opencontainers/runtime-spec v1.0.2 // indirect
github.com/panjf2000/ants/v2 v2.11.3 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.5.0 // indirect
github.com/prometheus/common v0.42.0 // indirect
github.com/prometheus/procfs v0.9.0 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
github.com/shirou/gopsutil/v3 v3.22.9 // indirect
github.com/shirou/gopsutil/v3 v3.24.2 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/soheilhy/cmux v0.1.5 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
@ -73,12 +75,12 @@ require (
github.com/tidwall/gjson v1.17.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/tklauser/numcpus v0.4.0 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 // indirect
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect
go.etcd.io/bbolt v1.3.6 // indirect
go.etcd.io/etcd/api/v3 v3.5.5 // indirect
go.etcd.io/etcd/client/pkg/v3 v3.5.5 // indirect

View File

@ -94,8 +94,8 @@ github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6ps
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
@ -140,8 +140,9 @@ github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ4
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo=
github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
@ -297,8 +298,9 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.5.0/go.mod h1:czIriw4a0C1dFun+ObrXp7ok03xON0N1awStJ6ArI7Y=
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a h1:3Bm7EwfUQUvhNeKIkUct/gl9eod1TcXuj8stxvi/GoI=
github.com/lufia/plan9stats v0.0.0-20240226150601-1dcf7310316a/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
@ -318,8 +320,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfr
github.com/mediocregopher/radix/v3 v3.4.2/go.mod h1:8FL3F6UQRXHXIBSPUs5h0RybMF8i4n7wVopoX3x7Bv8=
github.com/microcosm-cc/bluemonday v1.0.2/go.mod h1:iVP4YcDBq+n/5fb23BhYFvIMq/leAFZyRl6bYmGDlGc=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17 h1:LDOodBVtc2AYxcgc51vDwe+gJp96s6yhJLfdGbLrK+0=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.17/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786 h1:GspXs2i+sm2GE4n46VRWBjSCQjqtJDIwwcye+gFyxZA=
github.com/milvus-io/milvus-proto/go-api/v2 v2.5.18-0.20250822062940-e34629021786/go.mod h1:/6UT4zZl6awVeXLeE7UGDWZvXj3IWkRsh3mqsn0DiAs=
github.com/milvus-io/milvus/pkg/v2 v2.5.7 h1:b45jq1s1v03AekFucs2/dkkXohB57gEx7gspJuAkfbY=
github.com/milvus-io/milvus/pkg/v2 v2.5.7/go.mod h1:pImw1IGNS7k/5yvlZV2tZi5vZu1VQRlQij+r39d+XnI=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
@ -366,8 +368,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@ -417,8 +420,12 @@ github.com/samber/lo v1.27.0/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+R
github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v3 v3.22.9 h1:yibtJhIVEMcdw+tCTbOPiF1VcsuDeTE4utJ8Dm4c5eA=
github.com/shirou/gopsutil/v3 v3.22.9/go.mod h1:bBYl1kjgEJpWpxeHmLI+dVHWtyAwfcmSBLDsp2TNT8A=
github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y=
github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk=
github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM=
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@ -449,6 +456,7 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@ -458,6 +466,7 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
@ -469,10 +478,12 @@ github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802 h1:uruHq4dN7GR16kFc5fp3d1RIYzJW5onx8Ybykw2YQFA=
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
@ -503,8 +514,8 @@ github.com/yudai/pp v2.0.1+incompatible/go.mod h1:PuxR/8QJ7cyCkFp/aUDS+JY727OFEZ
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
@ -691,10 +702,12 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=

View File

@ -292,6 +292,24 @@ func GenNestedJSONExprKey(depth int, jsonField string) string {
return fmt.Sprintf("%s['%s']", jsonField, strings.Join(pathParts, "']['"))
}
// func GenDefaultGeometryData(nb int, option GenDataOption) [][]byte {
// const (
// point = "POINT (30.123 -10.456)"
// linestring = "LINESTRING (30.123 -10.456, 10.789 30.123, -40.567 40.890)"
// polygon = "POLYGON ((30.123 -10.456, 40.678 40.890, 20.345 40.567, 10.123 20.456, 30.123 -10.456))"
// multipoint = "MULTIPOINT ((10.111 40.222), (40.333 30.444), (20.555 20.666), (30.777 10.888))"
// multilinestring = "MULTILINESTRING ((10.111 10.222, 20.333 20.444), (15.555 15.666, 25.777 25.888), (-30.999 20.000, 40.111 30.222))"
// multipolygon = "MULTIPOLYGON (((30.123 -10.456, 40.678 40.890, 20.345 40.567, 10.123 20.456, 30.123 -10.456)),((15.123 5.456, 25.678 5.890, 25.345 15.567, 15.123 15.456, 15.123 5.456)))"
// )
// wktArray := [6]string{point, linestring, polygon, multipoint, multilinestring, multipolygon}
// geometryValues := make([][]byte, 0, nb)
// start := option.start
// for i := start; i < start+nb; i++ {
// geometryValues = append(geometryValues, []byte(wktArray[i%6]))
// }
// return geometryValues
// }
// GenColumnData GenColumnDataOption except dynamic column
func GenColumnData(nb int, fieldType entity.FieldType, option GenDataOption) column.Column {
dim := option.dim
@ -392,6 +410,10 @@ func GenColumnData(nb int, fieldType entity.FieldType, option GenDataOption) col
jsonValues := GenDefaultJSONData(nb, option)
return column.NewColumnJSONBytes(fieldName, jsonValues)
// case entity.FieldTypeGeometry:
// geometryValues := GenDefaultGeometryData(nb, option)
// return column.NewColumnGeometryBytes(fieldName, geometryValues)
case entity.FieldTypeFloatVector:
vecFloatValues := make([][]float32, 0, nb)
for i := start; i < start+nb; i++ {

View File

@ -78,6 +78,8 @@ func GetFieldNameByFieldType(t entity.FieldType, opts ...GetFieldNameOpt) string
return common.DefaultDynamicFieldName
}
return common.DefaultJSONFieldName
// case entity.FieldTypeGeometry:
// return common.DefaultGeometryName
case entity.FieldTypeArray:
return GetFieldNameByElementType(opt.elementType)
case entity.FieldTypeBinaryVector:

View File

@ -59,6 +59,7 @@ func GetAllScalarFieldType() []entity.FieldType {
entity.FieldTypeVarChar,
entity.FieldTypeArray,
entity.FieldTypeJSON,
// entity.FieldTypeGeometry,
}
}
@ -84,6 +85,7 @@ func GetInvalidPkFieldType() []entity.FieldType {
entity.FieldTypeDouble,
entity.FieldTypeString,
entity.FieldTypeJSON,
// entity.FieldTypeGeometry,
entity.FieldTypeArray,
}
return nonPkFieldTypes
@ -98,6 +100,7 @@ func GetInvalidPartitionKeyFieldType() []entity.FieldType {
entity.FieldTypeFloat,
entity.FieldTypeDouble,
entity.FieldTypeJSON,
// entity.FieldTypeGeometry,
entity.FieldTypeArray,
entity.FieldTypeFloatVector,
}

View File

@ -89,7 +89,7 @@ func SupportScalarIndexFieldType(field entity.FieldType) bool {
vectorFieldTypes := []entity.FieldType{
entity.FieldTypeBinaryVector, entity.FieldTypeFloatVector,
entity.FieldTypeFloat16Vector, entity.FieldTypeBFloat16Vector,
entity.FieldTypeSparseVector, entity.FieldTypeJSON,
entity.FieldTypeSparseVector, entity.FieldTypeJSON, // entity.FieldTypeGeometry // geometry now not support scalar index
}
for _, vectorFieldType := range vectorFieldTypes {
if field == vectorFieldType {

View File

@ -242,7 +242,7 @@ func TestCreateAutoIndexAllFields(t *testing.T) {
var expFields []string
var idx index.Index
for _, field := range schema.Fields {
if field.DataType == entity.FieldTypeJSON {
if field.DataType == entity.FieldTypeJSON { // || field.DataType == entity.FieldTypeGeometry
idx = index.NewAutoIndex(entity.IP)
opt := client.NewCreateIndexOption(schema.CollectionName, field.Name, idx)
opt.WithExtraParam("json_path", field.Name)
@ -458,7 +458,7 @@ func TestCreateSortedScalarIndex(t *testing.T) {
for _, field := range schema.Fields {
if hp.SupportScalarIndexFieldType(field.DataType) {
if field.DataType == entity.FieldTypeVarChar || field.DataType == entity.FieldTypeBool ||
field.DataType == entity.FieldTypeJSON || field.DataType == entity.FieldTypeArray {
field.DataType == entity.FieldTypeJSON || field.DataType == entity.FieldTypeArray { // || field.DataType == entity.FieldTypeGeometry
_, err := mc.CreateIndex(ctx, client.NewCreateIndexOption(schema.CollectionName, field.Name, idx))
common.CheckErr(t, err, false, "STL_SORT are only supported on numeric field")
} else {

View File

@ -52,6 +52,7 @@ func (s *CompactionSuite) TestMixCompaction() {
indexType = integration.IndexFaissIvfFlat
metricType = metric.L2
vecType = schemapb.DataType_FloatVector
// testType = schemapb.DataType_Geometry
)
collectionName := "TestCompaction_" + funcutil.GenRandomStr()
@ -92,6 +93,7 @@ func (s *CompactionSuite) TestMixCompaction() {
for i := 0; i < rowNum/batch; i++ {
// insert
fVecColumn := integration.NewFloatVectorFieldData(integration.FloatVecField, batch, dim)
// geoColumn := integration.NewGeometryFieldData(integration.GeometryField, batch)
hashKeys := integration.GenerateHashKeys(batch)
insertResult, err := c.Proxy.Insert(ctx, &milvuspb.InsertRequest{
DbName: dbName,

View File

@ -54,6 +54,8 @@ type BulkInsertSuite struct {
vecType schemapb.DataType
indexType indexparamcheck.IndexType
metricType metric.MetricType
expr string
testType schemapb.DataType
}
func (s *BulkInsertSuite) SetupTest() {
@ -66,6 +68,8 @@ func (s *BulkInsertSuite) SetupTest() {
s.vecType = schemapb.DataType_FloatVector
s.indexType = "HNSW"
s.metricType = metric.L2
s.expr = ""
s.testType = schemapb.DataType_None
}
func (s *BulkInsertSuite) run() {
@ -84,12 +88,23 @@ func (s *BulkInsertSuite) run() {
fieldSchema2 := &schemapb.FieldSchema{FieldID: 101, Name: "image_path", DataType: schemapb.DataType_VarChar, TypeParams: []*commonpb.KeyValuePair{{Key: common.MaxLengthKey, Value: "65535"}}}
fieldSchema3 := &schemapb.FieldSchema{FieldID: 102, Name: "embeddings", DataType: s.vecType, TypeParams: []*commonpb.KeyValuePair{{Key: common.DimKey, Value: "128"}}}
fieldSchema4 := &schemapb.FieldSchema{FieldID: 103, Name: "embeddings", DataType: s.vecType, TypeParams: []*commonpb.KeyValuePair{}}
fields := []*schemapb.FieldSchema{fieldSchema1, fieldSchema2}
if s.vecType != schemapb.DataType_SparseFloatVector {
schema = integration.ConstructSchema(collectionName, dim, false, fieldSchema1, fieldSchema2, fieldSchema3)
fields = append(fields, fieldSchema3)
} else {
schema = integration.ConstructSchema(collectionName, dim, false, fieldSchema1, fieldSchema2, fieldSchema4)
fields = append(fields, fieldSchema4)
}
// Append extra test field (e.g., Geometry) when specified
if s.testType != schemapb.DataType_None {
testFieldName := "testField" + schemapb.DataType_name[int32(s.testType)]
extraField := &schemapb.FieldSchema{FieldID: 104, Name: testFieldName, DataType: s.testType}
fields = append(fields, extraField)
}
schema = integration.ConstructSchema(collectionName, dim, false, fields...)
marshaledSchema, err := proto.Marshal(schema)
s.NoError(err)
@ -201,7 +216,7 @@ func (s *BulkInsertSuite) run() {
s.WaitForLoad(ctx, collectionName)
// search
expr := ""
expr := s.expr
nq := 10
topk := 10
roundDecimal := -1
@ -217,6 +232,12 @@ func (s *BulkInsertSuite) run() {
// s.Equal(nq*topk, len(searchResult.GetResults().GetScores()))
}
func (s *BulkInsertSuite) TestGeometryTypes() {
s.testType = schemapb.DataType_Geometry
s.expr = "st_equals(" + "testField" + schemapb.DataType_name[int32(s.testType)] + ",'POINT (-84.036 39.997)')"
s.run()
}
func (s *BulkInsertSuite) TestMultiFileTypes() {
fileTypeArr := []importutilv2.FileType{importutilv2.JSON, importutilv2.Numpy, importutilv2.Parquet, importutilv2.CSV}

Some files were not shown because too many files have changed in this diff Show More