1 /**
2  * Copyright 2015-2017 DataStax, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "php_driver.h"
18 #include "php_driver_types.h"
19 #include "util/result.h"
20 #include "util/ref.h"
21 #include "util/types.h"
22 
23 #include "DefaultIndex.h"
24 
25 zend_class_entry *php_driver_default_index_ce = NULL;
26 
27 php5to7_zval
php_driver_create_index(php_driver_ref * schema,const CassIndexMeta * meta TSRMLS_DC)28 php_driver_create_index(php_driver_ref *schema,
29                            const CassIndexMeta *meta TSRMLS_DC)
30 {
31   php5to7_zval result;
32   php_driver_index *index;
33   const char *name;
34   size_t name_length;
35 
36   PHP5TO7_ZVAL_UNDEF(result);
37 
38   PHP5TO7_ZVAL_MAYBE_MAKE(result);
39   object_init_ex(PHP5TO7_ZVAL_MAYBE_P(result), php_driver_default_index_ce);
40 
41   index = PHP_DRIVER_GET_INDEX(PHP5TO7_ZVAL_MAYBE_P(result));
42   index->meta   = meta;
43   index->schema = php_driver_add_ref(schema);
44 
45   cass_index_meta_name(meta, &name, &name_length);
46   PHP5TO7_ZVAL_MAYBE_MAKE(index->name);
47   PHP5TO7_ZVAL_STRINGL(PHP5TO7_ZVAL_MAYBE_P(index->name), name, name_length);
48 
49   return result;
50 }
51 
PHP_METHOD(DefaultIndex,name)52 PHP_METHOD(DefaultIndex, name)
53 {
54   php_driver_index *self;
55 
56   if (zend_parse_parameters_none() == FAILURE)
57     return;
58 
59   self = PHP_DRIVER_GET_INDEX(getThis());
60   RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(self->name), 1, 0);
61 }
62 
PHP_METHOD(DefaultIndex,target)63 PHP_METHOD(DefaultIndex, target)
64 {
65   php_driver_index *self;
66 
67   if (zend_parse_parameters_none() == FAILURE)
68     return;
69 
70   self = PHP_DRIVER_GET_INDEX(getThis());
71   if (PHP5TO7_ZVAL_IS_UNDEF(self->target)) {
72     const char *target;
73     size_t target_length;
74     cass_index_meta_target(self->meta, &target, &target_length);
75     PHP5TO7_ZVAL_MAYBE_MAKE(self->target);
76     PHP5TO7_ZVAL_STRINGL(PHP5TO7_ZVAL_MAYBE_P(self->target), target, target_length);
77   }
78 
79   RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(self->target), 1, 0);
80 }
81 
PHP_METHOD(DefaultIndex,kind)82 PHP_METHOD(DefaultIndex, kind)
83 {
84   php_driver_index *self;
85 
86   if (zend_parse_parameters_none() == FAILURE)
87     return;
88 
89   self = PHP_DRIVER_GET_INDEX(getThis());
90   if (PHP5TO7_ZVAL_IS_UNDEF(self->kind)) {
91     PHP5TO7_ZVAL_MAYBE_MAKE(self->kind);
92     switch (cass_index_meta_type(self->meta)) {
93       case CASS_INDEX_TYPE_KEYS:
94         PHP5TO7_ZVAL_STRING(PHP5TO7_ZVAL_MAYBE_P(self->kind), "keys");
95         break;
96       case CASS_INDEX_TYPE_CUSTOM:
97         PHP5TO7_ZVAL_STRING(PHP5TO7_ZVAL_MAYBE_P(self->kind), "custom");
98         break;
99       case CASS_INDEX_TYPE_COMPOSITES:
100         PHP5TO7_ZVAL_STRING(PHP5TO7_ZVAL_MAYBE_P(self->kind), "composites");
101         break;
102       default:
103         PHP5TO7_ZVAL_STRING(PHP5TO7_ZVAL_MAYBE_P(self->kind), "unknown");
104         break;
105     }
106   }
107 
108   RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(self->kind), 1, 0);
109 }
110 
php_driver_index_build_option(php_driver_index * index)111 void php_driver_index_build_option(php_driver_index *index)
112 {
113   const CassValue* options;
114 
115   PHP5TO7_ZVAL_MAYBE_MAKE(index->options);
116   array_init(PHP5TO7_ZVAL_MAYBE_P(index->options));
117   options = cass_index_meta_options(index->meta);
118   if (options) {
119     CassIterator* iterator = cass_iterator_from_map(options);
120     while (cass_iterator_next(iterator)) {
121       const char* key_str;
122       size_t key_str_length;
123       const char* value_str;
124       size_t value_str_length;
125       const CassValue* key = cass_iterator_get_map_key(iterator);
126       const CassValue* value = cass_iterator_get_map_value(iterator);
127 
128       cass_value_get_string(key, &key_str, &key_str_length);
129       cass_value_get_string(value, &value_str, &value_str_length);
130       PHP5TO7_ADD_ASSOC_STRINGL_EX(PHP5TO7_ZVAL_MAYBE_P(index->options),
131                                    key_str, key_str_length + 1,
132                                    value_str, value_str_length);
133     }
134   }
135 }
136 
PHP_METHOD(DefaultIndex,option)137 PHP_METHOD(DefaultIndex, option)
138 {
139   char *name;
140   php5to7_size name_len;
141   php_driver_index *self;
142   php5to7_zval* result;
143 
144   if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
145                             &name, &name_len) == FAILURE) {
146     return;
147   }
148 
149   self = PHP_DRIVER_GET_INDEX(getThis());
150   if (PHP5TO7_ZVAL_IS_UNDEF(self->options)) {
151     php_driver_index_build_option(self);
152   }
153 
154   if (PHP5TO7_ZEND_HASH_FIND(PHP5TO7_Z_ARRVAL_MAYBE_P(self->options),
155                          name, name_len + 1,
156                          result)) {
157     RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_DEREF(result), 1, 0);
158   }
159   RETURN_FALSE;
160 }
161 
PHP_METHOD(DefaultIndex,options)162 PHP_METHOD(DefaultIndex, options)
163 {
164   php_driver_index *self;
165 
166   if (zend_parse_parameters_none() == FAILURE)
167     return;
168 
169   self = PHP_DRIVER_GET_INDEX(getThis());
170   if (PHP5TO7_ZVAL_IS_UNDEF(self->options)) {
171     php_driver_index_build_option(self);
172   }
173 
174   RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_P(self->options), 1, 0);
175 }
176 
PHP_METHOD(DefaultIndex,className)177 PHP_METHOD(DefaultIndex, className)
178 {
179   php_driver_index *self;
180   php5to7_zval* result;
181 
182   if (zend_parse_parameters_none() == FAILURE)
183     return;
184 
185   self = PHP_DRIVER_GET_INDEX(getThis());
186   if (PHP5TO7_ZVAL_IS_UNDEF(self->options)) {
187     php_driver_index_build_option(self);
188   }
189 
190   if (PHP5TO7_ZEND_HASH_FIND(PHP5TO7_Z_ARRVAL_MAYBE_P(self->options),
191                          "class_name", sizeof("class_name"),
192                          result)) {
193     RETURN_ZVAL(PHP5TO7_ZVAL_MAYBE_DEREF(result), 1, 0);
194   }
195   RETURN_FALSE;
196 }
197 
PHP_METHOD(DefaultIndex,isCustom)198 PHP_METHOD(DefaultIndex, isCustom)
199 {
200   php_driver_index *self;
201   int is_custom;
202 
203   if (zend_parse_parameters_none() == FAILURE)
204     return;
205 
206   self = PHP_DRIVER_GET_INDEX(getThis());
207   if (PHP5TO7_ZVAL_IS_UNDEF(self->options)) {
208     php_driver_index_build_option(self);
209   }
210 
211   is_custom =
212       PHP5TO7_ZEND_HASH_EXISTS(PHP5TO7_Z_ARRVAL_MAYBE_P(self->options),
213                                "class_name", sizeof("class_name"));
214   RETURN_BOOL(is_custom);
215 }
216 
217 ZEND_BEGIN_ARG_INFO_EX(arginfo_name, 0, ZEND_RETURN_VALUE, 1)
218   ZEND_ARG_INFO(0, name)
219 ZEND_END_ARG_INFO()
220 
221 ZEND_BEGIN_ARG_INFO_EX(arginfo_none, 0, ZEND_RETURN_VALUE, 0)
222 ZEND_END_ARG_INFO()
223 
224 static zend_function_entry php_driver_default_index_methods[] = {
225   PHP_ME(DefaultIndex, name, arginfo_none, ZEND_ACC_PUBLIC)
226   PHP_ME(DefaultIndex, kind, arginfo_none, ZEND_ACC_PUBLIC)
227   PHP_ME(DefaultIndex, target, arginfo_none, ZEND_ACC_PUBLIC)
228   PHP_ME(DefaultIndex, option, arginfo_name, ZEND_ACC_PUBLIC)
229   PHP_ME(DefaultIndex, options, arginfo_none, ZEND_ACC_PUBLIC)
230   PHP_ME(DefaultIndex, className, arginfo_none, ZEND_ACC_PUBLIC)
231   PHP_ME(DefaultIndex, isCustom, arginfo_none, ZEND_ACC_PUBLIC)
232   PHP_FE_END
233 };
234 
235 static zend_object_handlers php_driver_default_index_handlers;
236 
237 static HashTable *
php_driver_type_default_index_gc(zval * object,php5to7_zval_gc table,int * n TSRMLS_DC)238 php_driver_type_default_index_gc(zval *object, php5to7_zval_gc table, int *n TSRMLS_DC)
239 {
240   *table = NULL;
241   *n = 0;
242   return zend_std_get_properties(object TSRMLS_CC);
243 }
244 
245 static HashTable *
php_driver_default_index_properties(zval * object TSRMLS_DC)246 php_driver_default_index_properties(zval *object TSRMLS_DC)
247 {
248   HashTable *props = zend_std_get_properties(object TSRMLS_CC);
249 
250   return props;
251 }
252 
253 static int
php_driver_default_index_compare(zval * obj1,zval * obj2 TSRMLS_DC)254 php_driver_default_index_compare(zval *obj1, zval *obj2 TSRMLS_DC)
255 {
256   if (Z_OBJCE_P(obj1) != Z_OBJCE_P(obj2))
257     return 1; /* different classes */
258 
259   return Z_OBJ_HANDLE_P(obj1) != Z_OBJ_HANDLE_P(obj1);
260 }
261 
262 static void
php_driver_default_index_free(php5to7_zend_object_free * object TSRMLS_DC)263 php_driver_default_index_free(php5to7_zend_object_free *object TSRMLS_DC)
264 {
265   php_driver_index *self = PHP5TO7_ZEND_OBJECT_GET(index, object);
266 
267   PHP5TO7_ZVAL_MAYBE_DESTROY(self->name);
268   PHP5TO7_ZVAL_MAYBE_DESTROY(self->kind);
269   PHP5TO7_ZVAL_MAYBE_DESTROY(self->target);
270   PHP5TO7_ZVAL_MAYBE_DESTROY(self->options);
271 
272   if (self->schema) {
273     php_driver_del_ref(&self->schema);
274     self->schema = NULL;
275   }
276   self->meta = NULL;
277 
278   zend_object_std_dtor(&self->zval TSRMLS_CC);
279   PHP5TO7_MAYBE_EFREE(self);
280 }
281 
282 static php5to7_zend_object
php_driver_default_index_new(zend_class_entry * ce TSRMLS_DC)283 php_driver_default_index_new(zend_class_entry *ce TSRMLS_DC)
284 {
285   php_driver_index *self =
286       PHP5TO7_ZEND_OBJECT_ECALLOC(index, ce);
287 
288   PHP5TO7_ZVAL_UNDEF(self->name);
289   PHP5TO7_ZVAL_UNDEF(self->kind);
290   PHP5TO7_ZVAL_UNDEF(self->target);
291   PHP5TO7_ZVAL_UNDEF(self->options);
292 
293   self->schema = NULL;
294   self->meta = NULL;
295 
296   PHP5TO7_ZEND_OBJECT_INIT_EX(index, default_index, self, ce);
297 }
298 
php_driver_define_DefaultIndex(TSRMLS_D)299 void php_driver_define_DefaultIndex(TSRMLS_D)
300 {
301   zend_class_entry ce;
302 
303   INIT_CLASS_ENTRY(ce, PHP_DRIVER_NAMESPACE "\\DefaultIndex", php_driver_default_index_methods);
304   php_driver_default_index_ce = zend_register_internal_class(&ce TSRMLS_CC);
305   zend_class_implements(php_driver_default_index_ce TSRMLS_CC, 1, php_driver_index_ce);
306   php_driver_default_index_ce->ce_flags     |= PHP5TO7_ZEND_ACC_FINAL;
307   php_driver_default_index_ce->create_object = php_driver_default_index_new;
308 
309   memcpy(&php_driver_default_index_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
310   php_driver_default_index_handlers.get_properties  = php_driver_default_index_properties;
311 #if PHP_VERSION_ID >= 50400
312   php_driver_default_index_handlers.get_gc          = php_driver_type_default_index_gc;
313 #endif
314   php_driver_default_index_handlers.compare_objects = php_driver_default_index_compare;
315   php_driver_default_index_handlers.clone_obj = NULL;
316 }
317