Issue 47: Query expression planner now recognises GSIs (#48)
The query expression planner now recognises GSIs, and will use them if the expression can be executed as a query over an index.
This commit is contained in:
		
							parent
							
								
									7caf905c82
								
							
						
					
					
						commit
						733e59ec95
					
				
							
								
								
									
										9
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								go.mod
									
									
									
									
									
								
							|  | @ -18,7 +18,7 @@ require ( | |||
| 	github.com/charmbracelet/bubbles v0.14.0 | ||||
| 	github.com/charmbracelet/bubbletea v0.22.1 | ||||
| 	github.com/charmbracelet/lipgloss v0.6.0 | ||||
| 	github.com/google/uuid v1.3.0 | ||||
| 	github.com/cloudcmds/tamarin v1.0.0 | ||||
| 	github.com/lmika/events v0.0.0-20200906102219-a2269cd4394e | ||||
| 	github.com/lmika/go-bubble-table v0.2.2-0.20220616114432-6bbb2995e538 | ||||
| 	github.com/lmika/gopkgs v0.0.0-20211210041137-0dc91e939890 | ||||
|  | @ -29,10 +29,10 @@ require ( | |||
| 	github.com/pkg/errors v0.9.1 | ||||
| 	github.com/stretchr/testify v1.8.1 | ||||
| 	golang.design/x/clipboard v0.6.2 | ||||
| 	golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a | ||||
| ) | ||||
| 
 | ||||
| require ( | ||||
| 	atomicgo.dev/keyboard v0.2.8 // indirect | ||||
| 	github.com/DataDog/zstd v1.5.2 // indirect | ||||
| 	github.com/Sereal/Sereal v0.0.0-20220220040404-e0d1e550e879 // indirect | ||||
| 	github.com/atotto/clipboard v0.1.4 // indirect | ||||
|  | @ -48,10 +48,8 @@ require ( | |||
| 	github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 // indirect | ||||
| 	github.com/aws/smithy-go v1.13.5 // indirect | ||||
| 	github.com/aymanbagabas/go-osc52 v1.0.3 // indirect | ||||
| 	github.com/cloudcmds/tamarin v1.0.0 // indirect | ||||
| 	github.com/containerd/console v1.0.3 // indirect | ||||
| 	github.com/davecgh/go-spew v1.1.1 // indirect | ||||
| 	github.com/fatih/color v1.13.0 // indirect | ||||
| 	github.com/gofrs/uuid v4.3.1+incompatible // indirect | ||||
| 	github.com/golang/protobuf v1.5.2 // indirect | ||||
| 	github.com/golang/snappy v0.0.4 // indirect | ||||
|  | @ -64,7 +62,6 @@ require ( | |||
| 	github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc // indirect | ||||
| 	github.com/lucasb-eyer/go-colorful v1.2.0 // indirect | ||||
| 	github.com/lunixbochs/vtclean v1.0.0 // indirect | ||||
| 	github.com/mattn/go-colorable v0.1.12 // indirect | ||||
| 	github.com/mattn/go-isatty v0.0.16 // indirect | ||||
| 	github.com/mattn/go-localereader v0.0.1 // indirect | ||||
| 	github.com/muesli/cancelreader v0.2.2 // indirect | ||||
|  | @ -80,7 +77,7 @@ require ( | |||
| 	github.com/wI2L/jsondiff v0.3.0 // indirect | ||||
| 	go.etcd.io/bbolt v1.3.6 // indirect | ||||
| 	golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect | ||||
| 	golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a // indirect | ||||
| 	golang.org/x/exp/shiny v0.0.0-20230213192124-5e25df0256eb // indirect | ||||
| 	golang.org/x/image v0.0.0-20211028202545-6944b10bf410 // indirect | ||||
| 	golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554 // indirect | ||||
| 	golang.org/x/sys v0.1.0 // indirect | ||||
|  |  | |||
							
								
								
									
										104
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								go.sum
									
									
									
									
									
								
							|  | @ -1,78 +1,46 @@ | |||
| atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4= | ||||
| atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= | ||||
| github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= | ||||
| github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= | ||||
| github.com/DataDog/zstd v1.5.2/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= | ||||
| github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= | ||||
| github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= | ||||
| github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= | ||||
| github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= | ||||
| github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= | ||||
| github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= | ||||
| github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= | ||||
| github.com/Sereal/Sereal v0.0.0-20220220040404-e0d1e550e879 h1:M5ptEKnqKqpFTKbe+p5zEf3ro1deJ6opUz5j3g3/ErQ= | ||||
| github.com/Sereal/Sereal v0.0.0-20220220040404-e0d1e550e879/go.mod h1:D0JMgToj/WdxCgd30Kc1UcA9E+WdZoJqeVOuYW7iTBM= | ||||
| github.com/alecthomas/participle v0.7.1 h1:2bN7reTw//5f0cugJcTOnY/NYZcWQOaajW+BwZB5xWs= | ||||
| github.com/alecthomas/participle/v2 v2.0.0-alpha7 h1:cK4vjj0VSgb3lN1nuKA5F7dw+1s1pWBe5bx7nNCnN+c= | ||||
| github.com/alecthomas/participle/v2 v2.0.0-alpha7/go.mod h1:NumScqsC42o9x+dGj8/YqsIfhrIQjFEOFovxotbBirA= | ||||
| github.com/alecthomas/assert/v2 v2.0.3 h1:WKqJODfOiQG0nEJKFKzDIG3E29CN2/4zR9XGJzKIkbg= | ||||
| github.com/alecthomas/participle/v2 v2.0.0-beta.5 h1:y6dsSYVb1G5eK6mgmy+BgI3Mw35a3WghArZ/Hbebrjo= | ||||
| github.com/alecthomas/participle/v2 v2.0.0-beta.5/go.mod h1:RC764t6n4L8D8ITAJv0qdokritYSNR3wV5cVwmIEaMM= | ||||
| github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1 h1:GDQdwm/gAcJcLAKQQZGOJ4knlw+7rfEQQcmwTbt4p5E= | ||||
| github.com/alecthomas/repr v0.0.0-20181024024818-d37bc2a10ba1/go.mod h1:xTS7Pm1pD1mvyM075QCDSRqH6qRLXylzS24ZTpRiSzQ= | ||||
| github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE= | ||||
| github.com/asdine/storm v2.1.2+incompatible h1:dczuIkyqwY2LrtXPz8ixMrU/OFgZp71kbKTHGrXYt/Q= | ||||
| github.com/asdine/storm v2.1.2+incompatible/go.mod h1:RarYDc9hq1UPLImuiXK3BIWPJLdIygvV3PsInK0FbVQ= | ||||
| github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= | ||||
| github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= | ||||
| github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= | ||||
| github.com/aws/aws-sdk-go-v2 v1.13.0/go.mod h1:L6+ZpqHaLbAaxsqV0L4cvxZY7QupWJB4fhkf8LXvC7w= | ||||
| github.com/aws/aws-sdk-go-v2 v1.16.1/go.mod h1:ytwTPBG6fXTZLxxeeCCWj2/EMYp/xDUgX+OET6TLNNU= | ||||
| github.com/aws/aws-sdk-go-v2 v1.16.5 h1:Ah9h1TZD9E2S1LzHpViBO3Jz9FPL5+rmflmb8hXirtI= | ||||
| github.com/aws/aws-sdk-go-v2 v1.16.5/go.mod h1:Wh7MEsmEApyL5hrWzpDkba4gwAPc5/piwLVLFnCxp48= | ||||
| github.com/aws/aws-sdk-go-v2 v1.17.4 h1:wyC6p9Yfq6V2y98wfDsj6OnNQa4w2BLGCLIxzNhwOGY= | ||||
| github.com/aws/aws-sdk-go-v2 v1.17.4/go.mod h1:uzbQtefpm44goOPmdKyAlXSNcwlRgF3ePWVW6EtJvvw= | ||||
| github.com/aws/aws-sdk-go-v2/config v1.13.1 h1:yLv8bfNoT4r+UvUKQKqRtdnvuWGMK5a82l4ru9Jvnuo= | ||||
| github.com/aws/aws-sdk-go-v2/config v1.13.1/go.mod h1:Ba5Z4yL/UGbjQUzsiaN378YobhFo0MLfueXGiOsYtEs= | ||||
| github.com/aws/aws-sdk-go-v2/credentials v1.8.0 h1:8Ow0WcyDesGNL0No11jcgb1JAtE+WtubqXjgxau+S0o= | ||||
| github.com/aws/aws-sdk-go-v2/credentials v1.8.0/go.mod h1:gnMo58Vwx3Mu7hj1wpcG8DI0s57c9o42UQ6wgTQT5to= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.9.4 h1:EoyeSOfbSuKh+bQIDoZaVJjON6PF+dsSn5w1RhIpMD0= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.9.4/go.mod h1:bfCL7OwZS6owS06pahfGxhcgpLWj2W1sQASoYRuenag= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.10.12 h1:ama2cD4WaH6+8Gq/M/g+ZumPmmqCyanr+6Sm+iJVxfA= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.10.12/go.mod h1:tPnUO5mS3JThpwfq4Q8iPd745s7yh6fGPqDUEBw+Wv4= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression v1.4.10 h1:IBIZfpnWCTTQhH/bMvDcCMw10BtLBPYO30Ev8MLXMTY= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression v1.4.10/go.mod h1:RL7aJOwlWj2N6wkE4nKR1S5M4iGph+xSu7JovwNYpyU= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression v1.4.39 h1:PhgfvgqwMFQKwOcxLV7V3lNDVnR3ZUWzoB6T9oCFpR4= | ||||
| github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression v1.4.39/go.mod h1:/GkvC7uHpK50ilKkKx9I2gZiI/ieZbKjS2aah1rT9uE= | ||||
| github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0 h1:NITDuUZO34mqtOwFWZiXo7yAHj7kf+XPE+EiKuCBNUI= | ||||
| github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.10.0/go.mod h1:I6/fHT/fH460v09eg2gVrd8B/IqskhNdpcLH0WNO3QI= | ||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.4/go.mod h1:XHgQ7Hz2WY2GAn//UXHofLfPXWh+s62MbMOijrg12Lw= | ||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.8/go.mod h1:LnTQMTqbKsbtt+UI5+wPsB7jedW+2ZgozoPG8k6cMxg= | ||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.12 h1:Zt7DDk5V7SyQULUUwIKzsROtVzp/kVvcz15uQx/Tkow= | ||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.12/go.mod h1:Afj/U8svX6sJ77Q+FPWMzabJ9QjbwP32YlopgKALUpg= | ||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28 h1:r+XwaCLpIvCKjBIYy/HVZujQS9tsz5ohHG3ZIe0wKoE= | ||||
| github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.28/go.mod h1:3lwChorpIM/BhImY/hy+Z6jekmN92cXGPI1QJasVPYY= | ||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.2.0/go.mod h1:BsCSJHx5DnDXIrOcqB8KN1/B+hXLG/bi4Y6Vjcx/x9E= | ||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.2/go.mod h1:1x4ZP3Z8odssdhuLI+/1Tqw6Pt/VAaP4Tr8EUxHvPXE= | ||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.6 h1:eeXdGVtXEe+2Jc49+/vAzna3FAQnUD4AagAw8tzbmfc= | ||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.6/go.mod h1:FwpAKI+FBPIELJIdmQzlLtRe8LQSOreMcM2wBsPMvvc= | ||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22 h1:7AwGYXDdqRQYsluvKFmWoqpcOQJ4bH634SkYf3FNj/A= | ||||
| github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.4.22/go.mod h1:EqK7gVrIGAHyZItrD1D8B0ilgwMD1GiWAmbU4u/JHNk= | ||||
| github.com/aws/aws-sdk-go-v2/internal/ini v1.3.5 h1:ixotxbfTCFpqbuwFv/RcZwyzhkxPSYDYEMcj4niB5Uk= | ||||
| github.com/aws/aws-sdk-go-v2/internal/ini v1.3.5/go.mod h1:R3sWUqPcfXSiF/LSFJhjyJmpg9uV6yP2yv3YZZjldVI= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodb v1.15.7 h1:Ls6kDGWNr3wxE8JypXgTTonHpQ1eRVCGNqaFHY2UASw= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodb v1.15.7/go.mod h1:+v2jeT4/39fCXUQ0ZfHQHMMiJljnmiuj16F03uAd9DY= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodb v1.18.3 h1:MxOpCZ+o9+AIeQHi2ocW7H4D7p0LhEkmetETVvDnkvg= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodb v1.18.3/go.mod h1:nkpC9xkh+3vdxmhqN8Ac10pgV14DsJDLzUsV2CcS+44= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.13.7 h1:o2HKntJx3vr3y11NK58RA6tYKZKQo5PWWt/bs0rWR0U= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.13.7/go.mod h1:FAVtDKEl/8WxRDQ33e2fz16RO1t4zeEwWIU5kR29xXs= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.14.3 h1:B+bkmCnNJi194pu9aTtYUe8f4EPXafC+xfU+zciVxdg= | ||||
| github.com/aws/aws-sdk-go-v2/service/dynamodbstreams v1.14.3/go.mod h1:bRphLmXQD9Ux4jLcFEwyrWdmuPTj2Lh8VGl9wILuJII= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.2 h1:T/ywkX1ed+TsZVQccu/8rRJGxKZF/t0Ivgrb4MHTSeo= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.2/go.mod h1:RnloUnyZ4KN9JStGY1LuQ7Wzqh7V0f8FinmRdHYtuaA= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.7.6 h1:JGrc3+kkyr848/wpG2+kWuzHK3H4Fyxj2jnXj8ijQ/Y= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.7.6/go.mod h1:zwvTysbXES8GDwFcwCPB8NkC+bCdio1abH+E+BRe/xg= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.7.22 h1:6zEryIiJOSk5/OcVHzkPDwzNBQ2atYCTShyA7TqkuxA= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/endpoint-discovery v1.7.22/go.mod h1:moeOz5SKfY0p6pNIChdPIQdfaUfWI67+OVe0/r6+aGY= | ||||
| github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.7.0 h1:4QAOB3KrvI1ApJK14sliGr3Ie2pjyvNypn/lfzDHfUw= | ||||
|  | @ -87,8 +55,6 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.14.0 h1:ksiDXhvNYg0D2/UFkLejsaz3LqpW | |||
| github.com/aws/aws-sdk-go-v2/service/sts v1.14.0/go.mod h1:u0xMJKDvvfocRjiozsoZglVNXRG19043xzp3r2ivLIk= | ||||
| github.com/aws/smithy-go v1.10.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E= | ||||
| github.com/aws/smithy-go v1.11.2/go.mod h1:3xHYmszWVx2c0kIwQeEVf9uSm4fYZt67FBJnwub1bgM= | ||||
| github.com/aws/smithy-go v1.11.3 h1:DQixirEFM9IaKxX1olZ3ke3nvxRS2xMDteKIDWxozW8= | ||||
| github.com/aws/smithy-go v1.11.3/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= | ||||
| github.com/aws/smithy-go v1.13.5 h1:hgz0X/DX0dGqTYpGALqXJoRKRj5oQ7150i5FdTePzO8= | ||||
| github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= | ||||
| github.com/aymanbagabas/go-osc52 v1.0.3 h1:DTwqENW7X9arYimJrPeGZcV0ln14sGMt3pHZspWD+Mg= | ||||
|  | @ -97,23 +63,15 @@ github.com/brianvoe/gofakeit/v6 v6.15.0 h1:lJPGJZ2/07TRGDazyTzD5b18N3y4tmmJpdhCU | |||
| github.com/brianvoe/gofakeit/v6 v6.15.0/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= | ||||
| github.com/calyptia/go-bubble-table v0.2.1 h1:NWcVRyGCLuP7QIA29uUFSY+IjmWcmUWHjy5J/CPb0Rk= | ||||
| github.com/calyptia/go-bubble-table v0.2.1/go.mod h1:gJvzUOUzfQeA9JmgLumyJYWJMtuRQ7WxxTwc9tjEiGw= | ||||
| github.com/charmbracelet/bubbles v0.11.0 h1:fBLyY0PvJnd56Vlu5L84JJH6f4axhgIJ9P3NET78f0Q= | ||||
| github.com/charmbracelet/bubbles v0.11.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc= | ||||
| github.com/charmbracelet/bubbles v0.14.0 h1:DJfCwnARfWjZLvMglhSQzo76UZ2gucuHPy9jLWX45Og= | ||||
| github.com/charmbracelet/bubbles v0.14.0/go.mod h1:bbeTiXwPww4M031aGi8UK2HT9RDWoiNibae+1yCMtcc= | ||||
| github.com/charmbracelet/bubbletea v0.21.0 h1:f3y+kanzgev5PA916qxmDybSHU3N804uOnKnhRPXTcI= | ||||
| github.com/charmbracelet/bubbletea v0.21.0/go.mod h1:GgmJMec61d08zXsOhqRC/AiOx4K4pmz+VIcRIm1FKr4= | ||||
| github.com/charmbracelet/bubbletea v0.22.1 h1:z66q0LWdJNOWEH9zadiAIXp2GN1AWrwNXU8obVY9X24= | ||||
| github.com/charmbracelet/bubbletea v0.22.1/go.mod h1:8/7hVvbPN6ZZPkczLiB8YpLkLJ0n7DMho5Wvfd2X1C0= | ||||
| github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= | ||||
| github.com/charmbracelet/lipgloss v0.5.0 h1:lulQHuVeodSgDez+3rGiuxlPVXSnhth442DATR2/8t8= | ||||
| github.com/charmbracelet/lipgloss v0.5.0/go.mod h1:EZLha/HbzEt7cYqdFPovlqy5FZPj0xFhg5SaqxScmgs= | ||||
| github.com/charmbracelet/lipgloss v0.6.0 h1:1StyZB9vBSOyuZxQUcUwGr17JmojPNm87inij9N3wJY= | ||||
| github.com/charmbracelet/lipgloss v0.6.0/go.mod h1:tHh2wr34xcHjC2HCXIlGSG1jaDF0S0atAUvBMP6Ppuk= | ||||
| github.com/cloudcmds/tamarin v0.0.12 h1:xigMcfala5I81fh+6FSaJpjiKyWTOqzdf/GIQnsk/oc= | ||||
| github.com/cloudcmds/tamarin v0.0.12/go.mod h1:U1aHBoAFtJbI9jzgaj8TUo9C6vfzUKzn1OhWKIdigVM= | ||||
| github.com/cloudcmds/tamarin v0.0.14 h1:LNHz/CplhiM9u4SVy/9dGjyXpMTvKMmWcuO0+f0t5Ls= | ||||
| github.com/cloudcmds/tamarin v0.0.14/go.mod h1:U1aHBoAFtJbI9jzgaj8TUo9C6vfzUKzn1OhWKIdigVM= | ||||
| github.com/cloudcmds/tamarin v1.0.0 h1:PhrJ74FCUJo24/nIPXnQe9E3WVEIYo4aG58pICOMDBE= | ||||
| github.com/cloudcmds/tamarin v1.0.0/go.mod h1:U1aHBoAFtJbI9jzgaj8TUo9C6vfzUKzn1OhWKIdigVM= | ||||
| github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= | ||||
|  | @ -121,8 +79,6 @@ github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkX | |||
| github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||||
| github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
| github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= | ||||
| github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= | ||||
| github.com/gofrs/uuid v4.3.1+incompatible h1:0/KbAdpx3UXAx1kEOWHJeOkpbgRFGHVgv+CFIY7dBJI= | ||||
| github.com/gofrs/uuid v4.3.1+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= | ||||
| github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
|  | @ -137,14 +93,11 @@ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ | |||
| github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= | ||||
| github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= | ||||
| github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= | ||||
| github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= | ||||
| github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= | ||||
| github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= | ||||
| github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= | ||||
| github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA= | ||||
| github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= | ||||
| github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= | ||||
| github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= | ||||
| github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= | ||||
| github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= | ||||
| github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= | ||||
| github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= | ||||
|  | @ -157,15 +110,11 @@ github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGw | |||
| github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= | ||||
| github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc h1:ZQrgZFsLzkw7o3CoDzsfBhx0bf/1rVBXrLy8dXKRe8o= | ||||
| github.com/juju/ansiterm v0.0.0-20210929141451-8b71cc96ebdc/go.mod h1:PyXUpnI3olx3bsPcHt98FGPX/KCFZ1Fi+hw1XLI6384= | ||||
| github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= | ||||
| github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= | ||||
| github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= | ||||
| github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= | ||||
| github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= | ||||
| github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= | ||||
| github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= | ||||
| github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= | ||||
| github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= | ||||
| github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= | ||||
| github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= | ||||
| github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= | ||||
| github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= | ||||
| github.com/lmika/events v0.0.0-20200906102219-a2269cd4394e h1:0QkUe2ejnT/i+xbgGylMU1b+XnZponQKiPVNi+C/xgA= | ||||
|  | @ -180,12 +129,8 @@ github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69 | |||
| github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= | ||||
| github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8= | ||||
| github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= | ||||
| github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= | ||||
| github.com/mattn/go-colorable v0.1.10/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= | ||||
| github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= | ||||
| github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= | ||||
| github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= | ||||
| github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= | ||||
| github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= | ||||
| github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= | ||||
| github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= | ||||
|  | @ -193,14 +138,12 @@ github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2J | |||
| github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= | ||||
| github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= | ||||
| github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= | ||||
| github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= | ||||
| github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= | ||||
| github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= | ||||
| github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= | ||||
| github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= | ||||
| github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70 h1:kMlmsLSbjkikxQJ1IPwaM+7LJ9ltFu/fi8CRzvSnQmA= | ||||
| github.com/muesli/ansi v0.0.0-20211031195517-c9f0611b6c70/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= | ||||
| github.com/muesli/cancelreader v0.2.0 h1:SOpr+CfyVNce341kKqvbhhzQhBPyJRXQaCtn03Pae1Q= | ||||
| github.com/muesli/cancelreader v0.2.0/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= | ||||
| github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= | ||||
| github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= | ||||
|  | @ -209,41 +152,26 @@ github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= | |||
| github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= | ||||
| github.com/muesli/termenv v0.11.1-0.20220204035834-5ac8409525e0/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= | ||||
| github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ7pd+SrtBSrSNoBBmXlcY8+Xj4BMJgh8qcZrvs= | ||||
| github.com/muesli/termenv v0.12.0 h1:KuQRUE3PgxRFWhq4gHvZtPSLCGDqM5q/cYr1pZ39ytc= | ||||
| github.com/muesli/termenv v0.12.0/go.mod h1:WCCv32tusQ/EEZ5S8oUIIrC/nIuBcxCVqlN4Xfkv+7A= | ||||
| github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0= | ||||
| github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= | ||||
| github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= | ||||
| github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= | ||||
| 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/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= | ||||
| github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= | ||||
| github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= | ||||
| github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= | ||||
| github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= | ||||
| github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= | ||||
| github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= | ||||
| github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | ||||
| github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= | ||||
| github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= | ||||
| github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= | ||||
| github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= | ||||
| github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= | ||||
| github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= | ||||
| github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= | ||||
| github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= | ||||
| github.com/stretchr/objx v0.1.0/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 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= | ||||
| github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= | ||||
| github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= | ||||
| github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= | ||||
| github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | ||||
| github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY= | ||||
| github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | ||||
| github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= | ||||
| github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= | ||||
| github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= | ||||
| github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= | ||||
|  | @ -258,7 +186,6 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible h1:dSLoQfGFAo3F6OoNhwUmLwVgaU | |||
| github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= | ||||
| github.com/wI2L/jsondiff v0.3.0 h1:iTzQ9u/d86GE9RsBzVHX88f2EA1vQUboHwLhSQFc1s4= | ||||
| github.com/wI2L/jsondiff v0.3.0/go.mod h1:y1IMzNNjlSsk3IUoJdRJO7VRBtzMvRgyo4Vu0LdHpTc= | ||||
| github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= | ||||
| github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= | ||||
| go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= | ||||
| go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= | ||||
|  | @ -269,10 +196,11 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U | |||
| golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
| golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM= | ||||
| golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= | ||||
| golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU= | ||||
| golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= | ||||
| golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a h1:tlXy25amD5A7gOfbXdqCGN5k8ESEed/Ee1E5RcrYnqU= | ||||
| golang.org/x/exp v0.0.0-20230108222341-4b8118a2686a/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= | ||||
| golang.org/x/exp/shiny v0.0.0-20230213192124-5e25df0256eb h1:gdeQX7xJSkTNF+Sw7++XNIOo4pGL0CjQv3N2Vm1Erxk= | ||||
| golang.org/x/exp/shiny v0.0.0-20230213192124-5e25df0256eb/go.mod h1:UH99kUObWAZkDnWqppdQe5ZhPYESUw8I0zVV1uWBR+0= | ||||
| 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/image v0.0.0-20211028202545-6944b10bf410 h1:hTftEOvwiOq2+O8k2D5/Q7COC7k5Qcrgc2TFURJYnvQ= | ||||
|  | @ -284,10 +212,10 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= | |||
| golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | ||||
| golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | ||||
| golang.org/x/net v0.0.0-20190603091049-60506f45cf65 h1:+rhAzEzT3f4JtomfC371qB+0Ola2caSKcY69NUBZrRQ= | ||||
| golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= | ||||
| golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
| golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= | ||||
| golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE= | ||||
| golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
| golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | ||||
|  | @ -301,31 +229,19 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w | |||
| golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| 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-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/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-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= | ||||
| golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec h1:BkDtF2Ih9xZ7le9ndzTA7KJow28VbQW3odyk/8drmuI= | ||||
| golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= | ||||
| golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | ||||
| golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | ||||
| golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||||
| golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||||
| golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM= | ||||
| golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||||
| golang.org/x/term v0.0.0-20220919170432-7a66f970e087 h1:tPwmk4vmvVCMdr98VgL4JH+qZxPL8fqlUOHnyOM8N3w= | ||||
| golang.org/x/term v0.0.0-20220919170432-7a66f970e087/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= | ||||
| golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
| golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= | ||||
| golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
| golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= | ||||
| golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= | ||||
| golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= | ||||
| golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= | ||||
|  | @ -343,15 +259,11 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 | |||
| google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= | ||||
| google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= | ||||
| gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= | ||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= | ||||
| gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= | ||||
| gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
| gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||||
| gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= | ||||
|  |  | |||
|  | @ -100,6 +100,24 @@ func TestTableReadController_Query(t *testing.T) { | |||
| 		}, "")) | ||||
| 	}) | ||||
| 
 | ||||
| 	t.Run("should run query on index with filter based on user query", func(t *testing.T) { | ||||
| 		srv := newService(t, serviceConfig{tableName: "bravo-table"}) | ||||
| 
 | ||||
| 		tempFile := tempFile(t) | ||||
| 
 | ||||
| 		invokeCommand(t, srv.readController.Init()) | ||||
| 		invokeCommandWithPrompts(t, srv.readController.PromptForQuery(), `alpha = "This is some value"`) | ||||
| 		invokeCommand(t, srv.exportController.ExportCSV(tempFile)) | ||||
| 
 | ||||
| 		bts, err := os.ReadFile(tempFile) | ||||
| 		assert.NoError(t, err) | ||||
| 
 | ||||
| 		assert.Equal(t, string(bts), strings.Join([]string{ | ||||
| 			"pk,sk,alpha\n", | ||||
| 			"foo,bar,This is some value\n", | ||||
| 		}, "")) | ||||
| 	}) | ||||
| 
 | ||||
| 	t.Run("should return error if result set is not set", func(t *testing.T) { | ||||
| 		srv := newService(t, serviceConfig{tableName: "non-existant-table"}) | ||||
| 
 | ||||
|  | @ -250,6 +268,7 @@ var testData = []testdynamo.TestData{ | |||
| 	}, | ||||
| 	{ | ||||
| 		TableName: "bravo-table", | ||||
| 		Index:     []string{"alpha"}, | ||||
| 		Data: []map[string]interface{}{ | ||||
| 			{ | ||||
| 				"pk":    "foo", | ||||
|  |  | |||
|  | @ -8,6 +8,7 @@ import ( | |||
| 
 | ||||
| type QueryExecutionPlan struct { | ||||
| 	CanQuery   bool | ||||
| 	IndexName  string | ||||
| 	Expression expression.Expression | ||||
| } | ||||
| 
 | ||||
|  | @ -18,6 +19,9 @@ func (qep QueryExecutionPlan) Describe(dp DescribingPrinter) { | |||
| 		dp.Println("  execute as: scan") | ||||
| 	} | ||||
| 
 | ||||
| 	if qep.IndexName != "" { | ||||
| 		dp.Printf("  index: %v", qep.IndexName) | ||||
| 	} | ||||
| 	if keyCond := aws.ToString(qep.Expression.KeyCondition()); keyCond != "" { | ||||
| 		dp.Printf("  key condition: %v", keyCond) | ||||
| 	} | ||||
|  |  | |||
|  | @ -5,6 +5,7 @@ import ( | |||
| 	"github.com/alecthomas/participle/v2/lexer" | ||||
| 	"github.com/aws/aws-sdk-go-v2/feature/dynamodb/expression" | ||||
| 	"github.com/aws/aws-sdk-go-v2/service/dynamodb/types" | ||||
| 	"github.com/lmika/audax/internal/common/sliceutils" | ||||
| 	"github.com/lmika/audax/internal/dynamo-browse/models" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | @ -121,30 +122,43 @@ func Parse(expr string) (*QueryExpr, error) { | |||
| } | ||||
| 
 | ||||
| func (a *astExpr) calcQuery(ctx *evalContext, info *models.TableInfo) (*models.QueryExecutionPlan, error) { | ||||
| 	type queryTestAttempt struct { | ||||
| 		index         string | ||||
| 		keysUnderTest models.KeyAttribute | ||||
| 	} | ||||
| 	queryTestAttempts := append( | ||||
| 		[]queryTestAttempt{{keysUnderTest: info.Keys}}, | ||||
| 		sliceutils.Map(info.GSIs, func(gsi models.TableGSI) queryTestAttempt { | ||||
| 			return queryTestAttempt{index: gsi.Name, keysUnderTest: gsi.Keys} | ||||
| 		})...) | ||||
| 
 | ||||
| 	ir, err := a.evalToIR(ctx, info) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 
 | ||||
| 	var qci queryCalcInfo | ||||
| 	if canExecuteAsQuery(ir, info, &qci) { | ||||
| 		ke, err := ir.(queryableIRAtom).calcQueryForQuery(info) | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 	for _, attempt := range queryTestAttempts { | ||||
| 		var qci = queryCalcInfo{keysUnderTest: attempt.keysUnderTest} | ||||
| 		if canExecuteAsQuery(ir, &qci) { | ||||
| 			ke, err := ir.(queryableIRAtom).calcQueryForQuery() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 
 | ||||
| 			builder := expression.NewBuilder() | ||||
| 			builder = builder.WithKeyCondition(ke) | ||||
| 
 | ||||
| 			expr, err := builder.Build() | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 
 | ||||
| 			return &models.QueryExecutionPlan{ | ||||
| 				CanQuery:   true, | ||||
| 				IndexName:  attempt.index, | ||||
| 				Expression: expr, | ||||
| 			}, nil | ||||
| 		} | ||||
| 
 | ||||
| 		builder := expression.NewBuilder() | ||||
| 		builder = builder.WithKeyCondition(ke) | ||||
| 
 | ||||
| 		expr, err := builder.Build() | ||||
| 		if err != nil { | ||||
| 			return nil, err | ||||
| 		} | ||||
| 
 | ||||
| 		return &models.QueryExecutionPlan{ | ||||
| 			CanQuery:   true, | ||||
| 			Expression: expr, | ||||
| 		}, nil | ||||
| 	} | ||||
| 
 | ||||
| 	cb, err := ir.calcQueryForScan(info) | ||||
|  |  | |||
|  | @ -128,14 +128,14 @@ type irKeyFieldCmp struct { | |||
| 	cmpType int | ||||
| } | ||||
| 
 | ||||
| func (a irKeyFieldCmp) canBeExecutedAsQuery(info *models.TableInfo, qci *queryCalcInfo) bool { | ||||
| func (a irKeyFieldCmp) canBeExecutedAsQuery(qci *queryCalcInfo) bool { | ||||
| 	keyName := a.name.keyName() | ||||
| 	if keyName == "" { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	if keyName == info.Keys.SortKey { | ||||
| 		return qci.addKey(info, keyName) | ||||
| 	if keyName == qci.keysUnderTest.SortKey { | ||||
| 		return qci.addKey(keyName) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
|  | @ -158,7 +158,7 @@ func (a irKeyFieldCmp) calcQueryForScan(info *models.TableInfo) (expression.Cond | |||
| 	return expression.ConditionBuilder{}, errors.New("unsupported cmp type") | ||||
| } | ||||
| 
 | ||||
| func (a irKeyFieldCmp) calcQueryForQuery(info *models.TableInfo) (expression.KeyConditionBuilder, error) { | ||||
| func (a irKeyFieldCmp) calcQueryForQuery() (expression.KeyConditionBuilder, error) { | ||||
| 	keyName := a.name.keyName() | ||||
| 	vb := a.value.goValue() | ||||
| 
 | ||||
|  |  | |||
|  | @ -100,31 +100,31 @@ type irDualConjunction struct { | |||
| 	leftIsPK bool | ||||
| } | ||||
| 
 | ||||
| func (i *irDualConjunction) canBeExecutedAsQuery(info *models.TableInfo, qci *queryCalcInfo) bool { | ||||
| func (i *irDualConjunction) canBeExecutedAsQuery(qci *queryCalcInfo) bool { | ||||
| 	qciCopy := qci.clone() | ||||
| 
 | ||||
| 	leftCanExecuteAsQuery := canExecuteAsQuery(i.left, info, qci) | ||||
| 	leftCanExecuteAsQuery := canExecuteAsQuery(i.left, qci) | ||||
| 	if leftCanExecuteAsQuery { | ||||
| 		i.leftIsPK = qci.hasSeenPrimaryKey(info) | ||||
| 		return canExecuteAsQuery(i.right, info, qci) | ||||
| 		i.leftIsPK = qci.hasSeenPrimaryKey() | ||||
| 		return canExecuteAsQuery(i.right, qci) | ||||
| 	} | ||||
| 
 | ||||
| 	// Might be that the right is the partition key, so test again with them swapped
 | ||||
| 	rightCanExecuteAsQuery := canExecuteAsQuery(i.right, info, qciCopy) | ||||
| 	rightCanExecuteAsQuery := canExecuteAsQuery(i.right, qciCopy) | ||||
| 	if rightCanExecuteAsQuery { | ||||
| 		return canExecuteAsQuery(i.left, info, qciCopy) | ||||
| 		return canExecuteAsQuery(i.left, qciCopy) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
| } | ||||
| 
 | ||||
| func (i *irDualConjunction) calcQueryForQuery(info *models.TableInfo) (expression.KeyConditionBuilder, error) { | ||||
| 	left, err := i.left.(queryableIRAtom).calcQueryForQuery(info) | ||||
| func (i *irDualConjunction) calcQueryForQuery() (expression.KeyConditionBuilder, error) { | ||||
| 	left, err := i.left.(queryableIRAtom).calcQueryForQuery() | ||||
| 	if err != nil { | ||||
| 		return expression.KeyConditionBuilder{}, err | ||||
| 	} | ||||
| 
 | ||||
| 	right, err := i.right.(queryableIRAtom).calcQueryForQuery(info) | ||||
| 	right, err := i.right.(queryableIRAtom).calcQueryForQuery() | ||||
| 	if err != nil { | ||||
| 		return expression.KeyConditionBuilder{}, err | ||||
| 	} | ||||
|  |  | |||
|  | @ -136,15 +136,15 @@ type irKeyFieldEq struct { | |||
| 	value valueIRAtom | ||||
| } | ||||
| 
 | ||||
| func (a irKeyFieldEq) canBeExecutedAsQuery(info *models.TableInfo, qci *queryCalcInfo) bool { | ||||
| func (a irKeyFieldEq) canBeExecutedAsQuery(qci *queryCalcInfo) bool { | ||||
| 	keyName := a.name.keyName() | ||||
| 	if keyName == "" { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	if keyName == info.Keys.PartitionKey || | ||||
| 		(keyName == info.Keys.SortKey && qci.hasSeenPrimaryKey(info)) { | ||||
| 		return qci.addKey(info, keyName) | ||||
| 	if keyName == qci.keysUnderTest.PartitionKey || | ||||
| 		(keyName == qci.keysUnderTest.SortKey && qci.hasSeenPrimaryKey()) { | ||||
| 		return qci.addKey(keyName) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
|  | @ -156,7 +156,7 @@ func (a irKeyFieldEq) calcQueryForScan(info *models.TableInfo) (expression.Condi | |||
| 	return nb.Equal(vb), nil | ||||
| } | ||||
| 
 | ||||
| func (a irKeyFieldEq) calcQueryForQuery(info *models.TableInfo) (expression.KeyConditionBuilder, error) { | ||||
| func (a irKeyFieldEq) calcQueryForQuery() (expression.KeyConditionBuilder, error) { | ||||
| 	vb := a.value.goValue() | ||||
| 	return expression.Key(a.name.keyName()).Equal(expression.Value(vb)), nil | ||||
| } | ||||
|  | @ -188,14 +188,14 @@ type irFieldBeginsWith struct { | |||
| 	value irValue | ||||
| } | ||||
| 
 | ||||
| func (a irFieldBeginsWith) canBeExecutedAsQuery(info *models.TableInfo, qci *queryCalcInfo) bool { | ||||
| func (a irFieldBeginsWith) canBeExecutedAsQuery(qci *queryCalcInfo) bool { | ||||
| 	keyName := a.name.keyName() | ||||
| 	if keyName == "" { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
| 	if keyName == info.Keys.SortKey && qci.hasSeenPrimaryKey(info) { | ||||
| 		return qci.addKey(info, a.name.keyName()) | ||||
| 	if keyName == qci.keysUnderTest.SortKey && qci.hasSeenPrimaryKey() { | ||||
| 		return qci.addKey(a.name.keyName()) | ||||
| 	} | ||||
| 
 | ||||
| 	return false | ||||
|  | @ -212,7 +212,7 @@ func (a irFieldBeginsWith) calcQueryForScan(info *models.TableInfo) (expression. | |||
| 	return nb.BeginsWith(strValue), nil | ||||
| } | ||||
| 
 | ||||
| func (a irFieldBeginsWith) calcQueryForQuery(info *models.TableInfo) (expression.KeyConditionBuilder, error) { | ||||
| func (a irFieldBeginsWith) calcQueryForQuery() (expression.KeyConditionBuilder, error) { | ||||
| 	vb := a.value.goValue() | ||||
| 	strValue, isStrValue := vb.(string) | ||||
| 	if !isStrValue { | ||||
|  |  | |||
|  | @ -199,7 +199,8 @@ func (a *astExpr) String() string { | |||
| } | ||||
| 
 | ||||
| type queryCalcInfo struct { | ||||
| 	seenKeys map[string]struct{} | ||||
| 	keysUnderTest models.KeyAttribute | ||||
| 	seenKeys      map[string]struct{} | ||||
| } | ||||
| 
 | ||||
| func (qc *queryCalcInfo) clone() *queryCalcInfo { | ||||
|  | @ -207,16 +208,16 @@ func (qc *queryCalcInfo) clone() *queryCalcInfo { | |||
| 	for k, v := range qc.seenKeys { | ||||
| 		newKeys[k] = v | ||||
| 	} | ||||
| 	return &queryCalcInfo{seenKeys: newKeys} | ||||
| 	return &queryCalcInfo{keysUnderTest: qc.keysUnderTest, seenKeys: newKeys} | ||||
| } | ||||
| 
 | ||||
| func (qc *queryCalcInfo) hasSeenPrimaryKey(tableInfo *models.TableInfo) bool { | ||||
| 	_, hasKey := qc.seenKeys[tableInfo.Keys.PartitionKey] | ||||
| func (qc *queryCalcInfo) hasSeenPrimaryKey() bool { | ||||
| 	_, hasKey := qc.seenKeys[qc.keysUnderTest.PartitionKey] | ||||
| 	return hasKey | ||||
| } | ||||
| 
 | ||||
| func (qc *queryCalcInfo) addKey(tableInfo *models.TableInfo, key string) bool { | ||||
| 	if tableInfo.Keys.PartitionKey != key && tableInfo.Keys.SortKey != key { | ||||
| func (qc *queryCalcInfo) addKey(key string) bool { | ||||
| 	if qc.keysUnderTest.PartitionKey != key && qc.keysUnderTest.SortKey != key { | ||||
| 		return false | ||||
| 	} | ||||
| 
 | ||||
|  |  | |||
|  | @ -19,6 +19,22 @@ func TestModExpr_Query(t *testing.T) { | |||
| 			PartitionKey: "pk", | ||||
| 			SortKey:      "sk", | ||||
| 		}, | ||||
| 		GSIs: []models.TableGSI{ | ||||
| 			{ | ||||
| 				Name: "with-color", | ||||
| 				Keys: models.KeyAttribute{ | ||||
| 					PartitionKey: "color", | ||||
| 					SortKey:      "shade", | ||||
| 				}, | ||||
| 			}, | ||||
| 			{ | ||||
| 				Name: "with-apples", | ||||
| 				Keys: models.KeyAttribute{ | ||||
| 					PartitionKey: "apples", | ||||
| 					SortKey:      "sk", | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 
 | ||||
| 	t.Run("as queries", func(t *testing.T) { | ||||
|  | @ -113,10 +129,25 @@ func TestModExpr_Query(t *testing.T) { | |||
| 			), | ||||
| 
 | ||||
| 			// Querying the index
 | ||||
| 			scanCase("when request pk is fixed", | ||||
| 				`pk="prefix"`, | ||||
| 			scanCase("querying the index with the index pk", | ||||
| 				`color="blue"`, | ||||
| 				`#0 = :0`, | ||||
| 				exprNameIsString(0, 0, "pk", "prefix"), | ||||
| 				indexName("with-color"), | ||||
| 				exprNameIsString(0, 0, "color", "blue"), | ||||
| 			), | ||||
| 			scanCase("querying the index with the index pk and index sk", | ||||
| 				`color="red" and shade="gray"`, | ||||
| 				`(#0 = :0) AND (#1 = :1)`, | ||||
| 				indexName("with-color"), | ||||
| 				exprNameIsString(0, 0, "color", "red"), | ||||
| 				exprNameIsString(1, 1, "shade", "gray"), | ||||
| 			), | ||||
| 			scanCase("querying the index with the index pk and begins with index sk", | ||||
| 				`color="yellow" and shade ^= "dark"`, | ||||
| 				`(#0 = :0) AND (begins_with (#1, :1))`, | ||||
| 				indexName("with-color"), | ||||
| 				exprNameIsString(0, 0, "color", "yellow"), | ||||
| 				exprNameIsString(1, 1, "shade", "dark"), | ||||
| 			), | ||||
| 		} | ||||
| 
 | ||||
|  | @ -131,6 +162,7 @@ func TestModExpr_Query(t *testing.T) { | |||
| 				assert.NoError(t, err) | ||||
| 
 | ||||
| 				assert.True(t, plan.CanQuery) | ||||
| 				assert.Equal(t, scenario.indexName, plan.IndexName) | ||||
| 				assert.Equal(t, scenario.expectedFilter, aws.ToString(plan.Expression.KeyCondition())) | ||||
| 				for k, v := range scenario.expectedNames { | ||||
| 					assert.Equal(t, v, plan.Expression.Names()[k]) | ||||
|  | @ -824,6 +856,7 @@ type scanScenario struct { | |||
| 	description       string | ||||
| 	expression        string | ||||
| 	expectedFilter    string | ||||
| 	indexName         string | ||||
| 	expectedNames     map[string]string | ||||
| 	expectedValues    map[string]types.AttributeValue | ||||
| 	placeholderNames  map[string]string | ||||
|  | @ -844,6 +877,12 @@ func scanCase(description, expression, expectedFilter string, options ...func(ss | |||
| 	return ss | ||||
| } | ||||
| 
 | ||||
| func indexName(indexName string) func(ss *scanScenario) { | ||||
| 	return func(ss *scanScenario) { | ||||
| 		ss.indexName = indexName | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| func placeholderNames(placeholderNames map[string]string) func(ss *scanScenario) { | ||||
| 	return func(ss *scanScenario) { | ||||
| 		ss.placeholderNames = placeholderNames | ||||
|  |  | |||
|  | @ -16,10 +16,10 @@ type queryableIRAtom interface { | |||
| 	irAtom | ||||
| 
 | ||||
| 	// canBeExecutedAsQuery returns true if the atom is capable of being executed as a query
 | ||||
| 	canBeExecutedAsQuery(info *models.TableInfo, qci *queryCalcInfo) bool | ||||
| 	canBeExecutedAsQuery(qci *queryCalcInfo) bool | ||||
| 
 | ||||
| 	// calcQueryForQuery returns a key condition builder for this atom to include in a query
 | ||||
| 	calcQueryForQuery(info *models.TableInfo) (expression.KeyConditionBuilder, error) | ||||
| 	calcQueryForQuery() (expression.KeyConditionBuilder, error) | ||||
| } | ||||
| 
 | ||||
| type oprIRAtom interface { | ||||
|  | @ -43,10 +43,10 @@ type multiValueIRAtom interface { | |||
| 	calcGoValues(info *models.TableInfo) ([]any, error) | ||||
| } | ||||
| 
 | ||||
| func canExecuteAsQuery(ir irAtom, info *models.TableInfo, qci *queryCalcInfo) bool { | ||||
| func canExecuteAsQuery(ir irAtom, qci *queryCalcInfo) bool { | ||||
| 	queryable, isQuearyable := ir.(queryableIRAtom) | ||||
| 	if !isQuearyable { | ||||
| 		return false | ||||
| 	} | ||||
| 	return queryable.canBeExecutedAsQuery(info, qci) | ||||
| 	return queryable.canBeExecutedAsQuery(qci) | ||||
| } | ||||
|  |  | |||
|  | @ -41,12 +41,13 @@ func (p *Provider) DescribeTable(ctx context.Context, tableName string) (*models | |||
| 
 | ||||
| 	var tableInfo models.TableInfo | ||||
| 	tableInfo.Name = aws.ToString(out.Table.TableName) | ||||
| 	tableInfo.Keys = p.keySchemaToKeyAttributes(out.Table.KeySchema) | ||||
| 
 | ||||
| 	for _, keySchema := range out.Table.KeySchema { | ||||
| 		if keySchema.KeyType == types.KeyTypeHash { | ||||
| 			tableInfo.Keys.PartitionKey = aws.ToString(keySchema.AttributeName) | ||||
| 		} else if keySchema.KeyType == types.KeyTypeRange { | ||||
| 			tableInfo.Keys.SortKey = aws.ToString(keySchema.AttributeName) | ||||
| 	tableInfo.GSIs = make([]models.TableGSI, len(out.Table.GlobalSecondaryIndexes)) | ||||
| 	for i, gsiIndex := range out.Table.GlobalSecondaryIndexes { | ||||
| 		tableInfo.GSIs[i] = models.TableGSI{ | ||||
| 			Name: aws.ToString(gsiIndex.IndexName), | ||||
| 			Keys: p.keySchemaToKeyAttributes(gsiIndex.KeySchema), | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -57,6 +58,17 @@ func (p *Provider) DescribeTable(ctx context.Context, tableName string) (*models | |||
| 	return &tableInfo, nil | ||||
| } | ||||
| 
 | ||||
| func (p *Provider) keySchemaToKeyAttributes(keySchemaElements []types.KeySchemaElement) (keyAttribute models.KeyAttribute) { | ||||
| 	for _, keySchema := range keySchemaElements { | ||||
| 		if keySchema.KeyType == types.KeyTypeHash { | ||||
| 			keyAttribute.PartitionKey = aws.ToString(keySchema.AttributeName) | ||||
| 		} else if keySchema.KeyType == types.KeyTypeRange { | ||||
| 			keyAttribute.SortKey = aws.ToString(keySchema.AttributeName) | ||||
| 		} | ||||
| 	} | ||||
| 	return keyAttribute | ||||
| } | ||||
| 
 | ||||
| func (p *Provider) PutItem(ctx context.Context, name string, item models.Item) error { | ||||
| 	_, err := p.client.PutItem(ctx, &dynamodb.PutItemInput{ | ||||
| 		TableName: aws.String(name), | ||||
|  | @ -170,6 +182,7 @@ func (p *Provider) ScanItems( | |||
| func (p *Provider) QueryItems( | ||||
| 	ctx context.Context, | ||||
| 	tableName string, | ||||
| 	indexName string, | ||||
| 	filterExpr *expression.Expression, | ||||
| 	exclusiveStartKey map[string]types.AttributeValue, | ||||
| 	maxItems int, | ||||
|  | @ -179,6 +192,9 @@ func (p *Provider) QueryItems( | |||
| 	input := &dynamodb.QueryInput{ | ||||
| 		TableName: aws.String(tableName), | ||||
| 	} | ||||
| 	if indexName != "" { | ||||
| 		input.IndexName = aws.String(indexName) | ||||
| 	} | ||||
| 	if filterExpr != nil { | ||||
| 		input.KeyConditionExpression = filterExpr.KeyCondition() | ||||
| 		input.FilterExpression = filterExpr.Filter() | ||||
|  |  | |||
|  | @ -17,6 +17,7 @@ type TableProvider interface { | |||
| 	QueryItems( | ||||
| 		ctx context.Context, | ||||
| 		tableName string, | ||||
| 		indexName string, | ||||
| 		filterExpr *expression.Expression, | ||||
| 		exclusiveStartKey map[string]types.AttributeValue, | ||||
| 		maxItems int, | ||||
|  |  | |||
|  | @ -49,6 +49,7 @@ func (s *Service) doScan( | |||
| 	var ( | ||||
| 		filterExpr *expression.Expression | ||||
| 		runAsQuery bool | ||||
| 		index      string | ||||
| 		err        error | ||||
| 	) | ||||
| 	if expr != nil { | ||||
|  | @ -58,6 +59,7 @@ func (s *Service) doScan( | |||
| 		} | ||||
| 
 | ||||
| 		runAsQuery = plan.CanQuery | ||||
| 		index = plan.IndexName | ||||
| 		filterExpr = &plan.Expression | ||||
| 
 | ||||
| 		log.Printf("Running query over '%v'", tableInfo.Name) | ||||
|  | @ -69,7 +71,7 @@ func (s *Service) doScan( | |||
| 	var results []models.Item | ||||
| 	var lastEvalKey map[string]types.AttributeValue | ||||
| 	if runAsQuery { | ||||
| 		results, lastEvalKey, err = s.provider.QueryItems(ctx, tableInfo.Name, filterExpr, exclusiveStartKey, limit) | ||||
| 		results, lastEvalKey, err = s.provider.QueryItems(ctx, tableInfo.Name, index, filterExpr, exclusiveStartKey, limit) | ||||
| 	} else { | ||||
| 		results, lastEvalKey, err = s.provider.ScanItems(ctx, tableInfo.Name, filterExpr, exclusiveStartKey, limit) | ||||
| 	} | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ import ( | |||
| 
 | ||||
| type TestData struct { | ||||
| 	TableName string | ||||
| 	Index     []string | ||||
| 	Data      []map[string]interface{} | ||||
| } | ||||
| 
 | ||||
|  | @ -31,7 +32,7 @@ func SetupTestTable(t *testing.T, testData []TestData) *dynamodb.Client { | |||
| 		dynamodb.WithEndpointResolver(dynamodb.EndpointResolverFromURL("http://localhost:4566"))) | ||||
| 
 | ||||
| 	for _, table := range testData { | ||||
| 		_, err = dynamoClient.CreateTable(ctx, &dynamodb.CreateTableInput{ | ||||
| 		tableInput := &dynamodb.CreateTableInput{ | ||||
| 			TableName: aws.String(table.TableName), | ||||
| 			KeySchema: []types.KeySchemaElement{ | ||||
| 				{AttributeName: aws.String("pk"), KeyType: types.KeyTypeHash}, | ||||
|  | @ -45,7 +46,28 @@ func SetupTestTable(t *testing.T, testData []TestData) *dynamodb.Client { | |||
| 				ReadCapacityUnits:  aws.Int64(100), | ||||
| 				WriteCapacityUnits: aws.Int64(100), | ||||
| 			}, | ||||
| 		}) | ||||
| 		} | ||||
| 		for _, index := range table.Index { | ||||
| 			tableInput.AttributeDefinitions = append(tableInput.AttributeDefinitions, types.AttributeDefinition{ | ||||
| 				AttributeName: aws.String(index), | ||||
| 				AttributeType: types.ScalarAttributeTypeS, | ||||
| 			}) | ||||
| 			tableInput.GlobalSecondaryIndexes = append(tableInput.GlobalSecondaryIndexes, types.GlobalSecondaryIndex{ | ||||
| 				IndexName: aws.String(index + "-index"), | ||||
| 				KeySchema: []types.KeySchemaElement{ | ||||
| 					{AttributeName: aws.String(index), KeyType: types.KeyTypeHash}, | ||||
| 				}, | ||||
| 				Projection: &types.Projection{ | ||||
| 					ProjectionType: types.ProjectionTypeAll, | ||||
| 				}, | ||||
| 				ProvisionedThroughput: &types.ProvisionedThroughput{ | ||||
| 					ReadCapacityUnits:  aws.Int64(100), | ||||
| 					WriteCapacityUnits: aws.Int64(100), | ||||
| 				}, | ||||
| 			}) | ||||
| 		} | ||||
| 
 | ||||
| 		_, err = dynamoClient.CreateTable(ctx, tableInput) | ||||
| 		assert.NoError(t, err) | ||||
| 
 | ||||
| 		for _, item := range table.Data { | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue