1958 lines · 74.5 KB · Go
RawDownload
// Copyright (c) 2015-2021 MinIO, Inc.//// This file is part of MinIO Object Storage stack//// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU Affero General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the// GNU Affero General Public License for more details.//// You should have received a copy of the GNU Affero General Public License// along with this program.  If not, see <http://www.gnu.org/licenses/>. package s3select import (	"bytes"	"encoding/xml"	"fmt"	"io"	"io/ioutil"	"net/http"	"os"	"reflect"	"strings"	"testing" 	"github.com/klauspost/cpuid/v2"	"github.com/minio/minio-go/v7"	"github.com/minio/simdjson-go") func newStringRSC(s string) io.ReadSeekCloser {	return newBytesRSC([]byte(s))} func newBytesRSC(b []byte) io.ReadSeekCloser {	r := bytes.NewReader(b)	segmentReader := func(offset int64) (io.ReadCloser, error) {		_, err := r.Seek(offset, io.SeekStart)		if err != nil {			return nil, err		}		return io.NopCloser(r), nil	}	return NewObjectReadSeekCloser(segmentReader, int64(len(b)))} type testResponseWriter struct {	statusCode int	response   []byte} func (w *testResponseWriter) Header() http.Header {	return nil} func (w *testResponseWriter) Write(p []byte) (int, error) {	w.response = append(w.response, p...)	return len(p), nil} func (w *testResponseWriter) WriteHeader(statusCode int) {	w.statusCode = statusCode} func (w *testResponseWriter) Flush() {} func TestJSONQueries(t *testing.T) {	input := `{"id": 0,"title": "Test Record","desc": "Some text","synonyms": ["foo", "bar", "whatever"]}	{"id": 1,"title": "Second Record","desc": "another text","synonyms": ["some", "synonym", "value"]}	{"id": 2,"title": "Second Record","desc": "another text","numbers": [2, 3.0, 4]}	{"id": 3,"title": "Second Record","desc": "another text","nested": [[2, 3.0, 4], [7, 8.5, 9]]}` 	testTable := []struct {		name       string		query      string		requestXML []byte // override request XML		wantResult string		withJSON   string // Override JSON input	}{		{			name:       "select-in-array-full",			query:      `SELECT * from s3object s WHERE 'bar' IN s.synonyms[*]`,			wantResult: `{"id":0,"title":"Test Record","desc":"Some text","synonyms":["foo","bar","whatever"]}`,		},		{			name:  "simple-in-array",			query: `SELECT * from s3object s WHERE s.id IN (1,3)`,			wantResult: `{"id":1,"title":"Second Record","desc":"another text","synonyms":["some","synonym","value"]}{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "select-in-array-single",			query:      `SELECT synonyms from s3object s WHERE 'bar' IN s.synonyms[*] `,			wantResult: `{"synonyms":["foo","bar","whatever"]}`,		},		{			name:       "donatello-1",			query:      `SELECT * from s3object s WHERE 'bar' in s.synonyms`,			wantResult: `{"id":0,"title":"Test Record","desc":"Some text","synonyms":["foo","bar","whatever"]}`,		},		{			name:       "donatello-2",			query:      `SELECT * from s3object s WHERE 'bar' in s.synonyms[*]`,			wantResult: `{"id":0,"title":"Test Record","desc":"Some text","synonyms":["foo","bar","whatever"]}`,		},		{			name:  "bignum-1",			query: `SELECT id from s3object s WHERE s.id <= 9223372036854775807`,			wantResult: `{"id":0}{"id":1}{"id":2}{"id":3}`,		},		{			name:  "bignum-2",			query: `SELECT id from s3object s WHERE s.id >= -9223372036854775808`,			wantResult: `{"id":0}{"id":1}{"id":2}{"id":3}`,		},		{			name:       "donatello-3",			query:      `SELECT * from s3object s WHERE 'value' IN s.synonyms[*]`,			wantResult: `{"id":1,"title":"Second Record","desc":"another text","synonyms":["some","synonym","value"]}`,		},		{			name:       "select-in-number",			query:      `SELECT * from s3object s WHERE 4 in s.numbers[*]`,			wantResult: `{"id":2,"title":"Second Record","desc":"another text","numbers":[2,3,4]}`,		},		{			name:       "select-in-number-float",			query:      `SELECT * from s3object s WHERE 3 in s.numbers[*]`,			wantResult: `{"id":2,"title":"Second Record","desc":"another text","numbers":[2,3,4]}`,		},		{			name:       "select-in-number-float-in-sql",			query:      `SELECT * from s3object s WHERE 3.0 in s.numbers[*]`,			wantResult: `{"id":2,"title":"Second Record","desc":"another text","numbers":[2,3,4]}`,		},		{			name:       "select-in-list-match",			query:      `SELECT * from s3object s WHERE (2,3,4) IN s.nested[*]`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "select-in-nested-float",			query:      `SELECT s.nested from s3object s WHERE 8.5 IN s.nested[*][*]`,			wantResult: `{"nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "select-in-combine-and",			query:      `SELECT s.nested from s3object s WHERE (8.5 IN s.nested[*][*]) AND (s.id > 0)`,			wantResult: `{"nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "select-in-combine-and-no",			query:      `SELECT s.nested from s3object s WHERE (8.5 IN s.nested[*][*]) AND (s.id = 0)`,			wantResult: ``,		},		{			name:       "select-in-nested-float-no-flat",			query:      `SELECT s.nested from s3object s WHERE 8.5 IN s.nested[*]`,			wantResult: ``,		},		{			name:       "select-empty-field-result",			query:      `SELECT * from s3object s WHERE s.nested[0][0] = 2`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "select-arrays-specific",			query:      `SELECT * from s3object s WHERE s.nested[1][0] = 7`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "wrong-index-no-result",			query:      `SELECT * from s3object s WHERE s.nested[0][0] = 7`,			wantResult: ``,		},		{			name:  "not-equal-result",			query: `SELECT * from s3object s WHERE s.nested[1][0] != 7`,			wantResult: `{"id":0,"title":"Test Record","desc":"Some text","synonyms":["foo","bar","whatever"]}{"id":1,"title":"Second Record","desc":"another text","synonyms":["some","synonym","value"]}{"id":2,"title":"Second Record","desc":"another text","numbers":[2,3,4]}`,		},		{			name:       "indexed-list-match",			query:      `SELECT * from s3object s WHERE (7,8.5,9) IN s.nested[1]`,			wantResult: ``,		},		{			name:       "indexed-list-match-equals",			query:      `SELECT * from s3object s WHERE (7,8.5,9) = s.nested[1]`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "indexed-list-match-equals-s-star",			query:      `SELECT s.* from s3object s WHERE (7,8.5,9) = s.nested[1]`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "indexed-list-match-equals-s-index",			query:      `SELECT s.nested[1], s.nested[0] from s3object s WHERE (7,8.5,9) = s.nested[1]`,			wantResult: `{"_1":[7,8.5,9],"_2":[2,3,4]}`,		},		{			name:  "indexed-list-match-not-equals",			query: `SELECT * from s3object s WHERE (7,8.5,9) != s.nested[1]`,			wantResult: `{"id":0,"title":"Test Record","desc":"Some text","synonyms":["foo","bar","whatever"]}{"id":1,"title":"Second Record","desc":"another text","synonyms":["some","synonym","value"]}{"id":2,"title":"Second Record","desc":"another text","numbers":[2,3,4]}`,		},		{			name:       "indexed-list-square-bracket",			query:      `SELECT * from s3object s WHERE [7,8.5,9] = s.nested[1]`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "indexed-list-square-bracket",			query:      `SELECT * from s3object s WHERE [7,8.5,9] IN s.nested`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:  "indexed-list-square-bracket",			query: `SELECT * from s3object s WHERE id IN [3,2]`,			wantResult: `{"id":2,"title":"Second Record","desc":"another text","numbers":[2,3,4]}{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "index-wildcard-in",			query:      `SELECT * from s3object s WHERE (8.5) IN s.nested[1][*]`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "index-wildcard-in",			query:      `SELECT * from s3object s WHERE (8.0+0.5) IN s.nested[1][*]`,			wantResult: `{"id":3,"title":"Second Record","desc":"another text","nested":[[2,3,4],[7,8.5,9]]}`,		},		{			name:       "compare-mixed",			query:      `SELECT id from s3object s WHERE value = true`,			wantResult: `{"id":1}`,			withJSON: `{"id":0, "value": false}{"id":1, "value": true}{"id":2, "value": 42}{"id":3, "value": "true"}`,		},		{			name:       "compare-mixed-not",			query:      `SELECT COUNT(id) as n from s3object s WHERE value != true`,			wantResult: `{"n":3}`,			withJSON: `{"id":0, "value": false}{"id":1, "value": true}{"id":2, "value": 42}{"id":3, "value": "true"}`,		},		{			name:       "index-wildcard-in",			query:      `SELECT * from s3object s WHERE title = 'Test Record'`,			wantResult: `{"id":0,"title":"Test Record","desc":"Some text","synonyms":["foo","bar","whatever"]}`,		},		{			name: "select-output-field-as-csv",			requestXML: []byte(`<?xml version="1.0" encoding="UTF-8"?><SelectObjectContentRequest>    <Expression>SELECT s.synonyms from s3object s WHERE 'whatever' IN s.synonyms</Expression>    <ExpressionType>SQL</ExpressionType>    <InputSerialization>        <CompressionType>NONE</CompressionType>        <JSON>            <Type>DOCUMENT</Type>        </JSON>    </InputSerialization>    <OutputSerialization>        <CSV>	   <QuoteCharacter>"</QuoteCharacter>        </CSV>    </OutputSerialization>    <RequestProgress>        <Enabled>FALSE</Enabled>    </RequestProgress></SelectObjectContentRequest>`),			wantResult: `"[""foo"",""bar"",""whatever""]"`,		},		{			name:  "document",			query: "",			requestXML: []byte(`<?xml version="1.0" encoding="UTF-8"?><SelectObjectContentRequest>    <Expression>select * from s3object[*].elements[*] s where s.element_type = '__elem__merfu'</Expression>    <ExpressionType>SQL</ExpressionType>    <InputSerialization>        <CompressionType>NONE</CompressionType>        <JSON>            <Type>DOCUMENT</Type>        </JSON>    </InputSerialization>    <OutputSerialization>        <JSON>        </JSON>    </OutputSerialization>    <RequestProgress>        <Enabled>FALSE</Enabled>    </RequestProgress></SelectObjectContentRequest>`),			withJSON: `{  "name": "small_pdf1.pdf",  "lume_id": "9507193e-572d-4f95-bcf1-e9226d96be65",  "elements": [    {      "element_type": "__elem__image",      "element_id": "859d09c4-7cf1-4a37-9674-3a7de8b56abc",      "attributes": {        "__attr__image_dpi": 300,        "__attr__image_size": [          2550,          3299        ],        "__attr__image_index": 1,        "__attr__image_format": "JPEG",        "__attr__file_extension": "jpg",        "__attr__data": null      }    },    {      "element_type": "__elem__merfu",      "element_id": "d868aefe-ef9a-4be2-b9b2-c9fd89cc43eb",      "attributes": {        "__attr__image_dpi": 300,        "__attr__image_size": [          2550,          3299        ],        "__attr__image_index": 2,        "__attr__image_format": "JPEG",        "__attr__file_extension": "jpg",        "__attr__data": null      }    }  ],  "data": "asdascasdc1234e123erdasdas"}`,			wantResult: `{"element_type":"__elem__merfu","element_id":"d868aefe-ef9a-4be2-b9b2-c9fd89cc43eb","attributes":{"__attr__image_dpi":300,"__attr__image_size":[2550,3299],"__attr__image_index":2,"__attr__image_format":"JPEG","__attr__file_extension":"jpg","__attr__data":null}}`,		},		{			name:       "date_diff_month",			query:      `SELECT date_diff(MONTH, '2019-10-20T', '2020-01-20T') FROM S3Object LIMIT 1`,			wantResult: `{"_1":3}`,		},		{			name:       "date_diff_month_neg",			query:      `SELECT date_diff(MONTH, '2020-01-20T', '2019-10-20T') FROM S3Object LIMIT 1`,			wantResult: `{"_1":-3}`,		},		// Examples from https://docs.aws.amazon.com/AmazonS3/latest/userguide/s3-glacier-select-sql-reference-date.html#s3-glacier-select-sql-reference-date-diff		{			name:       "date_diff_year",			query:      `SELECT date_diff(year, '2010-01-01T', '2011-01-01T') FROM S3Object LIMIT 1`,			wantResult: `{"_1":1}`,		},		{			name:       "date_diff_year",			query:      `SELECT date_diff(month, '2010-01-01T', '2010-05T') FROM S3Object LIMIT 1`,			wantResult: `{"_1":4}`,		},		{			name:       "date_diff_month_oney",			query:      `SELECT date_diff(month, '2010T', '2011T') FROM S3Object LIMIT 1`,			wantResult: `{"_1":12}`,		},		{			name:       "date_diff_month_neg",			query:      `SELECT date_diff(month, '2011T', '2010T') FROM S3Object LIMIT 1`,			wantResult: `{"_1":-12}`,		},		{			name:       "date_diff_days",			query:      `SELECT date_diff(day, '2010-01-01T23:00:00Z', '2010-01-02T01:00:00Z') FROM S3Object LIMIT 1`,			wantResult: `{"_1":0}`,		},		{			name:       "date_diff_days_one",			query:      `SELECT date_diff(day, '2010-01-01T23:00:00Z', '2010-01-02T23:00:00Z') FROM S3Object LIMIT 1`,			wantResult: `{"_1":1}`,		},		{			name:       "cast_from_int_to_float",			query:      `SELECT cast(1 as float) FROM S3Object LIMIT 1`,			wantResult: `{"_1":1}`,		},		{			name:       "cast_from_float_to_float",			query:      `SELECT cast(1.0 as float) FROM S3Object LIMIT 1`,			wantResult: `{"_1":1}`,		},		{			name:       "arithmetic_integer_operand",			query:      `SELECT 1 / 2 FROM S3Object LIMIT 1`,			wantResult: `{"_1":0}`,		},		{			name:       "arithmetic_float_operand",			query:      `SELECT 1.0 / 2.0 * .3 FROM S3Object LIMIT 1`,			wantResult: `{"_1":0.15}`,		},		{			name:       "arithmetic_integer_float_operand",			query:      `SELECT 3.0 / 2, 5 / 2.0 FROM S3Object LIMIT 1`,			wantResult: `{"_1":1.5,"_2":2.5}`,		},		{			name:  "limit-1",			query: `SELECT * FROM S3Object[*].elements[*] LIMIT 1`,			requestXML: []byte(`<?xml version="1.0" encoding="UTF-8"?><SelectObjectContentRequest>    <Expression>select * from s3object[*].elements[*] s where s.element_type = '__elem__merfu'</Expression>    <ExpressionType>SQL</ExpressionType>    <InputSerialization>        <CompressionType>NONE</CompressionType>        <JSON>            <Type>DOCUMENT</Type>        </JSON>    </InputSerialization>    <OutputSerialization>        <JSON>        </JSON>    </OutputSerialization>    <RequestProgress>        <Enabled>FALSE</Enabled>    </RequestProgress></SelectObjectContentRequest>`),			wantResult: `{"element_type":"__elem__merfu","element_id":"d868aefe-ef9a-4be2-b9b2-c9fd89cc43eb","attributes":{"__attr__image_dpi":300,"__attr__image_size":[2550,3299],"__attr__image_index":2,"__attr__image_format":"JPEG","__attr__file_extension":"jpg","__attr__data":null}}`,			withJSON: `{  "name": "small_pdf1.pdf",  "lume_id": "9507193e-572d-4f95-bcf1-e9226d96be65",  "elements": [    {      "element_type": "__elem__image",      "element_id": "859d09c4-7cf1-4a37-9674-3a7de8b56abc",      "attributes": {        "__attr__image_dpi": 300,        "__attr__image_size": [          2550,          3299        ],        "__attr__image_index": 1,        "__attr__image_format": "JPEG",        "__attr__file_extension": "jpg",        "__attr__data": null      }    },    {      "element_type": "__elem__merfu",      "element_id": "d868aefe-ef9a-4be2-b9b2-c9fd89cc43eb",      "attributes": {        "__attr__image_dpi": 300,        "__attr__image_size": [          2550,          3299        ],        "__attr__image_index": 2,        "__attr__image_format": "JPEG",        "__attr__file_extension": "jpg",        "__attr__data": null      }    }  ],  "data": "asdascasdc1234e123erdasdas"}`,		},		{			name:       "limit-2",			query:      `select * from s3object[*].person[*] limit 1`,			wantResult: `{"Id":1,"Name":"Anshu","Address":"Templestowe","Car":"Jeep"}`,			withJSON:   `{ "person": [ { "Id": 1, "Name": "Anshu", "Address": "Templestowe", "Car": "Jeep" }, { "Id": 2, "Name": "Ben Mostafa", "Address": "Las Vegas", "Car": "Mustang" }, { "Id": 3, "Name": "Rohan Wood", "Address": "Wooddon", "Car": "VW" } ] }`,		},		{			name:       "lower-case-is",			query:      `select * from s3object[*] as s where s.request.header['User-Agent'] is not null`,			wantResult: `{"request":{"uri":"/1","header":{"User-Agent":"test"}}}`,			withJSON: `{"request":{"uri":"/1","header":{"User-Agent":"test"}}}{"request":{"uri":"/2","header":{}}}`,		},		{

Lines 1–500 of 1958.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t