Пример #1
0
 /**
  * Querys the database with a plain text query.
  * @param string $sql the sql string
  * @param bool $plan flag for plan creation
  * @param string $table result table
  * @param array $options for further options that are handeled by the queue
  * @return array $response 
  */
 public function query($sql, $plan = false, $table, $options = array())
 {
     // init error array
     $errors = array();
     // check if there is a name for the new table
     if (empty($table)) {
         $tablename = false;
     } else {
         $tablename = $table;
     }
     // get group of the user
     $usrGrp = Daiquiri_Auth::getInstance()->getCurrentRole();
     if ($usrGrp !== null) {
         $options['usrGrp'] = $usrGrp;
     } else {
         $options['usrGrp'] = "guest";
     }
     // if plan type direct, obtain query plan
     if ($this->_processor->supportsPlanType("QPROC_SIMPLE") === true and $plan === false) {
         $plan = $this->_processor->getPlan($sql, $errors);
         if (!empty($errors)) {
             return array('status' => 'error', 'errors' => $errors);
         }
     } else {
         // if plan type is AlterPlan and no plan is available, throw error
         if ($this->_processor->supportsPlanType("QPROC_ALTERPLAN") === true and $plan === false) {
             $errors['planError'] = 'Query plan required. If you end up here, something went badly wrong';
             return array('status' => 'error', 'errors' => $errors);
         }
         // split plan into lines
         $processing = new Query_Model_Resource_Processing();
         $noMultilineCommentSQL = $processing->removeMultilineComments($plan);
         $multiLines = $processing->splitQueryIntoMultiline($noMultilineCommentSQL, $errors);
         $plan = $multiLines;
     }
     // process sql string
     $job = $this->_processor->query($sql, $errors, $plan, $tablename);
     if (!empty($errors)) {
         return array('status' => 'error', 'errors' => $errors);
     }
     // before submission, see if user has enough quota
     if ($this->_checkQuota($this->_queue, $usrGrp)) {
         $errors['quotaError'] = 'Your quota has been reached. Drop some tables to free space or contact the administrators';
         return array('status' => 'error', 'errors' => $errors);
     }
     // submit job
     $statusId = $this->_queue->submitJob($job, $errors, $options);
     if (!empty($errors)) {
         return array('status' => 'error', 'errors' => $errors);
     }
     // return with success
     return array('status' => 'ok', 'job' => $job);
 }
Пример #2
0
 /**
  * Creates a new table in the database with the given sql query.
  * SIDE EFFECT: changes $job array and fills in the missing data
  * @param array $job object that hold information about the query
  * @param array $errors holding any error that occurs
  * @param array $options any options that a specific implementation of submitJob needs to get
  * @return int $status
  */
 public function submitJob(&$job, array &$errors, $options = false)
 {
     // switch to user adapter
     $this->setAdapter(Daiquiri_Config::getInstance()->getUserDbAdapter());
     // get adapter config
     $config = $this->getAdapter()->getConfig();
     // get tablename
     $table = $job['table'];
     // check if the table already exists
     if ($this->_tableExists($table)) {
         $errors['submitError'] = "Table '{$table}' already exists";
         return false;
     }
     // create the actual sql statement
     $actualQuery = $job['fullActualQuery'];
     unset($job['fullActualQuery']);
     // fire up the database
     // determining the DB adapter that is used. if we have thought about that one, use direct querying
     // without using prepared statement (not that fast and uses memory)
     // if not, fall back to prepared statements querying (using adapter->query abstractions of ZEND)
     $adaptType = get_class($this->getAdapter());
     // if query syntax is checked server side without executing query (like using paqu_validateSQL in MySQL),
     // we just fire up the query. if not, we need to split multiline queries up and check for any exception
     // raised by the server
     if (Daiquiri_Config::getInstance()->query->validate->serverSide) {
         if (strpos(strtolower($adaptType), "pdo") !== false) {
             try {
                 $stmt = $this->getAdapter()->getConnection()->exec($actualQuery);
             } catch (Exception $e) {
                 $errors['submitError'] = $e->getMessage();
             }
         } else {
             // fallback version
             try {
                 $stmt = $this->getAdapter()->query($actualQuery);
             } catch (Exception $e) {
                 $errors['submitError'] = $e->getMessage();
             }
             $stmt->closeCursor();
         }
     } else {
         // split the query into multiple queries...
         $processing = new Query_Model_Resource_Processing();
         $multiLine = $processing->splitQueryIntoMultiline($actualQuery, $errors);
         foreach ($multiLine as $query) {
             if (strpos(strtolower($adaptType), "pdo") !== false) {
                 try {
                     $stmt = $this->getAdapter()->getConnection()->exec($query);
                 } catch (Exception $e) {
                     $errors['submitError'] = $e->getMessage();
                     break;
                 }
             } else {
                 try {
                     $stmt = $this->getAdapter()->query($query);
                 } catch (Exception $e) {
                     $errors['submitError'] = $e->getMessage();
                     break;
                 }
             }
         }
         if (strpos(strtolower($adaptType), "pdo") === false) {
             $stmt->closeCursor();
         }
     }
     // if error has been raised just report it and don't add a job
     if (!empty($errors)) {
         return Query_Model_Resource_DirectQuery::$_status['error'];
     }
     // switch to user adapter (it could have been changed by the query, due to a "USE" statement)
     $this->setAdapter(Daiquiri_Config::getInstance()->getUserDbAdapter());
     // check if it worked
     if (in_array($table, $this->getAdapter()->listTables())) {
         // set status
         $statusId = Query_Model_Resource_DirectQuery::$_status['success'];
     } else {
         $statusId = Query_Model_Resource_DirectQuery::$_status['error'];
     }
     if (!empty($options) && array_key_exists('jobId', $options)) {
         $job['id'] = "{$options['jobId']}";
     }
     $job['database'] = $config['dbname'];
     $job['host'] = $config['host'];
     $job['time'] = date("Y-m-d\\TH:i:s");
     $job['user_id'] = Daiquiri_Auth::getInstance()->getCurrentId();
     $job['status_id'] = $statusId;
     // switch to web adapter
     $this->setAdapter(Daiquiri_Config::getInstance()->getWebAdapter());
     // insert job into jobs table
     $this->getAdapter()->insert('Query_Jobs', $job);
     // get Id of the new job
     $job['id'] = $this->getAdapter()->lastInsertId();
     // get username and status
     $statusStrings = array_flip(Query_Model_Resource_DirectQuery::$_status);
     $job['status'] = $statusStrings[$statusId];
     $job['username'] = Daiquiri_Auth::getInstance()->getCurrentUsername();
     return $statusId;
 }