Special care must be taken for Cacti to properly support multiple DBMS's.
When writing queries do not use quotes around numeric values. While MySQL is not strict about types, most DBMS's assume that any value contained within quotes is a string.
As well, single quotes are used unless a variable is referenced
$graphs = db_fetch_assoc('SELECT * FROM graph WHERE height >= 150');
$rows = db_fetch_cell("SELECT count(*) FROM $archive_table");
Do not use functions in SQL queries that are provided only by a
single DBMS. These functions are generally not uniformly support or even
available in all DBMS's. Common examples of such functions are
MD5()
, CONCAT()
, and NOW()
.
Cacti provides support for prepared statements. You should use these prepared statement functions as much as possible to avoid the risk of SQL Injection attacks from the Cacti website. Examples include:
// Example prepared statements
$hostname = db_fetch_cell_prepared('SELECT hostname FROM host WHERE id = ?', array($id));
$host = db_fetch_row_prepared('SELECT * FROM host WHERE id = ?', array($id));
$graphs = db_fetch_assoc('SELECT * FROM graph_local WHERE host_id = ?', array($id));
'UPDATE host SET description = ? WHERE id = ?', array('Local Machines', $id));
db_execute_prepared(
// Escape strings if using legacy functions
$hostname = db_qstr('myhost.com');
UPDATE host SET hostname = '$myhost' WHERE id = $id"); db_execute(
For short statements, SQL calls may be made on a single row.
If the SQL statement starts to grow and be unreadable without scrolling, it should be wrapped onto a continuation line for ease of use and readability. The following keywords should also be placed at the start of a new line:
joins statements (excluding JOIN itself which should not be used) (eg, INNER JOIN, LEFT JOIN, RIGHT JOIN, OUTER JOIN, CROSS JOIN)
Note: *Any implicit join or JOIN without one of the modifiers should be converted to an explicit join with a modifier. When converting the implicit join statement, remember to remove the WHERE joining clause.
AND / OR
FROM
WHERE
ORDER
GROUP BY
HAVING
LIMIT
prepared statement arrays
Indentation should consist of one extra tab when any of the following occur:
continuation lines
Subqueries
There should always be 'AS' when defining an alias for any table, field or query to clearly define the definition of said alias.
There should always be a space following a comma and before/after an operator.
$templates = db_fetch_assoc('SELECT DISTINCT gt.id, gt.name FROM graph_templates AS gt INNER JOIN graph_templates_graph AS gtg ON gt.id = gtg.graph_template_id INNER JOIN graph_templates_item AS gti ON gtg.graph_template_id=gti.graph_template_id INNER JOIN data_template_rrd AS dtr ON gti.task_item_id=dtr.id INNER JOIN data_template_data AS dtd ON dtd.data_template_id=dtr.data_template_id AND dtd.local_data_id = 0 WHERE gtg.local_graph_id=0 AND dtr.local_data_id = 0 AND dtd.local_data_id = 0 AND dtd.data_input_id in (2,11,12) ORDER BY gt.name;'
$templates = db_fetch_assoc_prepared('SELECT DISTINCT gt.id, gt.name
FROM graph_templates AS gt
INNER JOIN graph_templates_graph AS gtg
ON gt.id = gtg.graph_template_id
INNER JOIN graph_templates_item AS gti
ON gtg.graph_template_id=gti.graph_template_id
INNER JOIN data_template_rrd AS dtr
ON gti.task_item_id=dtr.id
INNER JOIN data_template_data AS dtd
ON dtd.data_template_id=dtr.data_template_id
AND dtd.local_data_id = 0
WHERE gtg.local_graph_id=0
AND dtr.local_data_id = 0
AND dtd.local_data_id = 0
AND dtd.data_input_id in (?,?,?)
ORDER BY gt.name',
array(2,11,12));
$user_realms = db_fetch_assoc('SELECT ua.id, uar.realm_id
FROM user_auth ua, user_auth_realms uar
WHERE ua.id = uar.user_id');
$user_realms = db_fetch_assoc('SELECT ua.id, uar.realm_id
FROM user_auth ua
INNER JOIN user_auth_realms uar
ON ua.id = uar.user_id');