mirror of
https://github.com/Cacti/documentation.git
synced 2026-10-23 03:26:44 +09:00
* docs: comprehensive audit, Spine poller overhaul, and technical refactor - Overhaul Spine documentation (Spine.md) with complete end-to-end guide: architecture, prerequisites for modern distros (EL8/9 CRB, Ubuntu 22/24, Debian 11/12, FreeBSD), SUID root permissions, secure spine.conf setup (0640), Web UI configuration (Paths, Poller type, Data Collectors tuning), MySQL max_connections sizing, and troubleshooting. - Fix broken links and anchors (Hardening, SNMP data queries, Hook API references). - Fix broken image reference in Sites.md (add-site.JPG -> add-site.png). - Fix syntax errors in documentation PHP code blocks, including invalid parenthesization, missing SQL execute quotes, and malformed comments in FAQ. - Fix DevOps installation commands: use config.php.dist, correct systemctl service names for MySQL/MariaDB/PHP-FPM, remove nonexistent php-json, add missing composer install, and correct Debian/Ubuntu systemd environment path. - Correct grammatical errors, repeated words, and typos across all markdown documents. - Remove obsolete unreferenced duplicate installation guides. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: correct reviewed examples and guidance Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: correct guidance that disagrees with the Cacti source Verified each claim against include/global_arrays.php, lib/auth.php, lib/functions.php, host_templates.php and the Spine config parser. The notable ones: api_plugin_safe_exec() does not exist on either branch, Spine reads DB_Pass rather than DB_Password, and the CDEF special data source table was missing five entries and renamed four others. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * docs: wrap Spine prose and fence the connection sizing formula The formula's bare asterisks rendered as emphasis, dropping the multiplication signs. Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> * chore: refresh copyright year in scripts and issue templates Signed-off-by: Thomas Vincent <thomasvincent@gmail.com> --------- Signed-off-by: Thomas Vincent <thomasvincent@gmail.com>
142 lines
4.4 KiB
Markdown
142 lines
4.4 KiB
Markdown
# SQL Standards
|
|
|
|
Special care must be taken for Cacti to properly support multiple DBMS's.
|
|
|
|
## Quotes
|
|
|
|
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
|
|
|
|
```php
|
|
$graphs = db_fetch_assoc('SELECT * FROM graph WHERE height >= 150');
|
|
```
|
|
|
|
```php
|
|
$rows = db_fetch_cell("SELECT count(*) FROM $archive_table");
|
|
```
|
|
|
|
## DBMS Functions
|
|
|
|
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()`.
|
|
|
|
## SQL Injection
|
|
|
|
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:
|
|
|
|
```php
|
|
// 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_prepared('SELECT * FROM graph_local WHERE host_id = ?', array($id));
|
|
|
|
db_execute_prepared('UPDATE host SET description = ? WHERE id = ?', array('Local Machines', $id));
|
|
|
|
// Escape strings if using legacy functions. db_qstr() returns the value
|
|
// already wrapped in quotes, so do not quote it again.
|
|
$hostname = db_qstr('myhost.com');
|
|
db_execute("UPDATE host SET hostname = $hostname WHERE id = " . (int) $id);
|
|
|
|
```
|
|
|
|
## Format of SQL statements
|
|
|
|
- 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.
|
|
|
|
### Example of single line SQL
|
|
|
|
#### Before formatting
|
|
|
|
```php
|
|
$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;');
|
|
```
|
|
|
|
#### Corrected formatting with prepared usage
|
|
|
|
```php
|
|
$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));
|
|
```
|
|
|
|
### Example of implicit join
|
|
|
|
#### Before formatting
|
|
|
|
```php
|
|
$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');
|
|
```
|
|
|
|
#### Corrected formatting
|
|
|
|
```php
|
|
$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');
|
|
```
|
|
|
|
---
|
|
|
|
Copyright (c) 2004-2026 The Cacti Group
|