diff --git a/Makefile b/Makefile index 55d31a3..1697e4d 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ all: test cover: go test -cover -tags=integration -generate-proto: +generate: protoc --go_out=. internal/public.proto test: diff --git a/client.go b/client.go index 3f26a22..916cc4a 100644 --- a/client.go +++ b/client.go @@ -36,9 +36,11 @@ import ( "bytes" "encoding/json" "fmt" + "io" "io/ioutil" "net" "net/http" + "sort" "time" "github.com/golang/protobuf/proto" @@ -181,6 +183,97 @@ func (c *Client) Schema() (*Schema, error) { return schema, nil } +func (c *Client) ImportFrame(frame *Frame, bitIterator *CSVBitIterator, batchSize uint) error { + const sliceWidth = 1048576 + canContinue := true + bitGroup := map[uint64][]Bit{} + var currentBatchSize uint + indexName := frame.index.name + frameName := frame.name + + callback := func(bit Bit) bool { + slice := bit.ColumnID / sliceWidth + if sliceArray, ok := bitGroup[slice]; ok { + bitGroup[slice] = append(sliceArray, bit) + } else { + bitGroup[slice] = []Bit{bit} + } + currentBatchSize++ + return currentBatchSize < batchSize + } + for canContinue { + err := bitIterator.Iterate(callback) + if err == io.EOF { + canContinue = false + } else if err != nil { + return err + } + for slice, bits := range bitGroup { + err := c.importBits(indexName, frameName, slice, bits) + if err != nil { + return err + } + } + } + + return nil +} + +func (c *Client) importBits(indexName string, frameName string, slice uint64, bits []Bit) error { + // The maximum ingestion speed is accomplished by sorting bits by row ID and then column ID + sort.Slice(bits, func(i, j int) bool { + bit := bits[i] + other := bits[j] + bitCmp := bit.RowID - other.RowID + if bitCmp == 0 { + return bit.ColumnID < other.ColumnID + } + return bitCmp < 0 + }) + nodes, err := c.fetchFragmentNodes(indexName, slice) + if err != nil { + return err + } + for _, node := range nodes { + uri, err := NewURIFromAddress(node.Host) + if err != nil { + return err + } + client := NewClientWithURI(uri) + err = client.importNode(bitsToImportRequest(indexName, frameName, slice, bits)) + if err != nil { + return err + } + } + + return nil +} + +func (c *Client) fetchFragmentNodes(indexName string, slice uint64) ([]FragmentNode, error) { + path := fmt.Sprintf("/fragment/nodes?slice=%d&index=%s", slice, indexName) + _, body, err := c.httpRequest("GET", path, []byte{}, errorCheckedResponse) + if err != nil { + return nil, err + } + fragmentNodes := []FragmentNode{} + err = json.Unmarshal(body, &fragmentNodes) + if err != nil { + return nil, err + } + return fragmentNodes, nil +} + +func (c *Client) importNode(request *internal.ImportRequest) error { + data, _ := proto.Marshal(request) + // request.Marshal never returns an error + _, _, err := c.httpRequest("POST", "/import", data, errorCheckedResponse) + if err != nil { + return err + } + + return nil +} + func (c *Client) patchIndexTimeQuantum(index *Index) error { data := []byte(fmt.Sprintf(`{"timeQuantum": "%s"}`, index.options.TimeQuantum)) path := fmt.Sprintf("/index/%s/time-quantum", index.name) @@ -273,6 +366,25 @@ func matchError(msg string) error { return nil } +func bitsToImportRequest(indexName string, frameName string, slice uint64, bits []Bit) *internal.ImportRequest { + bitmapIDs := make([]uint64, 0, len(bits)) + columnIDs := make([]uint64, 0, len(bits)) + timestamps := make([]int64, 0, len(bits)) + for _, bit := range bits { + bitmapIDs = append(bitmapIDs, bit.RowID) + columnIDs = append(columnIDs, bit.ColumnID) + timestamps = append(timestamps, bit.Timestamp) + } + return &internal.ImportRequest{ + Index: indexName, + Frame: frameName, + Slice: slice, + RowIDs: bitmapIDs, + ColumnIDs: columnIDs, + Timestamps: timestamps, + } +} + // ClientOptions control the properties of client connection to the server type ClientOptions struct { SocketTimeout time.Duration @@ -325,3 +437,8 @@ const ( rawResponse errorCheckedResponse ) + +type FragmentNode struct { + Host string + InternalHost string +} diff --git a/client_it_test.go b/client_it_test.go index b573694..f7a234a 100644 --- a/client_it_test.go +++ b/client_it_test.go @@ -36,12 +36,14 @@ package pilosa import ( "bytes" + "errors" "io" "net/http" "net/http/httptest" "os" "reflect" "strconv" + "strings" "testing" "time" @@ -242,6 +244,39 @@ func TestTopNReturns(t *testing.T) { } } +func TestIntersectReturns(t *testing.T) { + client := getClient() + options := &FrameOptions{ + RowLabel: "segment_id", + } + frame, err := index.Frame("segments", options) + if err != nil { + t.Fatal(err) + } + err = client.EnsureFrame(frame) + if err != nil { + t.Fatal(err) + } + qry1 := index.BatchQuery( + frame.SetBit(2, 10), + frame.SetBit(2, 15), + frame.SetBit(3, 10), + frame.SetBit(3, 20), + ) + client.Query(qry1, nil) + qry2 := index.Intersect(frame.Bitmap(2), frame.Bitmap(3)) + response, err := client.Query(qry2, nil) + if err != nil { + t.Fatal(err) + } + if len(response.Results()) != 1 { + t.Fatal("There must be 1 result") + } + if !reflect.DeepEqual(response.Result().Bitmap.Bits, []uint64{10}) { + t.Fatal("Returned bits must be: [10]") + } +} + func TestCreateDeleteIndexFrame(t *testing.T) { client := getClient() index1, err := NewIndex("to-be-deleted", nil) @@ -502,6 +537,85 @@ func TestInvalidSchema(t *testing.T) { } } +func TestCSVImport(t *testing.T) { + client := getClient() + text := ` + 10,5 + 2,3 + 10,7 + 7,1 + ` + iterator := NewCSVBitIterator(strings.NewReader(text)) + frame, err := index.Frame("importframe", nil) + if err != nil { + t.Fatal(err) + } + err = client.EnsureFrame(frame) + if err != nil { + t.Fatal(err) + } + err = client.ImportFrame(frame, iterator, 10) + if err != nil { + t.Fatal(err) + } + + target := []uint64{3, 1, 5} + bq := index.BatchQuery( + frame.Bitmap(2), + frame.Bitmap(7), + frame.Bitmap(10), + ) + response, err := client.Query(bq, nil) + if len(response.Results()) != 3 { + t.Fatalf("Result count should be 3") + } + for i, result := range response.Results() { + br := result.Bitmap + if target[i] != br.Bits[0] { + t.Fatalf("%d != %d", target[i], br.Bits[0]) + } + } +} + +func TestFetchFragmentNodes(t *testing.T) { + client := getClient() + nodes, err := client.fetchFragmentNodes(index.Name(), 0) + if err != nil { + t.Fatal(err) + } + if len(nodes) != 1 { + t.Fatalf("1 node should be returned") + } +} + +func TestImportBitIteratorError(t *testing.T) { + client := getClient() + frame, err := index.Frame("not-important", nil) + if err != nil { + t.Fatal(err) + } + iterator := NewCSVBitIterator(&BrokenReader{}) + err = client.ImportFrame(frame, iterator, 100) + if err == nil { + t.Fatalf("import frame should fail with broken reader") + } +} + +func TestImportFailsForFetchFrameError(t *testing.T) { + client := getClient() + frame, err := index.Frame("not-important", nil) + if err != nil { + t.Fatal(err) + } + iterator := NewCSVBitIterator(strings.NewReader("1,10")) + server := getMockServer(500, []byte{}, 0) + defer server.Close() + err = client.ImportFrame(frame, iterator, 100) + if err == nil { + t.Fatalf("import frame should fail when fetch frames fails") + } +} + func TestResponseWithInvalidType(t *testing.T) { qr := &internal.QueryResponse{ Err: "", @@ -556,3 +670,9 @@ func getMockServer(statusCode int, response []byte, contentLength int) *httptest }) return httptest.NewServer(handler) } + +type BrokenReader struct{} + +func (r BrokenReader) Read(p []byte) (n int, err error) { + return 0, errors.New("broken reader") +} diff --git a/fixture/sample1.csv b/fixture/sample1.csv new file mode 100644 index 0000000..d5cdd21 --- /dev/null +++ b/fixture/sample1.csv @@ -0,0 +1,3 @@ +1,10,683793200 +5,20,683793300 +3,41,683793385 diff --git a/imports.go b/imports.go new file mode 100644 index 0000000..83cbdc3 --- /dev/null +++ b/imports.go @@ -0,0 +1,117 @@ +// Copyright 2017 Pilosa Corp. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. + +package pilosa + +import ( + "bufio" + "fmt" + "io" + "strconv" + "strings" +) + +// Bit defines a single Pilosa bit. +type Bit struct { + RowID uint64 + ColumnID uint64 + Timestamp int64 +} + +// BitIteratorCallback gets called for each bit in a stream. +// return false to pause iteration. +type BitIteratorCallback func(bit Bit) bool + +// CSVBitIterator reads bits from a Reader. +// Each line should contain a single bit in the following form: +// rowID,columnID[,timestamp] +type CSVBitIterator struct { + reader io.Reader + line int + scanner *bufio.Scanner +} + +// NewCSVBitIterator creates a CSVBitIterator from a Reader. +func NewCSVBitIterator(reader io.Reader) *CSVBitIterator { + return &CSVBitIterator{ + reader: reader, + line: 0, + } +} + +// Iterate iterates on all lines of a Reader. +// If the callback returns false, the iteration is paused; call it again to resume. +// Returns io.EOF on end of iteration +func (c *CSVBitIterator) Iterate(callback BitIteratorCallback) error { + if c.scanner == nil { + c.scanner = bufio.NewScanner(c.reader) + } + + for c.scanner.Scan() { + c.line++ + text := strings.TrimSpace(c.scanner.Text()) + if text != "" { + parts := strings.Split(text, ",") + if len(parts) < 2 { + return fmt.Errorf("Invalid CSV line: %d", c.line) + } + rowID, err := strconv.Atoi(parts[0]) + if err != nil { + return fmt.Errorf("Invalid row ID at line: %d", c.line) + } + columnID, err := strconv.Atoi(parts[1]) + if err != nil { + return fmt.Errorf("Invalid column ID at line: %d", c.line) + } + timestamp := 0 + if len(parts) == 3 { + timestamp, err = strconv.Atoi(parts[2]) + if err != nil { + return fmt.Errorf("Invalid timestamp at line: %d", c.line) + } + } + bit := Bit{ + RowID: uint64(rowID), + ColumnID: uint64(columnID), + Timestamp: int64(timestamp), + } + if ok := callback(bit); !ok { + return nil + } + } + } + err := c.scanner.Err() + if err != nil { + return err + } + return io.EOF +} diff --git a/imports_it_test.go b/imports_it_test.go new file mode 100644 index 0000000..3f54c18 --- /dev/null +++ b/imports_it_test.go @@ -0,0 +1,83 @@ +// +build integration + +// Copyright 2017 Pilosa Corp. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. + +package pilosa + +import ( + "os" + "path" + "reflect" + "testing" +) + +func TestCSVBitIterator(t *testing.T) { + cwd, err := os.Getwd() + if err != nil { + t.Fatal(err) + } + csvFilename := path.Join(cwd, "fixture", "sample1.csv") + file, err := os.Open(csvFilename) + if err != nil { + t.Fatal(err) + } + defer file.Close() + iterator := NewCSVBitIterator(file) + if err != nil { + t.Fatal(err) + } + bits := []Bit{} + // simulates partial iteration + iterator.Iterate(func(bit Bit) bool { + bits = append(bits, bit) + return len(bits) != 2 + }) + if len(bits) != 2 { + t.Fatalf("There should be 2 bits") + } + iterator.Iterate(func(bit Bit) bool { + bits = append(bits, bit) + return true + }) + if len(bits) != 3 { + t.Fatalf("There should be 3 bits") + } + target := []Bit{ + Bit{1, 10, 683793200}, + Bit{5, 20, 683793300}, + Bit{3, 41, 683793385}, + } + if !reflect.DeepEqual(target, bits) { + t.Fatalf("%v != %v", target, bits) + } +} diff --git a/imports_test.go b/imports_test.go new file mode 100644 index 0000000..0e6eb56 --- /dev/null +++ b/imports_test.go @@ -0,0 +1,76 @@ +// Copyright 2017 Pilosa Corp. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions +// are met: +// +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its +// contributors may be used to endorse or promote products derived +// from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND +// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, +// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +// DAMAGE. + +package pilosa_test + +import ( + "strings" + "testing" + + "errors" + + pilosa "github.com/pilosa/go-pilosa" +) + +func TestCSVBitIteratorInvalidInput(t *testing.T) { + invalidInputs := []string{ + // less than 2 columns + "155", + // invalid row ID + "a5,155", + // invalid column ID + "155,a5", + // invalid timestamp + "155,255,a5", + } + for _, text := range invalidInputs { + iterator := pilosa.NewCSVBitIterator(strings.NewReader(text)) + err := iterator.Iterate(func(b pilosa.Bit) bool { return true }) + if err == nil { + t.Fatalf("CSVBitIterator input: %s should fail", text) + } + } +} + +func TestCSVBitIteratorError(t *testing.T) { + iterator := pilosa.NewCSVBitIterator(&BrokenReader{}) + err := iterator.Iterate(func(b pilosa.Bit) bool { return true }) + if err == nil { + t.Fatal("CSVBitIterator should fail with error") + } +} + +type BrokenReader struct{} + +func (r BrokenReader) Read(p []byte) (n int, err error) { + return 0, errors.New("broken reader") +} diff --git a/internal/public.pb.go b/internal/public.pb.go index 9b7896a..d085a88 100644 --- a/internal/public.pb.go +++ b/internal/public.pb.go @@ -1,34 +1,6 @@ -// Copyright 2017 Pilosa Corp. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions -// are met: -// -// 1. Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. Neither the name of the copyright holder nor the names of its -// contributors may be used to endorse or promote products derived -// from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND -// CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, -// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. +// Code generated by protoc-gen-go. +// source: internal/public.proto +// DO NOT EDIT! /* Package internal is a generated protocol buffer package. @@ -362,7 +334,7 @@ func (m *QueryResult) GetChanged() bool { } type ImportRequest struct { - DB string `protobuf:"bytes,1,opt,name=DB" json:"DB,omitempty"` + Index string `protobuf:"bytes,1,opt,name=Index" json:"Index,omitempty"` Frame string `protobuf:"bytes,2,opt,name=Frame" json:"Frame,omitempty"` Slice uint64 `protobuf:"varint,3,opt,name=Slice" json:"Slice,omitempty"` RowIDs []uint64 `protobuf:"varint,4,rep,packed,name=RowIDs" json:"RowIDs,omitempty"` @@ -375,9 +347,9 @@ func (m *ImportRequest) String() string { return proto.CompactTextStr func (*ImportRequest) ProtoMessage() {} func (*ImportRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{9} } -func (m *ImportRequest) GetDB() string { +func (m *ImportRequest) GetIndex() string { if m != nil { - return m.DB + return m.Index } return "" } @@ -433,40 +405,40 @@ func init() { func init() { proto.RegisterFile("internal/public.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 556 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x8a, 0xd4, 0x40, - 0x10, 0xa6, 0x93, 0xcc, 0x5f, 0xcd, 0xce, 0xb0, 0x34, 0xae, 0x06, 0x11, 0x09, 0xc1, 0x43, 0x4e, - 0x33, 0xb0, 0x3e, 0x80, 0x98, 0x99, 0x59, 0x18, 0xc4, 0xc5, 0xad, 0x59, 0xbd, 0x67, 0xd7, 0x66, - 0x0d, 0xe4, 0xcf, 0xee, 0x0e, 0x32, 0x0f, 0xe0, 0x5d, 0xf0, 0x09, 0xbc, 0xf9, 0x98, 0x52, 0xdd, - 0xe9, 0x49, 0xd6, 0x83, 0x78, 0xeb, 0xef, 0xab, 0xae, 0x4e, 0x7d, 0xf5, 0x55, 0x05, 0x2e, 0xf2, - 0x4a, 0x0b, 0x59, 0x65, 0xc5, 0xba, 0x69, 0xef, 0x8a, 0xfc, 0x7e, 0xd5, 0xc8, 0x5a, 0xd7, 0x7c, - 0xea, 0xe8, 0x38, 0x85, 0x71, 0x9a, 0xeb, 0x32, 0x6b, 0x38, 0x87, 0x20, 0xcd, 0xb5, 0x0a, 0x59, - 0xe4, 0x27, 0x01, 0x9a, 0x33, 0x7f, 0x05, 0xa3, 0xb7, 0x5a, 0x4b, 0x15, 0x7a, 0x91, 0x9f, 0xcc, - 0x2f, 0x97, 0x2b, 0x97, 0xb7, 0x22, 0x1a, 0x6d, 0x30, 0x5e, 0x41, 0xf0, 0x21, 0xcb, 0x25, 0x3f, - 0x07, 0xff, 0x9d, 0x38, 0x86, 0x2c, 0x62, 0x49, 0x80, 0x74, 0xe4, 0x4f, 0x60, 0xb4, 0xa9, 0xdb, - 0x4a, 0x87, 0x9e, 0xe1, 0x2c, 0x88, 0x3f, 0x82, 0x9f, 0xe6, 0x9a, 0x82, 0x58, 0x7f, 0xdb, 0x6f, - 0xbb, 0x04, 0x0b, 0xf8, 0x73, 0x98, 0x6e, 0xea, 0xa2, 0x2d, 0xab, 0xfd, 0xb6, 0xcb, 0x3a, 0x61, - 0xfe, 0x02, 0x66, 0xb7, 0x79, 0x29, 0x94, 0xce, 0xca, 0x26, 0xf4, 0x23, 0x96, 0xf8, 0xd8, 0x13, - 0xf1, 0x0e, 0x16, 0xf6, 0x26, 0x55, 0x75, 0x10, 0x9a, 0x2f, 0xc1, 0x3b, 0xbd, 0xee, 0xed, 0xb7, - 0xff, 0xa9, 0xe6, 0x37, 0x83, 0x80, 0x4e, 0x43, 0x39, 0x33, 0x2b, 0x87, 0x43, 0x70, 0x7b, 0x6c, - 0x44, 0x57, 0x97, 0x39, 0xf3, 0x08, 0xe6, 0x07, 0x2d, 0xf3, 0xea, 0xe1, 0x53, 0x56, 0xb4, 0xc2, - 0x54, 0x35, 0xc3, 0x21, 0x45, 0x8a, 0xf6, 0x95, 0xb6, 0xe1, 0xc0, 0x14, 0x7d, 0xc2, 0xa4, 0x28, - 0xad, 0xeb, 0xc2, 0x06, 0x47, 0x11, 0x4b, 0xa6, 0xd8, 0x13, 0xfc, 0x25, 0xc0, 0x55, 0x51, 0x67, - 0x5d, 0xee, 0x38, 0x62, 0x09, 0xc3, 0x01, 0x13, 0xaf, 0x61, 0x42, 0x95, 0xbe, 0xcf, 0x9a, 0x5e, - 0x1b, 0xfb, 0x97, 0xb6, 0x1f, 0x0c, 0xce, 0x6e, 0x5a, 0x21, 0x8f, 0x28, 0xbe, 0xb6, 0x42, 0x19, - 0x0f, 0x0c, 0xee, 0x54, 0x5a, 0xc0, 0x9f, 0xc2, 0xf8, 0x50, 0xe4, 0xf7, 0xc2, 0x76, 0x2a, 0xc0, - 0x0e, 0x91, 0xd6, 0xbe, 0xc3, 0xca, 0x68, 0x9d, 0xe2, 0x90, 0xe2, 0x21, 0x4c, 0x6e, 0xda, 0xac, - 0xd2, 0x6d, 0x69, 0xa4, 0xce, 0xd0, 0x41, 0x7a, 0x13, 0x45, 0x59, 0x6b, 0x27, 0xb3, 0x43, 0xf1, - 0x4f, 0x06, 0x8b, 0xae, 0x24, 0xd5, 0xd4, 0x95, 0x12, 0xd4, 0xf7, 0x9d, 0x94, 0xae, 0xef, 0x3b, - 0x29, 0xf9, 0x1a, 0x26, 0x28, 0x54, 0x5b, 0x68, 0x67, 0xdd, 0x45, 0x2f, 0xcf, 0xe5, 0xb6, 0x85, - 0x46, 0x77, 0x8b, 0xbf, 0x81, 0xe5, 0xa3, 0x51, 0xa0, 0x5a, 0x29, 0xef, 0x59, 0x9f, 0xf7, 0x28, - 0x8e, 0x7f, 0x5d, 0x8f, 0xbf, 0x33, 0x98, 0x0f, 0x5e, 0xe6, 0x89, 0x5b, 0x13, 0x53, 0xd6, 0xfc, - 0xf2, 0xbc, 0x7f, 0xc8, 0xf2, 0xe8, 0xd6, 0xe8, 0x0c, 0xd8, 0x75, 0x37, 0x20, 0xec, 0x9a, 0x6c, - 0xa1, 0xd5, 0x70, 0xdf, 0x1f, 0xd8, 0x42, 0x34, 0xda, 0x20, 0x75, 0x6d, 0xf3, 0x25, 0xab, 0x1e, - 0xc4, 0x67, 0xd3, 0xb5, 0x29, 0x3a, 0x18, 0xff, 0x62, 0xb0, 0xd8, 0x97, 0x4d, 0x2d, 0xb5, 0x73, - 0x6c, 0x09, 0xde, 0x36, 0xed, 0x9a, 0xe3, 0x6d, 0x53, 0x72, 0xf0, 0x4a, 0x66, 0xa5, 0x1d, 0xca, - 0x19, 0x5a, 0x40, 0xac, 0xf1, 0xcc, 0x78, 0x14, 0xa0, 0x05, 0xc6, 0x03, 0x5a, 0x32, 0x15, 0x06, - 0xd6, 0x57, 0x8b, 0x68, 0x0a, 0xdd, 0x8e, 0xa9, 0x70, 0x64, 0x42, 0x3d, 0x41, 0x53, 0x78, 0x5a, - 0x32, 0x15, 0x8e, 0x23, 0x3f, 0xf1, 0x71, 0xc0, 0xdc, 0x8d, 0xcd, 0x3f, 0xe5, 0xf5, 0x9f, 0x00, - 0x00, 0x00, 0xff, 0xff, 0x5d, 0x87, 0x06, 0x79, 0x6c, 0x04, 0x00, 0x00, + // 555 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x8c, 0x54, 0xcd, 0x6e, 0xd4, 0x30, + 0x10, 0x96, 0x37, 0xd9, 0xed, 0xee, 0x6c, 0x5b, 0x55, 0x16, 0x85, 0x08, 0x21, 0x14, 0x45, 0x1c, + 0x72, 0xda, 0x95, 0xca, 0x03, 0x20, 0xf6, 0xa7, 0x52, 0x84, 0xa8, 0xe8, 0x6c, 0xe1, 0x9e, 0xb6, + 0x56, 0x89, 0x94, 0xc4, 0xc1, 0x76, 0x04, 0xfb, 0x00, 0xdc, 0x91, 0x78, 0x08, 0x78, 0x4c, 0x34, + 0x76, 0xbc, 0x49, 0x39, 0x20, 0x6e, 0xfe, 0xbe, 0xf1, 0x38, 0xf3, 0xcd, 0x37, 0x13, 0x38, 0x2f, + 0x6a, 0x23, 0x54, 0x9d, 0x97, 0xcb, 0xa6, 0xbd, 0x2d, 0x8b, 0xbb, 0x45, 0xa3, 0xa4, 0x91, 0x7c, + 0xea, 0xe9, 0x64, 0x05, 0x93, 0x55, 0x61, 0xaa, 0xbc, 0xe1, 0x1c, 0xc2, 0x55, 0x61, 0x74, 0xc4, + 0xe2, 0x20, 0x0d, 0xd1, 0x9e, 0xf9, 0x2b, 0x18, 0xbf, 0x35, 0x46, 0xe9, 0x68, 0x14, 0x07, 0xe9, + 0xfc, 0xe2, 0x74, 0xe1, 0xf3, 0x16, 0x44, 0xa3, 0x0b, 0x26, 0x0b, 0x08, 0x3f, 0xe4, 0x85, 0xe2, + 0x67, 0x10, 0xbc, 0x13, 0xfb, 0x88, 0xc5, 0x2c, 0x0d, 0x91, 0x8e, 0xfc, 0x09, 0x8c, 0xd7, 0xb2, + 0xad, 0x4d, 0x34, 0xb2, 0x9c, 0x03, 0xc9, 0x47, 0x08, 0x56, 0x85, 0xa1, 0x20, 0xca, 0xaf, 0xd9, + 0xa6, 0x4b, 0x70, 0x80, 0x3f, 0x87, 0xe9, 0x5a, 0x96, 0x6d, 0x55, 0x67, 0x9b, 0x2e, 0xeb, 0x80, + 0xf9, 0x0b, 0x98, 0xdd, 0x14, 0x95, 0xd0, 0x26, 0xaf, 0x9a, 0x28, 0x88, 0x59, 0x1a, 0x60, 0x4f, + 0x24, 0x5b, 0x38, 0x71, 0x37, 0xa9, 0xaa, 0x9d, 0x30, 0xfc, 0x14, 0x46, 0x87, 0xd7, 0x47, 0xd9, + 0xe6, 0x3f, 0xd5, 0xfc, 0x66, 0x10, 0xd2, 0x69, 0x28, 0x67, 0xe6, 0xe4, 0x70, 0x08, 0x6f, 0xf6, + 0x8d, 0xe8, 0xea, 0xb2, 0x67, 0x1e, 0xc3, 0x7c, 0x67, 0x54, 0x51, 0x3f, 0x7c, 0xca, 0xcb, 0x56, + 0xd8, 0xaa, 0x66, 0x38, 0xa4, 0x48, 0x51, 0x56, 0x1b, 0x17, 0x0e, 0x6d, 0xd1, 0x07, 0x4c, 0x8a, + 0x56, 0x52, 0x96, 0x2e, 0x38, 0x8e, 0x59, 0x3a, 0xc5, 0x9e, 0xe0, 0x2f, 0x01, 0x2e, 0x4b, 0x99, + 0x77, 0xb9, 0x93, 0x98, 0xa5, 0x0c, 0x07, 0x4c, 0xb2, 0x84, 0x23, 0xaa, 0xf4, 0x7d, 0xde, 0xf4, + 0xda, 0xd8, 0xbf, 0xb4, 0xfd, 0x60, 0x70, 0x7c, 0xdd, 0x0a, 0xb5, 0x47, 0xf1, 0xa5, 0x15, 0xda, + 0x7a, 0x60, 0x71, 0xa7, 0xd2, 0x01, 0xfe, 0x14, 0x26, 0xbb, 0xb2, 0xb8, 0x13, 0xae, 0x53, 0x21, + 0x76, 0x88, 0xb4, 0xf6, 0x1d, 0xd6, 0x56, 0xeb, 0x14, 0x87, 0x14, 0x8f, 0xe0, 0xe8, 0xba, 0xcd, + 0x6b, 0xd3, 0x56, 0x56, 0xea, 0x0c, 0x3d, 0xa4, 0x37, 0x51, 0x54, 0xd2, 0x78, 0x99, 0x1d, 0x4a, + 0x7e, 0x32, 0x38, 0xe9, 0x4a, 0xd2, 0x8d, 0xac, 0xb5, 0xa0, 0xbe, 0x6f, 0x95, 0xf2, 0x7d, 0xdf, + 0x2a, 0xc5, 0x97, 0x70, 0x84, 0x42, 0xb7, 0xa5, 0xf1, 0xd6, 0x9d, 0xf7, 0xf2, 0x7c, 0x6e, 0x5b, + 0x1a, 0xf4, 0xb7, 0xf8, 0x1b, 0x38, 0x7d, 0x34, 0x0a, 0x54, 0x2b, 0xe5, 0x3d, 0xeb, 0xf3, 0x1e, + 0xc5, 0xf1, 0xaf, 0xeb, 0xc9, 0x77, 0x06, 0xf3, 0xc1, 0xcb, 0x3c, 0xf5, 0x6b, 0x62, 0xcb, 0x9a, + 0x5f, 0x9c, 0xf5, 0x0f, 0x39, 0x1e, 0xfd, 0x1a, 0x1d, 0x03, 0xbb, 0xea, 0x06, 0x84, 0x5d, 0x91, + 0x2d, 0xb4, 0x1a, 0xfe, 0xfb, 0x03, 0x5b, 0x88, 0x46, 0x17, 0xa4, 0xae, 0xad, 0x3f, 0xe7, 0xf5, + 0x83, 0xb8, 0xb7, 0x5d, 0x9b, 0xa2, 0x87, 0xc9, 0x2f, 0x06, 0x27, 0x59, 0xd5, 0x48, 0x65, 0x06, + 0x8e, 0x65, 0xf5, 0xbd, 0xf8, 0xe6, 0x1d, 0xb3, 0x80, 0xd8, 0x4b, 0x95, 0x57, 0x6e, 0x34, 0x67, + 0xe8, 0x00, 0xb1, 0xd6, 0x39, 0xeb, 0x54, 0x88, 0x0e, 0x58, 0x27, 0x68, 0xd5, 0x74, 0x14, 0x3a, + 0x77, 0x1d, 0xa2, 0x59, 0xf4, 0x9b, 0xa6, 0xa3, 0xb1, 0x0d, 0xf5, 0x04, 0xcd, 0xe2, 0x61, 0xd5, + 0x74, 0x34, 0x89, 0x83, 0x34, 0xc0, 0x01, 0x73, 0x3b, 0xb1, 0x7f, 0x96, 0xd7, 0x7f, 0x02, 0x00, + 0x00, 0xff, 0xff, 0xc5, 0xdb, 0xf7, 0x24, 0x72, 0x04, 0x00, 0x00, } diff --git a/internal/public.proto b/internal/public.proto index 91c1f31..571fe03 100644 --- a/internal/public.proto +++ b/internal/public.proto @@ -58,7 +58,7 @@ message QueryResult { } message ImportRequest { - string DB = 1; + string Index = 1; string Frame = 2; uint64 Slice = 3; repeated uint64 RowIDs = 4;