Uploaded image for project: 'ZABBIX BUGS AND ISSUES'
  1. ZABBIX BUGS AND ISSUES
  2. ZBX-9916

unclear "DBEXECUTE_ERROR" response for failed API calls

XMLWordPrintable

    • Icon: Incident report Incident report
    • Resolution: Unresolved
    • Icon: Trivial Trivial
    • None
    • 2.4.6
    • API (A)

      According to zabbix sources there are only 3 places which may return so short data:
      include/classes/db/DB.php:

      	protected static function reserveIds($table, $count) {
      		global $DB;
      
      		$tableSchema = self::getSchema($table);
      		$id_name = $tableSchema['key'];
      
      		$sql = 'SELECT nextid'.
      				' FROM ids'.
      				' WHERE table_name='.zbx_dbstr($table).
      					' AND field_name='.zbx_dbstr($id_name);
      
      		// SQLite3 does not support this syntax. Since we are in transaction, it can be ignored.
      		if ($DB['TYPE'] != ZBX_DB_SQLITE3) {
      			$sql = $sql.' FOR UPDATE';
      		}
      
      		$res = DBfetch(DBselect($sql));
      
      		if ($res) {
      			$maxNextId = bcadd($res['nextid'], $count, 0);
      
      			if (bccomp($maxNextId, ZBX_DB_MAX_ID) == 1) {
      				$nextid = self::refreshIds($table, $count);
      			}
      			else {
      				$sql = 'UPDATE ids'.
      						' SET nextid='.$maxNextId.
      						' WHERE table_name='.zbx_dbstr($table).
      							' AND field_name='.zbx_dbstr($id_name);
      
      				if (!DBexecute($sql)) {
      					self::exception(self::DBEXECUTE_ERROR, 'DBEXECUTE_ERROR');
      				}
      
      				$nextid = bcadd($res['nextid'], 1, 0);
      			}
      		}
      		else {
      			$nextid = self::refreshIds($table, $count);
      		}
      
      		return $nextid;
      	}
      
      ...
      private static function refreshIds($table, $count) {
      		$tableSchema = self::getSchema($table);
      		$id_name = $tableSchema['key'];
      
      		// when we reach the maximum ID, we try to refresh them to check if any IDs have been freed
      		$sql = 'DELETE FROM ids WHERE table_name='.zbx_dbstr($table).' AND field_name='.zbx_dbstr($id_name);
      
      		if (!DBexecute($sql)) {
      			self::exception(self::DBEXECUTE_ERROR, 'DBEXECUTE_ERROR');
      		}
      
      		$row = DBfetch(DBselect('SELECT MAX('.$id_name.') AS id FROM '.$table));
      
      		$nextid = ($row && $row['id']) ? $row['id'] : 0;
      
      		$maxNextId = bcadd($nextid, $count, 0);
      
      		if (bccomp($maxNextId, ZBX_DB_MAX_ID) == 1) {
      			self::exception(
      				self::RESERVEIDS_ERROR, __METHOD__.' ID greater than maximum allowed for table "'.$table.'"'
      			);
      		}
      
      		$sql = 'INSERT INTO ids (table_name,field_name,nextid)'.
      				' VALUES ('.zbx_dbstr($table).','.zbx_dbstr($id_name).','.$maxNextId.')';
      
      		if (!DBexecute($sql)) {
      			self::exception(self::DBEXECUTE_ERROR, 'DBEXECUTE_ERROR');
      		}
      
      		$nextid = bcadd($nextid, 1, 0);
      
      		return $nextid;
      	}
      

      Question is - why we don't return more details to distinguish those 3 different cases, including failed SQL ?

      It would help to troubleshoot unclear problems.

      For example we have code like this:

      $sql = 'INSERT INTO '.$table.' ('.implode(',', array_keys($row)).')'.
      					' VALUES ('.implode(',', array_values($row)).')';
      
      			if (!DBexecute($sql)) {
      				self::exception(self::DBEXECUTE_ERROR, _s('SQL statement execution has failed "%1$s".', $sql));
      			}
      

      Why would not reuse it for those 3 cases too ?

            Unassigned Unassigned
            zalex_ua Oleksii Zagorskyi
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: