public function testGetIndexes() { $table = new MingoTable('tablename'); $table->setIndex('index1', array('one', 'two')); $index_list = $table->getIndexes(); $this->assertEquals(1, count($index_list)); $table->setIndex('index2', array('two', 'three')); $index_list = $table->getIndexes(); $this->assertEquals(2, count($index_list)); }
protected function getTable($name = '') { if (empty($name)) { $name = get_class($this); } //if $table = new MingoTable($name); $table->setIndex('foobarbaz', array('foo', 'bar', 'baz')); $table->setField('foo', MingoField::TYPE_INT); $table->setIndex('barbaz', array('bar', 'baz')); return $table; }
/** * allows customizing the field sql type using the schema's field hints * * @since 10-19-10 * @param string $field the field name * @param MingoSchema $schema the schema for the table * @return string */ protected function normalizeSqlType(MingoTable $table, $field) { $ret_str = ''; $field_instance = $table->getField($field); switch ($field_instance->getType()) { case MingoField::TYPE_INT: if ($field_instance->hasRange()) { $max_size = $this->getMaxSize(); // http://help.scibit.com/mascon/masconMySQL_Field_Types.html if ($max_size < 128) { $ret_str = 'TINYINT(4)'; } else { if ($max_size < 32768) { $ret_str = 'SMALLINT'; } else { if ($max_size < 8388608) { $ret_str = 'MEDIUMINT'; } else { if ($max_size < 2147483648.0) { $ret_str = 'INT(11)'; } else { $ret_str = 'BIGINT'; } } } } //if/else if.../else } else { $ret_str = 'INT(11)'; } //if/else break; case MingoField::TYPE_POINT: $ret_str = 'POINT'; break; case MingoField::TYPE_BOOL: $ret_str = 'TINYINT(4)'; break; case MingoField::TYPE_FLOAT: $ret_str = 'FLOAT'; break; case MingoField::TYPE_STR: case MingoField::TYPE_LIST: case MingoField::TYPE_MAP: case MingoField::TYPE_DEFAULT: default: if ($field_instance->hasRange()) { if ($field_instance->isFixedSize()) { $ret_str = sprintf('CHAR(%s)', $field_instance->getMaxSize()); } else { $ret_str = sprintf('VARCHAR(%s)', $field_instance->getMaxSize()); } //if/else } else { $ret_str = 'VARCHAR(100)'; } //if/else break; } //switch return $ret_str; }
/** * converts the map into a document so Lucene can save it * * @param MingoTable $table * @param array $map the raw map passed to {@link insert()} or {@link update()} * @return Zend_Search_Lucene_Document */ protected function normalizeMap(MingoTable $table, array $map) { $document = new Zend_Search_Lucene_Document(); // add some fields that will be present in all documents... $document->addField(Zend_Search_Lucene_Field::unStored('_id', $map['_id'])); $document->addField(Zend_Search_Lucene_Field::binary('body', $this->getBody($map))); // add all the indexes into the document... foreach ($table->getIndexes() as $index) { foreach ($index->getFields() as $name => $options) { // use array_key... to account for null values... if (array_key_exists($name, $map)) { $val = null; if (is_array($map[$name])) { $val = join(' ', $map[$name]); } else { $val = $map[$name]; } //if/else $document->addField(Zend_Search_Lucene_Field::UnStored($name, $val)); // let's not try and add it twice... unset($map[$name]); } //if } //foreach } //foreach return $document; }
/** * allows customizing the field sql type using the schema's field hints * * @link http://www.postgresql.org/docs/8.1/static/datatype.html * @param \MingoTable $table * @param string $field the field name * @return string */ protected function normalizeSqlType(MingoTable $table, $field) { $ret_str = ''; $field_instance = $table->getField($field); switch ($field_instance->getType()) { case MingoField::TYPE_INT: $ret_str = 'INTEGER'; break; case MingoField::TYPE_BOOL: $ret_str = 'SMALLINT'; break; case MingoField::TYPE_FLOAT: $ret_str = 'REAL'; break; case MingoField::TYPE_POINT: $ret_str = 'POINT'; break; case MingoField::TYPE_STR: case MingoField::TYPE_LIST: case MingoField::TYPE_MAP: case MingoField::TYPE_DEFAULT: default: if ($field_instance->hasRange()) { if ($field_instance->isFixedSize()) { $ret_str = sprintf('CHAR(%s)', $field_instance->getMaxSize()); } else { $ret_str = sprintf('VARCHAR(%s)', $field_instance->getMaxSize()); } //if/else } else { $ret_str = 'VARCHAR(100)'; } //if/else break; } //switch return $ret_str; }
/** * do an integrity check on the fields * * @since 12-9-11 * @param MingoTable $table * @param array $map the key/value map that will be added to $table * @return array the $map with the best fields possible */ protected function assureFields(MingoTable $table, array $map) { // do some checks on the fields... foreach ($table->getFields() as $field_name => $field) { if ($field->isRequired()) { if (!array_key_exists($field_name, $map)) { $req_field_val = $field->getDefaultVal(); if ($req_field_val !== null) { $map[$field_name] = $req_field_val; } else { throw new DomainException(sprintf('cannot set() because $map is missing required field: [%s]', $field_name)); } //if/else } //if } //if if ($field->isUnique()) { if (isset($map[$field_name])) { $where_criteria = new MingoCriteria(); $where_criteria->isField($field_name, $map[$field_name]); if ($this->getOne($table, $where_criteria)) { throw new DomainException(sprintf('cannot set() on table %s because field [%s] with value [%s] is not unique', $table->getName(), $field_name, $map[$field_name])); } //if } //if } //if } //foreach return $map; }
/** * get the table this class will use on the db side * * @return MingoTable */ public function getTable() { // canary... if (!empty($this->table)) { return $this->table; } //if $table = new MingoTable($this->getTableName()); // set some of the default fields... $table->setField(self::_CREATED, MingoField::TYPE_INT); $table->setField(self::_UPDATED, MingoField::TYPE_INT); // let some custom stuff be added... $this->populateTable($table); $this->setTable($table); return $this->table; }
/** * assure right index is queried * * with 2 similar indexes using SQLite (and I assume MySQL) the interface's * index table selector would mess up because it would choose the first table * since the where would match and the sort was never taken into account, so a * PDOException would be thrown: * * PDOException: SQLSTATE[HY000]: General error: 1 no such column: che * * this test is here to make sure that is fixed * * @since 9-2-11 */ public function testSimilarIndexes() { $db = $this->getDb(); // create a more advanced table... $table = new MingoTable(__FUNCTION__); $table->setField('foo', MingoField::TYPE_STR); $table->setField('bar', MingoField::TYPE_STR); $table->setField('che', MingoField::TYPE_STR); // create 2 similar indexes... $table->setIndex('foo_and_bar', array('foo', 'bar')); $table->setIndex('foo_and_che', array('foo', 'che')); // make sure the table exists in the db $this->setTable($table); // now try and query the second index... $where_criteria = new MingoCriteria(); $where_criteria->isFoo(__FUNCTION__); $where_criteria->descChe(); // no errors should be thrown... $list = $db->get($table, $where_criteria); $this->assertEmpty($list); }
/** * find the index table name from the table and the list of fields the index comprises * * @param MingoTable $table the main table's name * @param MingoCriteria $where_criteria * @return string the index table name */ protected function findIndexTableName(MingoTable $table, MingoCriteria $where_criteria) { if (!$where_criteria->hasWhere() && !$where_criteria->hasSort()) { return ''; } //if $ret_str = ''; $is_match = false; $where_map = $where_criteria->getWhere(); $sort_map = $where_criteria->getSort(); // php >= 5.3, use when Mingo is ported to namespaces... ///$field_list = array_keys(array_replace($where_map,$sort_map)); // we need to get a list of all the fields used in the order they will be used $field_list = array_keys($where_map); if (!empty($sort_map)) { $field_list = array_unique(array_merge($field_list, array_keys($sort_map))); } //if // now go through the index and see if it matches all the fields... foreach ($table->getIndexes() as $index) { $field_i = 0; foreach ($index->getFieldNames() as $field) { if (isset($field_list[$field_i])) { if ($field === $field_list[$field_i]) { $is_match = true; $field_i++; } else { $is_match = false; break; } //if/else } else { break; } //if/else } //foreach if ($is_match) { // we're done, we found a match... $ret_str = $this->getIndexTableName($table, $index); break; } //if } //foreach if (!$is_match) { // since we couldn't find an index table, make sure the query can be valid // on the main table // we are selecting on the main table (no index is being used) so we can only // select or sort on 4 fields (by default): _id, _created, and _updated foreach ($field_list as $field) { // if a field in the where map is not in the main table we've got trouble // since an index table couldn't be found if (!in_array($field, $this->non_body_fields)) { $e_msg = sprintf('Could not match fields: [%s] sorted by fields: [%s] with an index table.', join(',', array_keys($where_map)), join(',', array_keys($sort_map))); // list the available index tables if we are in debug mode... if ($this->hasDebug()) { $e_msg .= ' Indexes available: '; $index_list = $this->getIndexes($table); $e_index_list = array(); foreach ($index_list as $index) { $e_index_list[] = sprintf('%s(%s)', $index->getName(), join(',', $index->getFieldNames())); } //foreach $e_msg .= join(', ', $e_index_list); } //if throw new RuntimeException($e_msg); } //if } //foreach } //if/else return $ret_str; }
/** * using the $table normalize the fields to make sure the values are what they should be * to query against the table * * @since 5-7-11 * @param MingoTable $table */ public function normalizeFields(MingoTable $table) { foreach ($this->field_map as $name => $val_list) { if ($table->hasField($name)) { $field = $table->getField($name); foreach (array_keys($val_list) as $key) { $val_list[$key] = $field->normalizeInVal($val_list[$key]); } //foreach } //if } //foreach }