public function testDoInsert() { $con = Propel::getServiceContainer()->getWriteConnection(BookTableMap::DATABASE_NAME); try { $c = new Criteria(); $c->setPrimaryTableName(BookTableMap::TABLE_NAME); $c->add(BookTableMap::AUTHOR_ID, 'lkhlkhj'); $db = Propel::getServiceContainer()->getAdapter($c->getDbName()); $c->doInsert($con); $this->fail('Missing expected exception on BAD SQL'); } catch (PropelException $e) { if ($db->isGetIdBeforeInsert()) { $this->assertContains($this->getSql('[INSERT INTO book (AUTHOR_ID,ID) VALUES (:p1,:p2)]'), $e->getMessage(), 'SQL query is written in the exception message'); } else { $this->assertContains($this->getSql('[INSERT INTO `book` (`AUTHOR_ID`) VALUES (:p1)]'), $e->getMessage(), 'SQL query is written in the exception message'); } } }
/** * Helper method which returns the primary key contained * in the given Criteria object. * * @param Criteria $criteria A Criteria. * @return ColumnMap If the Criteria object contains a primary key, or null if it doesn't. * * @throws \Propel\Runtime\Exception\RuntimeException */ private static function getPrimaryKey(Criteria $criteria) { // Assume all the keys are for the same table. $keys = $criteria->keys(); $key = $keys[0]; $table = $criteria->getTableName($key); $pk = null; if (!empty($table)) { $dbMap = Propel::getServiceContainer()->getDatabaseMap($criteria->getDbName()); $pks = $dbMap->getTable($table)->getPrimaryKeys(); if (!empty($pks)) { $pk = array_shift($pks); } } return $pk; }
/** * Method to perform inserts based on values and keys in a * Criteria. * <p> * If the primary key is auto incremented the data in Criteria * will be inserted and the auto increment value will be returned. * <p> * If the primary key is included in Criteria then that value will * be used to insert the row. * <p> * If no primary key is included in Criteria then we will try to * figure out the primary key from the database map and insert the * row with the next available id using util.db.IDBroker. * <p> * If no primary key is defined for the table the values will be * inserted as specified in Criteria and null will be returned. * * @param Criteria $criteria Object containing values to insert. * @param ConnectionInterface $con A ConnectionInterface connection. * @return mixed The primary key for the new row if the primary key is auto-generated. Otherwise will return null. * * @throws \Propel\Runtime\Exception\RuntimeException */ public static function doInsert($criteria, ConnectionInterface $con = null) { // The primary key $id = null; if (null === $con) { $con = Propel::getServiceContainer()->getWriteConnection($criteria->getDbName()); } $db = Propel::getServiceContainer()->getAdapter($criteria->getDbName()); // Get the table name and method for determining the primary // key value. $keys = $criteria->keys(); if (!empty($keys)) { $tableName = $criteria->getTableName($keys[0]); } else { throw new RuntimeException('Database insert attempted without anything specified to insert.'); } $tableName = $criteria->getTableName($keys[0]); $dbMap = Propel::getServiceContainer()->getDatabaseMap($criteria->getDbName()); $tableMap = $dbMap->getTable($tableName); $keyInfo = $tableMap->getPrimaryKeyMethodInfo(); $useIdGen = $tableMap->isUseIdGenerator(); //$keyGen = $con->getIdGenerator(); $pk = static::getPrimaryKey($criteria); // only get a new key value if you need to // the reason is that a primary key might be defined // but you are still going to set its value. for example: // a join table where both keys are primary and you are // setting both columns with your own values // pk will be null if there is no primary key defined for the table // we're inserting into. if (null !== $pk && $useIdGen && !$criteria->keyContainsValue($pk->getFullyQualifiedName()) && $db->isGetIdBeforeInsert()) { try { $id = $db->getId($con, $keyInfo); } catch (\Exception $e) { throw new RuntimeException('Unable to get sequence id.', 0, $e); } $criteria->add($pk->getFullyQualifiedName(), $id); } try { $adapter = Propel::getServiceContainer()->getAdapter($criteria->getDBName()); $qualifiedCols = $criteria->keys(); // we need table.column cols when populating values $columns = array(); // but just 'column' cols for the SQL foreach ($qualifiedCols as $qualifiedCol) { $columns[] = substr($qualifiedCol, strrpos($qualifiedCol, '.') + 1); } // add identifiers if ($adapter->useQuoteIdentifier()) { $columns = array_map(array($adapter, 'quoteIdentifier'), $columns); $tableName = $adapter->quoteIdentifierTable($tableName); } $sql = 'INSERT INTO ' . $tableName . ' (' . implode(',', $columns) . ')' . ' VALUES ('; // . substr(str_repeat("?,", count($columns)), 0, -1) . for ($p = 1, $cnt = count($columns); $p <= $cnt; $p++) { $sql .= ':p' . $p; if ($p !== $cnt) { $sql .= ','; } } $sql .= ')'; $params = static::buildParams($qualifiedCols, $criteria); $db->cleanupSQL($sql, $params, $criteria, $dbMap); $stmt = $con->prepare($sql); $db->bindValues($stmt, $params, $dbMap, $db); $stmt->execute(); } catch (\Exception $e) { Propel::log($e->getMessage(), Propel::LOG_ERR); throw new RuntimeException(sprintf('Unable to execute INSERT statement [%s]', $sql), 0, $e); } // If the primary key column is auto-incremented, get the id now. if (null !== $pk && $useIdGen && $db->isGetIdAfterInsert()) { try { $id = $db->getId($con, $keyInfo); } catch (\Exception $e) { throw new RuntimeException("Unable to get autoincrement id.", 0, $e); } } return $id; }
/** * Do Explain Plan for query object or query string * * @param ConnectionInterface $con propel connection * @param Criteria|string $query query the criteria or the query string * * @throws PropelException * @return PDOStatement A PDO statement executed using the connection, ready to be fetched */ public function doExplainPlan(ConnectionInterface $con, $query) { if ($query instanceof Criteria) { $params = array(); $dbMap = Propel::getServiceContainer()->getDatabaseMap($query->getDbName()); $sql = $query->createSelectSql($params); } else { $sql = $query; } $stmt = $con->prepare($this->getExplainPlanQuery($sql)); if ($query instanceof Criteria) { $this->bindValues($stmt, $params, $dbMap); } $stmt->execute(); return $stmt; }
/** * Init some properties with the help of outer class * @param Criteria $criteria The outer class */ public function init(Criteria $criteria) { try { $db = Propel::getServiceContainer()->getAdapter($criteria->getDbName()); $this->setAdapter($db); } catch (\Exception $e) { // we are only doing this to allow easier debugging, so // no need to throw up the exception, just make note of it. Propel::log("Could not get a AdapterInterface, sql may be wrong", Propel::LOG_ERR); } // init $this->realtable $realtable = $criteria->getTableForAlias($this->table); $this->realtable = $realtable ? $realtable : $this->table; }