/** * Gets the DBMS' native error code produced by the last query * * @return int the DBMS' error code */ function errorNative() { return @xf_db_errno($this->connection); }
/** * Takes an array of SQL query strings and performs them sequentially. * Will replace special value "__Tablename__auto_increment__" with the insert_id * from the table "Tablename" if one of the provided sql queries inserts a record * into Tablename. * * @param $sql An associative array [Table name] -> [SQL Query] of sql statements * to be executed. */ function performSQL($sql) { $ids = array(); $queue = $sql; $names = array_keys($sql); $tables = implode('|', $names); $skips = 0; // keep track of number of consecutive times we skip an iteration so we know when we have reached // a deadlock. if (func_num_args() >= 2) { $duplicates =& func_get_arg(1); if (!is_array($duplicates)) { throw new Exception(df_translate('scripts.Dataface.IO.performSQL.ERROR_PARAMETER_2', "In Dataface_IO::performSQL() 2nd argument is expected to be an array but received '" . get_class($duplicates) . "'.", array('class' => get_class($duplicates))), E_USER_ERROR); } } else { $duplicates = array(); } $queryAttempts = array(); $numQueries = count($queue); while (count($queue) > 0 and $skips < $numQueries) { $current_query = array_shift($queue); $current_table = array_shift($names); if (!isset($queryAttempts[$current_query])) { $queryAttempts[$current_query] = 1; } else { $queryAttempts[$current_query]++; } $matches = array(); if (preg_match('/__(' . $tables . ')__auto_increment__/', $current_query, $matches)) { $table = $matches[1]; if (isset($ids[$table])) { $current_query = preg_replace('/__' . $table . '__auto_increment__/', $ids[$table], $current_query); } else { array_push($queue, $current_query); array_push($names, $current_table); $skips++; continue; } } //$res = xf_db_query($current_query, $this->_table->db); $res = $this->dbObj->query($current_query, $this->_table->db, $this->lang); if (!$res || PEAR::isError($res)) { if (in_array(xf_db_errno($this->_table->db), array(MYSQL_ER_DUP_KEY, MYSQL_ER_DUP_ENTRY))) { /* * This is a duplicate record (ie: it already exists) */ $duplicates[] = $current_table; } else { if ($queryAttempts[$current_query] < 3 and in_array(xf_db_errno($this->_table->db), array(MYSQL_ER_NO_REFERENCED_ROW, MYSQL_ER_NO_REFERENCED_ROW_2, MYSQL_ER_ROW_IS_REFERENCED_2))) { /** * There is a foreign key constraint that is preventing us from inserting * this row. Perhaps we are just adding this row in the wrong order. * Let's re-add it to the queue. */ array_push($queue, $current_query); array_push($names, $current_table); } else { if (in_array(xf_db_errno($this->_table->db), array(MYSQL_ER_NO_REFERENCED_ROW, MYSQL_ER_NO_REFERENCED_ROW_2))) { /* THis failed due to a foreign key constraint. */ $err = PEAR::raiseError(sprintf(df_translate('scripts.Dataface.IO.performSQL.ERROR_FOREIGN_KEY', 'Failed to save record because a foreign key constraint failed: %s'), xf_db_error(df_db())), DATAFACE_E_NOTICE); error_log($err->toString()); return $err; } $err = PEAR::raiseError(DATAFACE_TABLE_SQL_ERROR, null, null, null, df_translate('scripts.Dataface.IO.performSQL.ERROR_PERFORMING_QUERY', "Error performing query '{$current_query}'", array('line' => 0, 'file' => '_', 'current_query' => $current_query)) . xf_db_errno($this->_table->db) . ': ' . xf_db_error($this->_table->db)); throw new Exception($err->toString(), E_USER_ERROR); } } } $ids[$current_table] = df_insert_id(); self::touchTable($current_table); $skips = 0; } $this->insertids = $ids; return true; }