github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/message/prepare.go (about) 1 // Copyright 2020 DataStax 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package message 16 17 import ( 18 "errors" 19 "fmt" 20 "io" 21 22 "github.com/datastax/go-cassandra-native-protocol/primitive" 23 ) 24 25 // Prepare is a request to prepare a CQL statement. 26 // +k8s:deepcopy-gen=true 27 // +k8s:deepcopy-gen:interfaces=github.com/datastax/go-cassandra-native-protocol/message.Message 28 type Prepare struct { 29 // The CQL query to prepare. 30 Query string 31 // The keyspace that the query should be executed in. 32 // Introduced in Protocol Version 5, also present in DSE protocol v2. 33 Keyspace string 34 } 35 36 func (m *Prepare) IsResponse() bool { 37 return false 38 } 39 40 func (m *Prepare) GetOpCode() primitive.OpCode { 41 return primitive.OpCodePrepare 42 } 43 44 func (m *Prepare) String() string { 45 return fmt.Sprintf("PREPARE (%v, %v)", m.Query, m.Keyspace) 46 } 47 48 func (m *Prepare) Flags() primitive.PrepareFlag { 49 var flags primitive.PrepareFlag 50 if m.Keyspace != "" { 51 flags = flags.Add(primitive.PrepareFlagWithKeyspace) 52 } 53 return flags 54 } 55 56 type prepareCodec struct{} 57 58 func (c *prepareCodec) Encode(msg Message, dest io.Writer, version primitive.ProtocolVersion) (err error) { 59 prepare, ok := msg.(*Prepare) 60 if !ok { 61 return errors.New(fmt.Sprintf("expected *message.Prepare, got %T", msg)) 62 } 63 if prepare.Query == "" { 64 return errors.New("cannot write PREPARE empty query string") 65 } else if err = primitive.WriteLongString(prepare.Query, dest); err != nil { 66 return fmt.Errorf("cannot write PREPARE query string: %w", err) 67 } 68 if version.SupportsPrepareFlags() { 69 flags := prepare.Flags() 70 if err = primitive.WriteInt(int32(flags), dest); err != nil { 71 return fmt.Errorf("cannot write PREPARE flags: %w", err) 72 } 73 if flags.Contains(primitive.PrepareFlagWithKeyspace) { 74 if prepare.Keyspace == "" { 75 return errors.New("cannot write empty keyspace") 76 } else if err = primitive.WriteString(prepare.Keyspace, dest); err != nil { 77 return fmt.Errorf("cannot write PREPARE keyspace: %w", err) 78 } 79 } 80 } 81 return 82 } 83 84 func (c *prepareCodec) EncodedLength(msg Message, version primitive.ProtocolVersion) (size int, err error) { 85 prepare, ok := msg.(*Prepare) 86 if !ok { 87 return -1, errors.New(fmt.Sprintf("expected *message.Prepare, got %T", msg)) 88 } 89 size += primitive.LengthOfLongString(prepare.Query) 90 if version.SupportsPrepareFlags() { 91 size += primitive.LengthOfInt // flags 92 if prepare.Keyspace != "" { 93 size += primitive.LengthOfString(prepare.Keyspace) 94 } 95 } 96 return size, nil 97 } 98 99 func (c *prepareCodec) Decode(source io.Reader, version primitive.ProtocolVersion) (msg Message, err error) { 100 prepare := &Prepare{} 101 if prepare.Query, err = primitive.ReadLongString(source); err != nil { 102 return nil, fmt.Errorf("cannot read PREPARE query: %w", err) 103 } 104 if version.SupportsPrepareFlags() { 105 var flags primitive.PrepareFlag 106 var f int32 107 if f, err = primitive.ReadInt(source); err != nil { 108 return nil, fmt.Errorf("cannot read PREPARE flags: %w", err) 109 } 110 flags = primitive.PrepareFlag(f) 111 if flags.Contains(primitive.PrepareFlagWithKeyspace) { 112 if prepare.Keyspace, err = primitive.ReadString(source); err != nil { 113 return nil, fmt.Errorf("cannot read PREPARE keyspace: %w", err) 114 } 115 } 116 } 117 return prepare, nil 118 } 119 120 func (c *prepareCodec) GetOpCode() primitive.OpCode { 121 return primitive.OpCodePrepare 122 }