1515 * encode as unsigned int.
1616 *
1717 * This is necessary because PHP doesn't have a real unsigned int type.
18+ *
19+ * You can pass in a signed int value, in which case the re-interpreted
20+ * 64-bit 2's complement value will be sent as an unsigned int.
21+ * For example:
22+ * new VTUnsignedInt(42) // will send 42
23+ * new VTUnsignedInt(-1) // will send 0xFFFFFFFFFFFFFFFF
24+ *
25+ * You can also pass in a string consisting of only decimal digits.
26+ * For example:
27+ * new VTUnsignedInt('12345') // will send 12345
1828 */
1929class VTUnsignedInt {
20- public $ value ;
30+ private $ value ;
2131
2232 public function __construct ($ value ) {
2333 if (is_int ($ value )) {
2434 $ this ->value = $ value ;
35+ } else if (is_string ($ value )) {
36+ if (! ctype_digit ($ value )) {
37+ throw new VTBadInputException ('Invalid string value given for VTUnsignedInt: ' . $ value );
38+ }
39+ $ this ->value = $ value ;
2540 } else {
26- throw new VTException ('Unsupported type for VTUnsignedInt ' );
41+ throw new VTBadInputException ('Unsupported type for VTUnsignedInt ' );
42+ }
43+ }
44+
45+ public function __toString () {
46+ if (is_int ($ this ->value )) {
47+ return sprintf ('%u ' , $ this ->value );
48+ } else {
49+ return strval ($ this ->value );
2750 }
2851 }
2952}
@@ -69,69 +92,62 @@ public static function BoundQuery($query, $vars) {
6992 public static function BindVariable ($ value ) {
7093 $ bind_var = new \query \BindVariable ();
7194
72- if (is_null ($ value )) {
73- $ bind_var ->setType (\query \BindVariable \Type::TYPE_NULL );
74- } else if (is_string ($ value )) {
75- $ bind_var ->setType (\query \BindVariable \Type::TYPE_BYTES );
76- $ bind_var ->setValueBytes ($ value );
77- } else if (is_int ($ value )) {
78- $ bind_var ->setType (\query \BindVariable \Type::TYPE_INT );
79- $ bind_var ->setValueInt ($ value );
80- } else if (is_float ($ value )) {
81- $ bind_var ->setType (\query \BindVariable \Type::TYPE_FLOAT );
82- $ bind_var ->setValueFloat ($ value );
83- } else if (is_object ($ value )) {
84- switch (get_class ($ value )) {
85- case 'VTUnsignedInt ' :
86- $ bind_var ->setType (\query \BindVariable \Type::TYPE_UINT );
87- $ bind_var ->setValueUint ($ value ->value );
88- break ;
89- default :
90- throw new VTException ('Unknown bind variable class: ' . get_class ($ value ));
95+ if (is_array ($ value )) {
96+ if (count ($ value ) == 0 ) {
97+ throw new VTBadInputException ('Empty list not allowed for list bind variable ' );
98+ }
99+
100+ $ bind_var ->setType (\query \Type::TUPLE );
101+
102+ foreach ($ value as $ elem ) {
103+ list ( $ type , $ tval ) = self ::TypedValue ($ elem );
104+ $ bind_var ->addValues ((new \query \Value ())->setType ($ type )->setValue ($ tval ));
91105 }
92- } else if (is_array ($ value )) {
93- self ::ListBindVariable ($ bind_var , $ value );
94106 } else {
95- throw new VTException ('Unknown bind variable type. ' );
107+ list ( $ type , $ tval ) = self ::TypedValue ($ value );
108+ $ bind_var ->setType ($ type );
109+ $ bind_var ->setValue ($ tval );
96110 }
97111
98112 return $ bind_var ;
99113 }
100114
101- protected static function ListBindVariable (&$ bind_var , array $ list ) {
102- if (count ($ list ) == 0 ) {
103- // The list is empty, so it has no type. VTTablet will reject an empty
104- // list anyway, so we'll just pretend it was a list of bytes.
105- $ bind_var ->setType (\query \BindVariable \Type::TYPE_BYTES_LIST );
106- return ;
107- }
108-
109- // Check type of first item to determine type of list.
110- // We only support lists whose elements have uniform types.
111- if (is_string ($ list [0 ])) {
112- $ bind_var ->setType (\query \BindVariable \Type::TYPE_BYTES_LIST );
113- $ bind_var ->setValueBytesList ($ list );
114- } else if (is_int ($ list [0 ])) {
115- $ bind_var ->setType (\query \BindVariable \Type::TYPE_INT_LIST );
116- $ bind_var ->setValueIntList ($ list );
117- } else if (is_float ($ list [0 ])) {
118- $ bind_var ->setType (\query \BindVariable \Type::TYPE_FLOAT_LIST );
119- $ bind_var ->setValueFloatList ($ list );
120- } else if (is_object ($ list [0 ])) {
121- switch (get_class ($ list [0 ])) {
115+ /**
116+ * Returns a tuple of detected \query\Type and string value compatible with \query\Value.
117+ */
118+ protected static function TypedValue ($ value ) {
119+ if (is_null ($ value )) {
120+ return array (
121+ \query \Type::NULL_ ,
122+ ''
123+ );
124+ } else if (is_string ($ value )) {
125+ return array (
126+ \query \Type::VARBINARY ,
127+ $ value
128+ );
129+ } else if (is_int ($ value )) {
130+ return array (
131+ \query \Type::INT64 ,
132+ strval ($ value )
133+ );
134+ } else if (is_float ($ value )) {
135+ return array (
136+ \query \Type::FLOAT64 ,
137+ strval ($ value )
138+ );
139+ } else if (is_object ($ value )) {
140+ switch (get_class ($ value )) {
122141 case 'VTUnsignedInt ' :
123- $ bind_var ->setType (\query \BindVariable \Type::TYPE_UINT_LIST );
124- $ value = array ();
125- foreach ($ list as $ val ) {
126- $ value [] = $ val ->value ;
127- }
128- $ bind_var ->setValueUintList ($ value );
129- break ;
142+ return array (
143+ \query \Type::UINT64 ,
144+ strval ($ value )
145+ );
130146 default :
131- throw new VTException ('Unknown list bind variable class: ' . get_class ($ list [ 0 ] ));
147+ throw new VTBadInputException ('Unknown \query\Value variable class: ' . get_class ($ value ));
132148 }
133149 } else {
134- throw new VTException ('Unknown list bind variable type. ' );
150+ throw new VTBadInputException ('Unknown type for \query\Value proto: ' . gettype ( $ value ) );
135151 }
136152 }
137153
@@ -162,27 +178,9 @@ public static function EntityId($keyspace_id, $value) {
162178 $ eid = new \vtgate \ExecuteEntityIdsRequest \EntityId ();
163179 $ eid ->setKeyspaceId ($ keyspace_id );
164180
165- if (is_string ($ value )) {
166- $ eid ->setXidType (\vtgate \ExecuteEntityIdsRequest \EntityId \Type::TYPE_BYTES );
167- $ eid ->setXidBytes ($ value );
168- } else if (is_int ($ value )) {
169- $ eid ->setXidType (\vtgate \ExecuteEntityIdsRequest \EntityId \Type::TYPE_INT );
170- $ eid ->setXidInt ($ value );
171- } else if (is_float ($ value )) {
172- $ eid ->setXidType (\vtgate \ExecuteEntityIdsRequest \EntityId \Type::TYPE_FLOAT );
173- $ eid ->setXidFloat ($ value );
174- } else if (is_object ($ value )) {
175- switch (get_class ($ value )) {
176- case 'VTUnsignedInt ' :
177- $ eid ->setXidType (\vtgate \ExecuteEntityIdsRequest \EntityId \Type::TYPE_UINT );
178- $ eid ->setXidUint ($ value ->value );
179- break ;
180- default :
181- throw new VTException ('Unknown entity ID class: ' . get_class ($ value ));
182- }
183- } else {
184- throw new VTException ('Unknown entity ID type. ' );
185- }
181+ list ( $ type , $ tval ) = self ::TypedValue ($ value );
182+ $ eid ->setXidType ($ type );
183+ $ eid ->setXidValue ($ tval );
186184
187185 return $ eid ;
188186 }
@@ -208,5 +206,31 @@ public function BoundKeyspaceIdQuery($query, $bind_vars, $keyspace, $keyspace_id
208206 $ value ->setKeyspaceIds ($ keyspace_ids );
209207 return $ value ;
210208 }
209+
210+ public function RowValues ($ row ) {
211+ $ values = array ();
212+
213+ // Row values are packed into a single buffer.
214+ // See the docs for the Row message in query.proto.
215+ $ start = 0 ;
216+ $ buf = $ row ->getValues ();
217+ $ lengths = $ row ->getLengths ();
218+ foreach ($ lengths as $ len ) {
219+ if ($ len < 0 ) {
220+ // This indicates a MySQL NULL value,
221+ // to distinguish it from a zero-length string.
222+ $ values [] = NULL ;
223+ } else {
224+ $ val = substr ($ buf , $ start , $ len );
225+ if ($ val === FALSE || strlen ($ val ) != $ len ) {
226+ throw new VTException ('Index out of bounds while decoding Row values ' );
227+ }
228+ $ values [] = $ val ;
229+ $ start += $ len ;
230+ }
231+ }
232+
233+ return $ values ;
234+ }
211235}
212236
0 commit comments