Overview

Namespaces

  • cassandra
  • None
  • PHP
  • phpcassa
    • Batch
    • Connection
    • Index
    • Iterator
    • Schema
      • DataType
    • Util
    • UUID

Classes

  • AbstractColumnFamily
  • ColumnFamily
  • ColumnSlice
  • SuperColumnFamily
  • SystemManager
  • UUID
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: namespace phpcassa;
  3: 
  4: use phpcassa\ColumnFamily;
  5: use phpcassa\ColumnSlice;
  6: 
  7: use cassandra\Deletion;
  8: use cassandra\ColumnParent;
  9: use cassandra\ColumnPath;
 10: use cassandra\CounterColumn;
 11: use cassandra\CounterSuperColumn;
 12: use cassandra\ColumnOrSuperColumn;
 13: use cassandra\Column;
 14: use cassandra\SuperColumn;
 15: 
 16: /**
 17:  * Representation of a super column family in Cassandra.
 18:  *
 19:  * Subclasses \phpcassa\ColumnFamily, so those methods are also
 20:  * available.
 21:  *
 22:  * @package phpcassa
 23:  */
 24: class SuperColumnFamily extends AbstractColumnFamily {
 25: 
 26:     /**
 27:      * Fetch a single super column.
 28:      *
 29:      * Returns an array of the subcolumns in that super column.
 30:      *
 31:      * @param string $key row key to fetch
 32:      * @param mixed $super_column return only subcolumns of this super column
 33:      * @param \phpcassa\ColumnSlice a slice of subcolumns to fetch, or null
 34:      * @param mixed[] $column_names limit the subcolumns fetched to this list
 35:      * @param ConsistencyLevel $consistency_level affects the guaranteed
 36:      *        number of nodes that must respond before the operation returns
 37:      *
 38:      * @return mixed array(subcolumn_name => subcolumn_value)
 39:      */
 40:     public function get_super_column($key,
 41:                                      $super_column,
 42:                                      $column_slice=null,
 43:                                      $column_names=null,
 44:                                      $consistency_level=null) {
 45: 
 46:         $cp = $this->create_column_parent($super_column);
 47:         $slice = $this->create_slice_predicate($column_names, $column_slice, false);
 48:         return $this->_get($key, $cp, $slice, $consistency_level);
 49:     }
 50: 
 51:     /**
 52:      * Fetch a super column from multiple rows from this column family.
 53:      *
 54:      * The returned array will map directly from keys to the subcolumn
 55:      * array; the super column layer is omitted.
 56:      *
 57:      * @param string[] $keys row keys to fetch
 58:      * @param mixed $super_column return only subcolumns of this super column
 59:      * @param \phpcassa\ColumnSlice a slice of subcolumns to fetch, or null
 60:      * @param mixed[] $column_names limit the subcolumns fetched to this list
 61:      * @param ConsistencyLevel $consistency_level affects the guaranteed
 62:      *        number of nodes that must respond before the operation returns
 63:      * @param int $buffer_size the number of keys to multiget at a single time. If your
 64:      *        rows are large, having a high buffer size gives poor performance; if your
 65:      *        rows are small, consider increasing this value.
 66:      *
 67:      * @return mixed array(key => array(subcolumn_name => subcolumn_value))
 68:      */
 69:     public function multiget_super_column($keys,
 70:                                           $super_column,
 71:                                           $column_slice=null,
 72:                                           $column_names=null,
 73:                                           $consistency_level=null,
 74:                                           $buffer_size=16)  {
 75: 
 76:         $cp = $this->create_column_parent($super_column);
 77:         $slice = $this->create_slice_predicate($column_names, $column_slice, false);
 78: 
 79:         return $this->_multiget($keys, $cp, $slice, $consistency_level, $buffer_size);
 80:     }
 81: 
 82:     /**
 83:      * Count the number of subcolumns in a supercolumn.
 84:      *
 85:      * @param string $key row to be counted
 86:      * @param mixed $super_column count only subcolumns in this super column
 87:      * @param \phpcassa\ColumnSlice a slice of subcolumns to count, or null
 88:      * @param mixed[] $column_names limit the possible subcolumns or counted to this list
 89:      * @param ConsistencyLevel $consistency_level affects the guaranteed
 90:      *        number of nodes that must respond before the operation returns
 91:      *
 92:      * @return int
 93:      */
 94:     public function get_subcolumn_count($key,
 95:                                         $super_column,
 96:                                         $column_slice=null,
 97:                                         $column_names=null,
 98:                                         $consistency_level=null) {
 99: 
100:         $cp = $this->create_column_parent($super_column);
101:         $slice = $this->create_slice_predicate(
102:             $column_names, $column_slice, false, ColumnSlice::MAX_COUNT);
103: 
104:         return $this->_get_count($key, $cp, $slice, $consistency_level);
105:     }
106: 
107:     /**
108:      * Count the number of subcolumns in a particular super column
109:      * across a set of rows.
110:      *
111:      * @param string[] $keys rows to be counted
112:      * @param mixed $super_column count only subcolumns in this super column
113:      * @param \phpcassa\ColumnSlice a slice of subcolumns to count, or null
114:      * @param mixed[] $column_names limit the possible subcolumns counted to this list
115:      * @param ConsistencyLevel $consistency_level affects the guaranteed
116:      *        number of nodes that must respond before the operation returns
117:      *
118:      * @return mixed array(row_key => subcolumn_count)
119:      */
120:     public function multiget_subcolumn_count($keys,
121:                                              $super_column,
122:                                              $column_slice=null,
123:                                              $column_names=null,
124:                                              $consistency_level=null) {
125: 
126:         $cp = $this->create_column_parent($super_column);
127:         $slice = $this->create_slice_predicate(
128:             $column_names, $column_slice, false, ColumnSlice::MAX_COUNT);
129: 
130:         return $this->_multiget_count($keys, $cp, $slice, $consistency_level);
131:     }
132: 
133:     /**
134:      * Get an iterator over a particular super column across a range of rows.
135:      *
136:      * The returned iterator will return one array per row. This array will
137:      * look like array($rowkey, $subcolumns). Note that the super column layer
138:      * is omitted from the results.
139:      *
140:      * @param mixed $super_column return only columns in this super column
141:      * @param mixed $key_start fetch rows with a key >= this
142:      * @param mixed $key_finish fetch rows with a key <= this
143:      * @param int $row_count limit the number of rows returned to this amount
144:      * @param \phpcassa\ColumnSlice a slice of subcolumns to fetch, or null
145:      * @param mixed[] $column_names limit the subcolumns fetched to this list
146:      * @param ConsistencyLevel $consistency_level affects the guaranteed
147:      *        number of nodes that must respond before the operation returns
148:      * @param int $buffer_size When calling `get_range`, the intermediate results need
149:      *        to be buffered if we are fetching many rows, otherwise the Cassandra
150:      *        server will overallocate memory and fail.  This is the size of
151:      *        that buffer in number of rows.
152:      *
153:      * @return phpcassa\Iterator\RangeColumnFamilyIterator
154:      */
155:     public function get_super_column_range($super_column,
156:                                            $key_start="",
157:                                            $key_finish="",
158:                                            $row_count=self::DEFAULT_ROW_COUNT,
159:                                            $column_slice=null,
160:                                            $column_names=null,
161:                                            $consistency_level=null,
162:                                            $buffer_size=null) {
163: 
164:         $cp = $this->create_column_parent($super_column);
165:         $slice = $this->create_slice_predicate($column_names, $column_slice, false);
166: 
167:         return $this->_get_range($key_start, $key_finish, $row_count,
168:             $cp, $slice, $consistency_level, $buffer_size);
169:     }
170: 
171:     /**
172:      * Increment or decrement a counter.
173:      *
174:      * `value` should be an integer, either positive or negative, to be added
175:      * to a counter column. By default, `value` is 1.
176:      *
177:      * This method is not idempotent. Retrying a failed add may result
178:      * in a double count. You should consider using a separate
179:      * ConnectionPool with retries disabled for column families
180:      * with counters.
181:      *
182:      * Only available in Cassandra 0.8.0 and later.
183:      *
184:      * @param string $key the row to insert or update the columns in
185:      * @param mixed $super_column the super column to use
186:      * @param mixed $column the column name of the counter
187:      * @param int $value the amount to adjust the counter by
188:      * @param ConsistencyLevel $consistency_level affects the guaranteed
189:      *        number of nodes that must respond before the operation returns
190:      */
191:     public function add($key, $super_column, $column, $value=1,
192:                         $consistency_level=null) {
193:         $packed_key = $this->pack_key($key);
194:         $cp = $this->create_column_parent($super_column);
195:         $counter = new CounterColumn();
196:         $counter->name = $this->pack_name($column);
197:         $counter->value = $value;
198:         return $this->pool->call("add", $packed_key, $cp, $counter,
199:             $this->wcl($consistency_level));
200:     }
201: 
202:     /**
203:      * Remove a super column from a row or a set of subcolumns from
204:      * a single super column.
205:      *
206:      * @param string $key the row to remove columns from
207:      * @param mixed $super_column only remove this super column or its subcolumns
208:      * @param mixed[] $subcolumns the subcolumns to remove. If null, the entire
209:      *                            supercolumn will be removed.
210:      * @param ConsistencyLevel $consistency_level affects the guaranteed
211:      *        number of nodes that must respond before the operation returns
212:      *
213:      * @return int the timestamp for the operation
214:      */
215:     public function remove_super_column($key, $super_column, $subcolumns=null,
216:                                         $consistency_level=null) {
217: 
218:         if ($subcolumns === null || count($subcolumns) == 1) {
219:             $cp = new ColumnPath();
220:             $cp->column_family = $this->column_family;
221:             $cp->super_column = $this->pack_name($super_column, true);
222:             if ($subcolumns !== null) {
223:                 $cp->column = $this->pack_name($subcolumns[0], false);
224:             }
225:             return $this->_remove_single($key, $cp, $consistency_level);
226:         } else {
227:             $deletion = new Deletion();
228:             $deletion->super_column = $this->pack_name($super_column, true);
229:             if ($subcolumns !== null) {
230:                 $predicate = $this->create_slice_predicate($subcolumns, null, false);
231:                 $deletion->predicate = $predicate;
232:             }
233:             return $this->_remove_multi($key, $deletion, $consistency_level);
234:         }
235:     }
236: 
237:     /**
238:      * Remove a counter at the specified location.
239:      *
240:      * Note that counters have limited support for deletes: if you remove a
241:      * counter, you must wait to issue any following update until the delete
242:      * has reached all the nodes and all of them have been fully compacted.
243:      *
244:      * Available in Cassandra 0.8.0 and later.
245:      *
246:      * @param string $key the key for the row
247:      * @param mixed $super_column the super column the counter is in
248:      * @param mixed $column the column name of the counter; if left as null,
249:      *                      the entire super column will be removed
250:      * @param ConsistencyLevel $consistency_level affects the guaranteed
251:      *        number of nodes that must respond before the operation returns
252:      */
253:     public function remove_counter($key, $super_column, $column=null,
254:                                    $consistency_level=null) {
255:         $cp = new ColumnPath();
256:         $packed_key = $this->pack_key($key);
257:         $cp->column_family = $this->column_family;
258:         $cp->super_column = $this->pack_name($super_column, true);
259:         if ($column !== null)
260:             $cp->column = $this->pack_name($column);
261:         $this->pool->call("remove_counter", $packed_key, $cp,
262:             $this->wcl($consistency_level));
263:     }
264: 
265:     protected function dict_to_coscs($data, $timestamp, $ttl) {
266:         $have_counters = $this->has_counters;
267:         $ret = array();
268:         foreach ($data as $name => $value) {
269:             $cosc = new ColumnOrSuperColumn();
270:             if($have_counters) {
271:                 $sub = new CounterSuperColumn();
272:                 $cosc->counter_super_column = $sub;
273:             } else {
274:                 $sub = new SuperColumn();
275:                 $cosc->super_column = $sub;
276:             }
277:             $sub->name = $this->pack_name($name, true, self::NON_SLICE, true);
278:             $sub->columns = $this->dict_to_columns($value, $timestamp, $ttl);
279:             $ret[] = $cosc;
280:         }
281: 
282:         return $ret;
283:     }
284: 
285:     protected function array_to_coscs($data, $timestamp, $ttl) {
286:         $have_counters = $this->has_counters;
287:         $ret = array();
288:         foreach ($data as $supercol) {
289:             list($name, $columns) = $supercol;
290:             $cosc = new ColumnOrSuperColumn();
291:             if($have_counters) {
292:                 $sub = new CounterSuperColumn();
293:                 $cosc->counter_super_column = $sub;
294:             } else {
295:                 $sub = new SuperColumn();
296:                 $cosc->super_column = $sub;
297:             }
298:             $sub->name = $this->pack_name($name, true, self::NON_SLICE, false);
299:             $sub->columns = $this->array_to_columns($columns, $timestamp, $ttl);
300:             $ret[] = $cosc;
301:         }
302: 
303:         return $ret;
304:     }
305: 
306:     protected function dict_to_columns($array, $timestamp, $ttl) {
307:         $ret = array();
308:         foreach($array as $name => $value) {
309:             if($this->has_counters) {
310:                 $column = new CounterColumn();
311:             } else {
312:                 $column = new Column();
313:                 $column->timestamp = $timestamp;
314:                 $column->ttl = $ttl;
315:             }
316:             $column->name = $this->pack_name(
317:                 $name, false, self::NON_SLICE, true);
318:             $column->value = $this->pack_value($value, $column->name);
319:             $ret[] = $column;
320:         }
321:         return $ret;
322:     }
323: 
324:     protected function array_to_columns($array, $timestamp, $ttl) {
325:         $ret = array();
326:         foreach($array as $col) {
327:             list($name, $value) = $col;
328:             if($this->has_counters) {
329:                 $column = new CounterColumn();
330:             } else {
331:                 $column = new Column();
332:                 $column->timestamp = $timestamp;
333:                 $column->ttl = $ttl;
334:             }
335:             $column->name = $this->pack_name(
336:                 $name, false, self::NON_SLICE, false);
337:             $column->value = $this->pack_value($value, $column->name);
338:             $ret[] = $column;
339:         }
340:         return $ret;
341:     }
342: 
343:     protected function coscs_to_dict($array_of_coscs) {
344:         $ret = array();
345:         $first = $array_of_coscs[0];
346:         if($first->column) { // normal columns
347:             foreach($array_of_coscs as $cosc) {
348:                 $name = $this->unpack_name($cosc->column->name, false);
349:                 $value = $this->unpack_value($cosc->column->value, $cosc->column->name);
350:                 $ret[$name] = $value;
351:             }
352:         } else if($first->super_column) { // super columns
353:             foreach($array_of_coscs as $cosc) {
354:                 $name = $this->unpack_name($cosc->super_column->name, true);
355:                 $columns = $cosc->super_column->columns;
356:                 $ret[$name] = $this->columns_to_dict($columns, false);
357:             }
358:         } else if ($first->counter_column) {
359:             foreach($array_of_coscs as $cosc) {
360:                 $name = $this->unpack_name($cosc->counter_column->name, false);
361:                 $ret[$name] = $cosc->counter_column->value;
362:             }
363:         } else { // counter_super_column
364:             foreach($array_of_coscs as $cosc) {
365:                 $name = $this->unpack_name($cosc->counter_super_column->name, true);
366:                 $columns = $cosc->counter_super_column->columns;
367:                 $ret[$name] = $this->columns_to_dict($columns, true);
368:             }
369:         }
370:         return $ret;
371:     }
372: 
373:     protected function coscs_to_array($array_of_coscs) {
374:         $ret = array();
375:         $first = $array_of_coscs[0];
376:         if($first->column) { // normal columns
377:             foreach($array_of_coscs as $cosc) {
378:                 $name = $this->unpack_name($cosc->column->name, false, false);
379:                 $value = $this->unpack_value($cosc->column->value, $cosc->column->name);
380:                 $ret[] = array($name, $value);
381:             }
382:         } else if($first->super_column) { // super columns
383:             foreach($array_of_coscs as $cosc) {
384:                 $name = $this->unpack_name($cosc->super_column->name, true, false);
385:                 $columns = $cosc->super_column->columns;
386:                 $ret[] = array($name, $this->columns_to_array($columns, false));
387:             }
388:         } else if ($first->counter_column) {
389:             foreach($array_of_coscs as $cosc) {
390:                 $name = $this->unpack_name($cosc->counter_column->name, false, false);
391:                 $ret[] = array($name, $cosc->counter_column->value);
392:             }
393:         } else { // counter_super_column
394:             foreach($array_of_coscs as $cosc) {
395:                 $name = $this->unpack_name($cosc->counter_super_column->name, true, false);
396:                 $columns = $cosc->counter_super_column->columns;
397:                 $ret[] = array($name, $this->columns_to_array($columns, true));
398:             }
399:         }
400:         return $ret;
401:     }
402: 
403:     protected function unpack_coscs_attrs($array_of_coscs) {
404:         $ret = array();
405:         $first = $array_of_coscs[0];
406:         if($first->column) { // normal columns
407:             foreach($array_of_coscs as $cosc) {
408:                 $col = $cosc->column;
409:                 $col->value = $this->unpack_value($col->value, $col->name);
410:                 $col->name = $this->unpack_name($col->name, false, false);
411:                 $ret[] = $col;
412:             }
413:         } else if($first->super_column) { // super columns
414:             foreach($array_of_coscs as $cosc) {
415:                 $supercol = $cosc->super_column;
416:                 $supercol->name = $this->unpack_name(
417:                         $supercol->name, true, false);
418:                 $supercol->columns = $this->unpack_subcolumn_attrs(
419:                         $supercol->columns, false);
420:                 $ret[] = $supercol;
421:             }
422:         } else if ($first->counter_column) {
423:             foreach($array_of_coscs as $cosc) {
424:                 $col = $cosc->counter_column;
425:                 $col->name = $this->unpack_name($col->name, false, false);
426:                 $ret[] = $col;
427:             }
428:         } else { // counter_super_column
429:             foreach($array_of_coscs as $cosc) {
430:                 $supercol = $cosc->super_column;
431:                 $supercol->name = $this->unpack_name(
432:                         $supercol->name, true, false);
433:                 $supercol->columns = $this->unpack_subcolumn_attrs(
434:                         $supercol->columns, true);
435:                 $ret[] = $supercol;
436:             }
437:         }
438:         return $ret;
439:     }
440: 
441:     protected function unpack_subcolumn_attrs($columns, $have_counters) {
442:         $ret = array();
443:         if (!$have_counters) {
444:             foreach($columns as $c) {
445:                 $c->value = $this->unpack_value($c->value, $c->name);
446:                 $c->name = $this->unpack_name($c->name, false, false);
447:                 $ret[] = $c;
448:             }
449:         } else {
450:             foreach($columns as $c) {
451:                 $c->name = $this->unpack_name($c->name, false, false);
452:                 $ret[] = $c;
453:             }
454:         }
455:         return $ret;
456:     }
457: 
458:     protected function columns_to_dict($columns, $have_counters) {
459:         $ret = array();
460:         if (!$have_counters) {
461:             foreach($columns as $c) {
462:                 $value = $this->unpack_value($c->value, $c->name);
463:                 $name  = $this->unpack_name($c->name, false);
464:                 $ret[$name] = $value;
465:             }
466:         } else {
467:             foreach($columns as $c) {
468:                 $name = $this->unpack_name($c->name, false);
469:                 $ret[$name] = $c->value;
470:             }
471:         }
472:         return $ret;
473:     }
474: 
475:     protected function columns_to_array($columns, $have_counters) {
476:         $ret = array();
477:         if (!$have_counters) {
478:             foreach($columns as $c) {
479:                 $value = $this->unpack_value($c->value, $c->name);
480:                 $name  = $this->unpack_name($c->name, false, false);
481:                 $ret[] = array($name, $value);
482:             }
483:         } else {
484:             foreach($columns as $c) {
485:                 $name = $this->unpack_name($c->name, false, false);
486:                 $ret[] = array($name, $c->value);
487:             }
488:         }
489:         return $ret;
490:     }
491: 
492: }
493: 
phpcassa API documentation generated by ApiGen 2.8.0