Use PDO for MySQL queries (#8935)

Gut dbFacile
mres() now does nothing... could have some vulnerable queries, but most are ok

TODO
- [x] IRC client broke
- [x] Install broke

DO NOT DELETE THIS TEXT

#### Please note

> Please read this information carefully. You can run `./scripts/pre-commit.php` to check your code before submitting.

- [x] Have you followed our [code guidelines?](http://docs.librenms.org/Developing/Code-Guidelines/)

#### Testers

If you would like to test this pull request then please run: `./scripts/github-apply <pr_id>`, i.e `./scripts/github-apply 5926`
This commit is contained in:
Tony Murray 2018-08-17 15:29:20 -05:00 committed by Neil Lathwood
parent 86c097574b
commit a2e33efba8
29 changed files with 354 additions and 486 deletions

View File

@ -26,33 +26,92 @@
namespace LibreNMS\DB; namespace LibreNMS\DB;
use Illuminate\Database\Capsule\Manager as Capsule; use Illuminate\Database\Capsule\Manager as Capsule;
use Illuminate\Database\Events\StatementPrepared;
use Illuminate\Events\Dispatcher; use Illuminate\Events\Dispatcher;
class Eloquent class Eloquent
{ {
/** @var Capsule static reference to capsule */ /** @var Capsule static reference to capsule */
private static $capsule; private static $capsule;
private static $legacy_listener_installed = false;
public static function boot() public static function boot($options = [])
{ {
// boot Eloquent outside of Laravel // boot Eloquent outside of Laravel
if (!defined('LARAVEL_START') && class_exists(Capsule::class)) { if (!defined('LARAVEL_START') && class_exists(Capsule::class) && is_null(self::$capsule)) {
$install_dir = realpath(__DIR__ . '/../../'); $install_dir = realpath(__DIR__ . '/../../');
self::$capsule = new Capsule;
$db_config = include($install_dir . '/config/database.php'); $db_config = include($install_dir . '/config/database.php');
self::$capsule->addConnection($db_config['connections'][$db_config['default']]); $settings = $db_config['connections'][$db_config['default']];
// legacy connection override
if (!empty($options)) {
$fields = [
'host' => 'db_host',
'port' => 'db_port',
'database' => 'db_name',
'username' => 'db_user',
'password' => 'db_pass',
'unix_socket' => 'db_socket',
];
foreach ($fields as $new => $old) {
if (isset($options[$old])) {
$settings[$new] = $options[$old];
}
}
}
self::$capsule = new Capsule;
self::$capsule->addConnection($settings);
self::$capsule->setEventDispatcher(new Dispatcher()); self::$capsule->setEventDispatcher(new Dispatcher());
self::$capsule->setAsGlobal(); self::$capsule->setAsGlobal();
self::$capsule->bootEloquent(); self::$capsule->bootEloquent();
} }
self::initLegacyListeners();
self::setStrictMode(false); // set non-strict mode if for legacy code
}
public static function initLegacyListeners()
{
if (self::isConnected() && !self::$legacy_listener_installed) {
// set FETCH_ASSOC for queries that required by setting the global variable $PDO_FETCH_ASSOC (for dbFacile)
self::DB()->getEventDispatcher()->listen(StatementPrepared::class, function ($event) {
global $PDO_FETCH_ASSOC;
if ($PDO_FETCH_ASSOC) {
$event->statement->setFetchMode(\PDO::FETCH_ASSOC);
}
});
self::$legacy_listener_installed = true;
}
}
/**
* Set the strict mode for the current connection (will not persist)
* @param bool $strict
*/
public static function setStrictMode($strict = true)
{
if (self::isConnected()) {
if ($strict) {
self::DB()->getPdo()->exec("SET sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'");
} else {
self::DB()->getPdo()->exec("SET sql_mode=''");
}
}
} }
public static function isConnected() public static function isConnected()
{ {
$conn = self::DB(); try {
if ($conn) { $conn = self::DB();
return (bool)$conn->getDatabaseName(); if ($conn) {
$conn->getPdo();
return true;
}
} catch (\PDOException $e) {
return false;
} }
return false; return false;
@ -66,7 +125,7 @@ class Eloquent
public static function DB() public static function DB()
{ {
// check if Laravel is booted // check if Laravel is booted
if (class_exists('DB')) { if (defined('LARAVEL_START') && class_exists('DB')) {
return \DB::connection(); return \DB::connection();
} }

View File

@ -21,7 +21,7 @@
namespace LibreNMS; namespace LibreNMS;
use LibreNMS\Authentication\Auth; use LibreNMS\Authentication\Auth;
use LibreNMS\Exceptions\DatabaseConnectException; use LibreNMS\DB\Eloquent;
class IRCBot class IRCBot
{ {
@ -68,11 +68,8 @@ class IRCBot
public function __construct() public function __construct()
{ {
global $config, $database_link; global $config;
$this->log('Setting up IRC-Bot..'); $this->log('Setting up IRC-Bot..');
if (is_resource($database_link)) {
$this->sql = $database_link;
}
$this->config = $config; $this->config = $config;
$this->debug = $this->config['irc_debug']; $this->debug = $this->config['irc_debug'];
@ -507,10 +504,10 @@ class IRCBot
private function chkdb() private function chkdb()
{ {
if (!is_resource($this->sql)) { if (!Eloquent::isConnected()) {
try { try {
$this->sql = dbConnect(); Eloquent::boot();
} catch (DatabaseConnectException $e) { } catch (\PDOException $e) {
$this->log('Cannot connect to MySQL: ' . $e->getMessage()); $this->log('Cannot connect to MySQL: ' . $e->getMessage());
return die(); return die();
} }

View File

@ -63,13 +63,6 @@ class Database extends BaseValidation
private function checkMode(Validator $validator) private function checkMode(Validator $validator)
{ {
// Test for MySQL Strict mode
$strict_mode = dbFetchCell("SELECT @@global.sql_mode");
if (str_contains($strict_mode, 'STRICT_TRANS_TABLES')) {
//FIXME - Come back to this once other MySQL modes are fixed
//$valid->fail('You have MySQL STRICT_TRANS_TABLES enabled, please disable this until full support has been added: https://dev.mysql.com/doc/refman/5.0/en/sql-mode.html');
}
// Test for lower case table name support // Test for lower case table name support
$lc_mode = dbFetchCell("SELECT @@global.lower_case_table_names"); $lc_mode = dbFetchCell("SELECT @@global.lower_case_table_names");
if ($lc_mode != 0) { if ($lc_mode != 0) {
@ -78,13 +71,6 @@ class Database extends BaseValidation
'Set lower_case_table_names=0 in your mysql config file in the [mysqld] section.' 'Set lower_case_table_names=0 in your mysql config file in the [mysqld] section.'
); );
} }
if (empty($strict_mode) === false) {
$validator->fail(
"You have not set sql_mode='' in your mysql config.",
"Set sql-mode='' in your mysql config file in the [mysqld] section."
);
}
} }
private function checkCollation(Validator $validator) private function checkCollation(Validator $validator)

View File

@ -20,19 +20,8 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function boot() public function boot()
{ {
// connect legacy db, only if configured // Install legacy dbFacile fetch mode listener
//FIXME this is for auth right now, remove later \LibreNMS\DB\Eloquent::initLegacyListeners();
$db_config = config('database.connections')[config('database.default')];
if (!empty($db_config['database'])) {
dbConnect(
$db_config['host'],
$db_config['username'],
$db_config['password'],
$db_config['database'],
$db_config['port'],
$db_config['unix_socket']
);
}
// load config // load config
Config::load(); Config::load();

View File

@ -41,6 +41,11 @@ $app->singleton(
App\Exceptions\Handler::class App\Exceptions\Handler::class
); );
$app->configureMonologUsing(function (Monolog\Logger $logger) use ($app) {
$path = $app->basePath(config('app.log'));
$logger->pushHandler(new \Monolog\Handler\StreamHandler($path));
});
/* /*
|-------------------------------------------------------------------------- |--------------------------------------------------------------------------
| Return The Application | Return The Application

View File

@ -24,34 +24,27 @@
* @author Tony Murray <murraytony@gmail.com> * @author Tony Murray <murraytony@gmail.com>
*/ */
use LibreNMS\Exceptions\DatabaseConnectException;
if (!isset($init_modules)) { if (!isset($init_modules)) {
$init_modules = array('nodb'); $init_modules = array('nodb');
require __DIR__ . '/includes/init.php'; require __DIR__ . '/includes/init.php';
$opts = getopt('ldh:u:p:n:t:s:'); $opts = getopt('ldh:u:p:n:t:s:');
try { if (isset($opts['h'])) {
if (isset($opts['h'])) { dbConnect(
dbConnect( isset($opts['h']) ? $opts['h'] : null,
isset($opts['h']) ? $opts['h'] : null, isset($opts['u']) ? $opts['u'] : '',
isset($opts['u']) ? $opts['u'] : '', isset($opts['p']) ? $opts['p'] : '',
isset($opts['p']) ? $opts['p'] : '', isset($opts['n']) ? $opts['n'] : '',
isset($opts['n']) ? $opts['n'] : '', isset($opts['t']) ? $opts['t'] : null,
isset($opts['t']) ? $opts['t'] : null, isset($opts['s']) ? $opts['s'] : null
isset($opts['s']) ? $opts['s'] : null );
); } else {
} else { // use configured database credentials
// use configured database credentials \LibreNMS\DB\Eloquent::boot();
dbConnect();
}
} catch (DatabaseConnectException $e) {
echo $e->getMessage() . PHP_EOL;
exit;
} }
$debug = isset($opts['d']); set_debug(isset($opts['d']));
$skip_schema_lock = isset($opts['l']); $skip_schema_lock = isset($opts['l']);
} }

View File

@ -120,7 +120,7 @@ return [
| |
*/ */
'log' => env('APP_LOG', 'errorlog'), // use error log until we are booted 'log' => env('APP_LOG', 'logs/librenms.log'), // log to the default file, until boot
'log_level' => env('APP_LOG_LEVEL', 'debug'), 'log_level' => env('APP_LOG_LEVEL', 'debug'),

View File

@ -39,13 +39,10 @@ exit
vi /etc/my.cnf vi /etc/my.cnf
> NOTE: Whilst we are working on ensuring LibreNMS is compatible with MySQL strict mode, for now, please disable this after mysql is installed.
Within the `[mysqld]` section please add: Within the `[mysqld]` section please add:
```bash ```bash
innodb_file_per_table=1 innodb_file_per_table=1
sql-mode=""
lower_case_table_names=0 lower_case_table_names=0
``` ```
systemctl enable mariadb systemctl enable mariadb

View File

@ -39,13 +39,10 @@ exit
vi /etc/my.cnf vi /etc/my.cnf
> NOTE: Whilst we are working on ensuring LibreNMS is compatible with MySQL strict mode, for now, please disable this after mysql is installed.
Within the `[mysqld]` section please add: Within the `[mysqld]` section please add:
```bash ```bash
innodb_file_per_table=1 innodb_file_per_table=1
sql-mode=""
lower_case_table_names=0 lower_case_table_names=0
``` ```
systemctl enable mariadb systemctl enable mariadb

View File

@ -36,13 +36,10 @@ exit
vi /etc/mysql/mariadb.conf.d/50-server.cnf vi /etc/mysql/mariadb.conf.d/50-server.cnf
> NOTE: Whilst we are working on ensuring LibreNMS is compatible with MySQL strict mode, for now, please disable this after mysql is installed.
Within the `[mysqld]` section please add: Within the `[mysqld]` section please add:
```bash ```bash
innodb_file_per_table=1 innodb_file_per_table=1
sql-mode=""
lower_case_table_names=0 lower_case_table_names=0
``` ```
systemctl restart mysql systemctl restart mysql

View File

@ -35,13 +35,10 @@ exit
vim /etc/mysql/mariadb.conf.d/50-server.cnf vim /etc/mysql/mariadb.conf.d/50-server.cnf
> NOTE: Whilst we are working on ensuring LibreNMS is compatible with MySQL strict mode, for now, please disable this after mysql is installed.
Within the `[mysqld]` section please add: Within the `[mysqld]` section please add:
```bash ```bash
innodb_file_per_table=1 innodb_file_per_table=1
sql-mode=""
lower_case_table_names=0 lower_case_table_names=0
``` ```
systemctl restart mysql systemctl restart mysql

View File

@ -24,9 +24,6 @@ if (file_exists('../config.php') && $stage != 6) {
// do not use the DB in init, we'll bring it up ourselves // do not use the DB in init, we'll bring it up ourselves
$init_modules = array('web', 'nodb'); $init_modules = array('web', 'nodb');
if ($stage > 3) {
$init_modules[] = 'auth';
}
require realpath(__DIR__ . '/..') . '/includes/init.php'; require realpath(__DIR__ . '/..') . '/includes/init.php';
// List of php modules we expect to see // List of php modules we expect to see

View File

@ -28,7 +28,7 @@ $msg_box = array();
// Check for install.inc.php // Check for install.inc.php
if (!file_exists('../config.php') && $_SERVER['PATH_INFO'] != '/install.php') { if (!file_exists('../config.php') && $_SERVER['PATH_INFO'] != '/install.php') {
// no config.php does so let's redirect to the install // no config.php does so let's redirect to the install
header("Location: {$config['base_url']}/install.php"); header("Location: " . rtrim(Config::get('base_url'), '/') . "/install.php");
exit; exit;
} }

View File

@ -404,6 +404,7 @@ function truncate($substring, $max = 50, $rep = '...')
function mres($string) function mres($string)
{ {
return $string; // FIXME bleh
// short function wrapper because the real one is stupidly long and ugly. aesthetics. // short function wrapper because the real one is stupidly long and ugly. aesthetics.
global $database_link; global $database_link;
return mysqli_real_escape_string($database_link, $string); return mysqli_real_escape_string($database_link, $string);

View File

@ -17,17 +17,14 @@
* 3. Oh, and dbFetchAll() is now dbFetchRows() * 3. Oh, and dbFetchAll() is now dbFetchRows()
*/ */
use Illuminate\Database\QueryException;
use LibreNMS\Config; use LibreNMS\Config;
use LibreNMS\Exceptions\DatabaseConnectException; use LibreNMS\Exceptions\DatabaseConnectException;
use LibreNMS\DB\Eloquent;
function dbIsConnected() function dbIsConnected()
{ {
global $database_link; return Eloquent::isConnected();
if (empty($database_link)) {
return false;
}
return mysqli_ping($database_link);
} }
/** /**
@ -40,169 +37,93 @@ function dbIsConnected()
* @param string $db_name * @param string $db_name
* @param string $db_port * @param string $db_port
* @param string $db_socket * @param string $db_socket
* @return mysqli * @return \Illuminate\Database\Connection
* @throws DatabaseConnectException * @throws DatabaseConnectException
*/ */
function dbConnect($db_host = null, $db_user = '', $db_pass = '', $db_name = '', $db_port = null, $db_socket = null) function dbConnect($db_host = null, $db_user = '', $db_pass = '', $db_name = '', $db_port = null, $db_socket = null)
{ {
global $database_link; if (Eloquent::isConnected()) {
return Eloquent::DB();
if (dbIsConnected()) {
return $database_link;
} }
if (!function_exists('mysqli_connect')) { if (!function_exists('mysqli_connect')) {
throw new DatabaseConnectException("mysqli extension not loaded!"); throw new DatabaseConnectException("mysqli extension not loaded!");
} }
if (is_null($db_host)) { try {
$db_config = Config::getDatabaseSettings(); if (is_null($db_host) && empty($db_name)) {
extract($db_config); Eloquent::boot();
/** @var string $db_host */ } else {
/** @var string $db_port */ Eloquent::boot(get_defined_vars());
/** @var string $db_socket */
/** @var string $db_name */
/** @var string $db_user */
/** @var string $db_pass */
}
if (empty($db_socket)) {
$db_socket = null;
}
if (!is_numeric($db_port)) {
$db_port = null;
}
if (!$db_host && !$db_socket) {
throw new DatabaseConnectException("Database configuration not configured");
}
$database_link = @mysqli_connect('p:' . $db_host, $db_user, $db_pass, null, $db_port, $db_socket);
if ($database_link === false) {
$error = mysqli_connect_error();
if ($error == 'No such file or directory') {
$error = 'Could not connect to ' . $db_host;
} }
throw new DatabaseConnectException($error); } catch (PDOException $e) {
throw new DatabaseConnectException($e->getMessage(), $e->getCode(), $e);
} }
mysqli_options($database_link, MYSQLI_OPT_LOCAL_INFILE, false); return Eloquent::DB();
$database_db = mysqli_select_db($database_link, $db_name);
if (!$database_db) {
$db_create_sql = "CREATE DATABASE $db_name CHARACTER SET utf8 COLLATE utf8_unicode_ci";
mysqli_query($database_link, $db_create_sql);
$database_db = mysqli_select_db($database_link, $db_name);
}
if (!$database_db) {
throw new DatabaseConnectException("Could not select database: $db_name. " . mysqli_error($database_link));
}
dbQuery("SET NAMES 'utf8'");
dbQuery("SET CHARACTER SET 'utf8'");
dbQuery("SET COLLATION_CONNECTION = 'utf8_unicode_ci'");
return $database_link;
} }
/* /**
* Performs a query using the given string. * Performs a query using the given string.
* Used by the other _query functions. * @param string $sql
* */ * @param array $parameters
* @return bool if query was successful or not
*/
function dbQuery($sql, $parameters = array()) function dbQuery($sql, $parameters = [])
{ {
global $fullSql, $debug, $database_link, $config; try {
$fullSql = dbMakeQuery($sql, $parameters); if (empty($parameters)) {
if ($debug) { // don't use prepared statements for queries without parameters
$fullSql = str_replace(PHP_EOL, '', $fullSql); return Eloquent::DB()->getPdo()->exec($sql) !== false;
// hide binary field updates and inserts
$fullSql = preg_replace("/(.*alert_log.*details[` ]*= *')[^']*('.*)/i", '$1<binary data>$2', $fullSql);
if (class_exists('Log')) {
Log::info("SQL[%y$fullSql%n]", ['color' => true]);
} else {
c_echo("SQL[%y$fullSql%n] \n");
} }
return Eloquent::DB()->statement($sql, $parameters);
} catch (PDOException $pdoe) {
dbHandleException(new QueryException($sql, $parameters, $pdoe));
return false;
} }
}
$result = mysqli_query($database_link, $fullSql);
if (!$result) {
$mysql_error = mysqli_error($database_link);
if (isset($config['mysql_log_level']) && ((in_array($config['mysql_log_level'], array('INFO', 'ERROR')) && !preg_match('/Duplicate entry/', $mysql_error)) || in_array($config['mysql_log_level'], array('DEBUG')))) {
if (!empty($mysql_error)) {
$error_msg = "MySQL Error: $mysql_error ($fullSql)";
c_echo("%R$error_msg%n\n", isCli() || $debug);
logfile(date($config['dateformat']['compact']) . ' ' . $error_msg);
}
}
}
return $result;
}//end dbQuery()
/*
* Passed an array and a table name, it attempts to insert the data into the table.
* Check for boolean false to determine whether insert failed
* */
/**
* @param array $data
* @param string $table
* @return null|int
*/
function dbInsert($data, $table) function dbInsert($data, $table)
{ {
global $database_link;
$time_start = microtime(true); $time_start = microtime(true);
// the following block swaps the parameters if they were given in the wrong order. $sql = 'INSERT IGNORE INTO `'.$table.'` (`'.implode('`,`', array_keys($data)).'`) VALUES ('.implode(',', dbPlaceHolders($data)).')';
// it allows the method to work for those that would rather it (or expect it to)
// follow closer with SQL convention:
// insert into the TABLE this DATA
if (is_string($data) && is_array($table)) {
$tmp = $data;
$data = $table;
$table = $tmp;
// trigger_error('QDB - Parameters passed to insert() were in reverse order, but it has been allowed', E_USER_NOTICE);
}
$sql = 'INSERT INTO `'.$table.'` (`'.implode('`,`', array_keys($data)).'`) VALUES ('.implode(',', dbPlaceHolders($data)).')'; try {
$result = Eloquent::DB()->insert($sql, $data);
dbBeginTransaction(); } catch (PDOException $pdoe) {
$result = dbQuery($sql, $data); dbHandleException(new QueryException($sql, $data, $pdoe));
if ($result) {
$id = mysqli_insert_id($database_link);
dbCommitTransaction();
// return $id;
} else {
dbRollbackTransaction();
$id = null;
} }
recordDbStatistic('insert', $time_start); recordDbStatistic('insert', $time_start);
return $id; if ($result) {
return Eloquent::DB()->getPdo()->lastInsertId();
} else {
return null;
}
}//end dbInsert() }//end dbInsert()
/* /**
* Passed an array and a table name, it attempts to insert the data into the table. * Passed an array and a table name, it attempts to insert the data into the table.
* $data is an array (rows) of key value pairs. keys are fields. Rows need to have same fields. * $data is an array (rows) of key value pairs. keys are fields. Rows need to have same fields.
* Check for boolean false to determine whether insert failed * Check for boolean false to determine whether insert failed
* */ *
* @param array $data
* @param string $table
* @return bool
*/
function dbBulkInsert($data, $table) function dbBulkInsert($data, $table)
{ {
$time_start = microtime(true); $time_start = microtime(true);
// the following block swaps the parameters if they were given in the wrong order.
// it allows the method to work for those that would rather it (or expect it to)
// follow closer with SQL convention:
// insert into the TABLE this DATA
if (is_string($data) && is_array($table)) {
$tmp = $data;
$data = $table;
$table = $tmp;
}
// check that data isn't an empty array // check that data isn't an empty array
if (empty($data)) { if (empty($data)) {
return false; return false;
@ -213,63 +134,52 @@ function dbBulkInsert($data, $table)
return false; return false;
} }
$sql = 'INSERT INTO `'.$table.'` (`'.implode('`,`', $fields).'`) VALUES '; try {
$values =''; // $result = Eloquent::DB()->insert($sql.$values);
$result = Eloquent::DB()->table($table)->insert($data);
foreach ($data as $row) { recordDbStatistic('insert', $time_start);
if ($values != '') { return $result;
$values .= ','; } catch (PDOException $pdoe) {
} // FIXME query?
$rowvalues=''; dbHandleException(new QueryException("Bulk insert $table", $data, $pdoe));
foreach ($row as $key => $value) {
if ($rowvalues != '') {
$rowvalues .= ',';
}
if (is_null($value)) {
$rowvalues .= 'NULL';
} else {
$rowvalues .= "'" . mres($value) . "'";
}
}
$values .= "(".$rowvalues.")";
} }
$result = dbQuery($sql.$values); return false;
recordDbStatistic('insert', $time_start);
return $result;
}//end dbBulkInsert() }//end dbBulkInsert()
/* /**
* Passed an array, table name, WHERE clause, and placeholder parameters, it attempts to update a record. * Passed an array, table name, WHERE clause, and placeholder parameters, it attempts to update a record.
* Returns the number of affected rows * Returns the number of affected rows
* */ *
* @param array $data
* @param string $table
function dbUpdate($data, $table, $where = null, $parameters = array()) * @param string $where
* @param array $parameters
* @return bool|int
*/
function dbUpdate($data, $table, $where = null, $parameters = [])
{ {
global $fullSql, $database_link;
$time_start = microtime(true); $time_start = microtime(true);
// the following block swaps the parameters if they were given in the wrong order.
// it allows the method to work for those that would rather it (or expect it to)
// follow closer with SQL convention:
// update the TABLE with this DATA
if (is_string($data) && is_array($table)) {
$tmp = $data;
$data = $table;
$table = $tmp;
// trigger_error('QDB - The first two parameters passed to update() were in reverse order, but it has been allowed', E_USER_NOTICE);
}
// need field name and placeholder value // need field name and placeholder value
// but how merge these field placeholders with actual $parameters array for the WHERE clause // but how merge these field placeholders with actual $parameters array for the WHERE clause
$sql = 'UPDATE `'.$table.'` set '; $sql = 'UPDATE `'.$table.'` set ';
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
$sql .= '`'.$key.'` '.'=:'.$key.','; $sql .= '`'.$key.'`=';
if (is_array($value)) {
$sql .= reset($value);
unset($data[$key]);
} else {
$sql .= '?';
}
$sql .= ',';
} }
// strip keys
$data = array_values($data);
$sql = substr($sql, 0, -1); $sql = substr($sql, 0, -1);
// strip off last comma // strip off last comma
if ($where) { if ($where) {
@ -277,22 +187,21 @@ function dbUpdate($data, $table, $where = null, $parameters = array())
$data = array_merge($data, $parameters); $data = array_merge($data, $parameters);
} }
if (dbQuery($sql, $data)) { try {
$return = mysqli_affected_rows($database_link); $result = Eloquent::DB()->update($sql, $data);
} else {
// echo("$fullSql"); recordDbStatistic('update', $time_start);
//trigger_error('QDB - Update failed.', E_USER_WARNING); return $result;
$return = false; } catch (PDOException $pdoe) {
dbHandleException(new QueryException($sql, $data, $pdoe));
} }
recordDbStatistic('update', $time_start); return false;
return $return;
}//end dbUpdate() }//end dbUpdate()
function dbDelete($table, $where = null, $parameters = array()) function dbDelete($table, $where = null, $parameters = array())
{ {
global $database_link;
$time_start = microtime(true); $time_start = microtime(true);
$sql = 'DELETE FROM `'.$table.'`'; $sql = 'DELETE FROM `'.$table.'`';
@ -300,14 +209,14 @@ function dbDelete($table, $where = null, $parameters = array())
$sql .= ' WHERE '.$where; $sql .= ' WHERE '.$where;
} }
$result = dbQuery($sql, $parameters); try {
$result = Eloquent::DB()->delete($sql, $parameters);
} catch (PDOException $pdoe) {
dbHandleException(new QueryException($sql, $parameters, $pdoe));
}
recordDbStatistic('delete', $time_start); recordDbStatistic('delete', $time_start);
if ($result) { return $result;
return mysqli_affected_rows($database_link);
} else {
return false;
}
}//end dbDelete() }//end dbDelete()
@ -321,7 +230,6 @@ function dbDelete($table, $where = null, $parameters = array())
*/ */
function dbDeleteOrphans($target_table, $parents) function dbDeleteOrphans($target_table, $parents)
{ {
global $database_link;
$time_start = microtime(true); $time_start = microtime(true);
if (empty($parents)) { if (empty($parents)) {
@ -350,14 +258,15 @@ function dbDeleteOrphans($target_table, $parents)
} }
$query = "$sql WHERE" . implode(' AND', $where); $query = "$sql WHERE" . implode(' AND', $where);
$result = dbQuery($query, array());
try {
$result = Eloquent::DB()->delete($query);
} catch (PDOException $pdoe) {
dbHandleException(new QueryException($query, [], $pdoe));
}
recordDbStatistic('delete', $time_start); recordDbStatistic('delete', $time_start);
if ($result) { return $result;
return mysqli_affected_rows($database_link);
} else {
return false;
}
} }
/* /*
@ -366,30 +275,23 @@ function dbDeleteOrphans($target_table, $parents)
* */ * */
function dbFetchRows($sql, $parameters = array()) function dbFetchRows($sql, $parameters = [])
{ {
global $PDO_FETCH_ASSOC;
$time_start = microtime(true); $time_start = microtime(true);
$result = dbQuery($sql, $parameters);
if ($result !== false) { try {
if (mysqli_num_rows($result) > 0) { $PDO_FETCH_ASSOC = true;
$rows = []; $rows = Eloquent::DB()->select($sql, $parameters);
while ($row = mysqli_fetch_assoc($result)) {
$rows[] = $row;
}
mysqli_free_result($result); recordDbStatistic('fetchrows', $time_start);
return $rows;
recordDbStatistic('fetchrows', $time_start); } catch (PDOException $pdoe) {
return $rows; dbHandleException(new QueryException($sql, $parameters, $pdoe));
} } finally {
$PDO_FETCH_ASSOC = false;
mysqli_free_result($result);
} }
// no records, thus return empty array
// which should evaluate to false, and will prevent foreach notices/warnings
recordDbStatistic('fetchrows', $time_start);
return []; return [];
}//end dbFetchRows() }//end dbFetchRows()
@ -400,7 +302,7 @@ function dbFetchRows($sql, $parameters = array())
* */ * */
function dbFetch($sql, $parameters = array()) function dbFetch($sql, $parameters = [])
{ {
return dbFetchRows($sql, $parameters); return dbFetchRows($sql, $parameters);
/* /*
@ -422,19 +324,24 @@ function dbFetch($sql, $parameters = array())
* */ * */
function dbFetchRow($sql = null, $parameters = array()) function dbFetchRow($sql = null, $parameters = [])
{ {
global $PDO_FETCH_ASSOC;
$time_start = microtime(true); $time_start = microtime(true);
$result = dbQuery($sql, $parameters);
if ($result) { try {
$row = mysqli_fetch_assoc($result); $PDO_FETCH_ASSOC = true;
mysqli_free_result($result); $row = Eloquent::DB()->selectOne($sql, $parameters);
recordDbStatistic('fetchrow', $time_start); recordDbStatistic('fetchrow', $time_start);
return $row; return $row;
} else { } catch (PDOException $pdoe) {
return null; dbHandleException(new QueryException($sql, $parameters, $pdoe));
} finally {
$PDO_FETCH_ASSOC = false;
} }
return [];
}//end dbFetchRow() }//end dbFetchRow()
@ -443,16 +350,25 @@ function dbFetchRow($sql = null, $parameters = array())
* */ * */
function dbFetchCell($sql, $parameters = array()) function dbFetchCell($sql, $parameters = [])
{ {
global $PDO_FETCH_ASSOC;
$time_start = microtime(true); $time_start = microtime(true);
$row = dbFetchRow($sql, $parameters);
recordDbStatistic('fetchcell', $time_start); try {
if ($row) { $PDO_FETCH_ASSOC = true;
return array_shift($row); $row = Eloquent::DB()->selectOne($sql, $parameters);
// shift first field off first row recordDbStatistic('fetchcell', $time_start);
if ($row) {
return reset($row);
// shift first field off first row
}
} catch (PDOException $pdoe) {
dbHandleException(new QueryException($sql, $parameters, $pdoe));
} finally {
$PDO_FETCH_ASSOC = false;
} }
return null; return null;
}//end dbFetchCell() }//end dbFetchCell()
@ -463,16 +379,29 @@ function dbFetchCell($sql, $parameters = array())
* */ * */
function dbFetchColumn($sql, $parameters = array()) function dbFetchColumn($sql, $parameters = [])
{ {
global $PDO_FETCH_ASSOC;
$time_start = microtime(true); $time_start = microtime(true);
$cells = array();
foreach (dbFetch($sql, $parameters) as $row) { $cells = [];
$cells[] = array_shift($row);
try {
$PDO_FETCH_ASSOC = true;
foreach (Eloquent::DB()->select($sql, $parameters) as $row) {
$cells[] = reset($row);
}
$PDO_FETCH_ASSOC = false;
recordDbStatistic('fetchcolumn', $time_start);
return $cells;
} catch (PDOException $pdoe) {
dbHandleException(new QueryException($sql, $parameters, $pdoe));
} finally {
$PDO_FETCH_ASSOC = false;
} }
recordDbStatistic('fetchcolumn', $time_start); return [];
return $cells;
}//end dbFetchColumn() }//end dbFetchColumn()
@ -502,91 +431,52 @@ function dbFetchKeyValue($sql, $parameters = array())
return $data; return $data;
}//end dbFetchKeyValue() }//end dbFetchKeyValue()
/**
/* * Legacy dbFacile indicates DB::raw() as a value wrapped in an array
* This combines a query and parameter array into a final query string for execution *
* PDO drivers don't need to use this * @param array $data
* @return array
*/ */
function dbArrayToRaw($data)
function dbMakeQuery($sql, $parameters)
{ {
// bypass extra logic if we have no parameters array_walk($data, function (&$item) {
if (sizeof($parameters) == 0) { if (is_array($item)) {
return $sql; $item = Eloquent::DB()->raw(reset($item));
}
});
return $data;
}
function dbHandleException(QueryException $exception)
{
$message = $exception->getMessage();
if ($exception->getCode() == 2002) {
$message = "Could not connect to database! " . $message;
} }
$parameters = dbPrepareData($parameters); // ? bindings should already be replaced, just replace named bindings
// separate the two types of parameters for easier handling foreach ($exception->getBindings() as $key => $value) {
$questionParams = array(); if (is_string($key)) {
$namedParams = array(); $message = str_replace(":$key", $value, $message);
foreach ($parameters as $key => $value) {
if (is_numeric($key)) {
$questionParams[] = $value;
} else {
$namedParams[':'.$key] = $value;
} }
} }
// sort namedParams in reverse to stop substring squashing foreach ($exception->getTrace() as $trace) {
krsort($namedParams); $message .= "\n " . $trace['file'] . ':' . $trace['line'];
}
// split on question-mark and named placeholders if (class_exists('Log')) {
if (preg_match('/(\[\[:[\w]+:\]\])/', $sql)) { Log::error($message);
$result = preg_split('/(\?[a-zA-Z0-9_-]*)/', $sql, -1, (PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE));
} else { } else {
$result = preg_split('/(\?|:[a-zA-Z0-9_-]+)/', $sql, -1, (PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE)); c_echo("%rSQL Error!%n ");
echo $message . PHP_EOL;
} }
// every-other item in $result will be the placeholder that was found // TODO remove this
$query = ''; // exit;
$res_size = sizeof($result); }
for ($i = 0; $i < $res_size; $i += 2) {
$query .= $result[$i];
$j = ($i + 1);
if (array_key_exists($j, $result)) {
$test = $result[$j];
if ($test == '?') {
$query .= array_shift($questionParams);
} else {
$query .= $namedParams[$test];
}
}
}
return $query;
}//end dbMakeQuery()
function dbPrepareData($data)
{
global $database_link;
$values = array();
foreach ($data as $key => $value) {
$escape = true;
// don't quote or esc if value is an array, we treat it
// as a "decorator" that tells us not to escape the
// value contained in the array
if (is_array($value) && !is_object($value)) {
$escape = false;
$value = array_shift($value);
}
// it's not right to worry about invalid fields in this method because we may be operating on fields
// that are aliases, or part of other tables through joins
// if(!in_array($key, $columns)) // skip invalid fields
// continue;
if ($escape) {
$values[$key] = "'".mysqli_real_escape_string($database_link, $value)."'";
} else {
$values[$key] = $value;
}
}
return $values;
}//end dbPrepareData()
/** /**
* Given a data array, this returns an array of placeholders * Given a data array, this returns an array of placeholders
@ -595,11 +485,15 @@ function dbPrepareData($data)
* @param array $values * @param array $values
* @return array * @return array
*/ */
function dbPlaceHolders($values) function dbPlaceHolders(&$values)
{ {
$data = array(); $data = array();
foreach ($values as $key => $value) { foreach ($values as $key => $value) {
if (is_numeric($key)) { if (is_array($value)) {
// array wrapped values are raw sql
$data[] = reset($value);
unset($values[$key]);
} elseif (is_numeric($key)) {
$data[] = '?'; $data[] = '?';
} else { } else {
$data[] = ':'.$key; $data[] = ':'.$key;
@ -612,22 +506,19 @@ function dbPlaceHolders($values)
function dbBeginTransaction() function dbBeginTransaction()
{ {
global $database_link; Eloquent::DB()->beginTransaction();
mysqli_query($database_link, 'begin');
}//end dbBeginTransaction() }//end dbBeginTransaction()
function dbCommitTransaction() function dbCommitTransaction()
{ {
global $database_link; Eloquent::DB()->commit();
mysqli_query($database_link, 'commit');
}//end dbCommitTransaction() }//end dbCommitTransaction()
function dbRollbackTransaction() function dbRollbackTransaction()
{ {
global $database_link; Eloquent::DB()->rollBack();
mysqli_query($database_link, 'rollback');
}//end dbRollbackTransaction() }//end dbRollbackTransaction()
/** /**

View File

@ -2494,7 +2494,14 @@ function get_schema_list()
*/ */
function get_db_schema() function get_db_schema()
{ {
return (int)@dbFetchCell('SELECT version FROM `dbSchema` ORDER BY version DESC LIMIT 1'); try {
return \LibreNMS\DB\Eloquent::DB()
->table('dbSchema')
->orderBy('version', 'DESC')
->value('version');
} catch (PDOException $e) {
return 0;
}
} }
/** /**

View File

@ -92,25 +92,6 @@ if (module_selected('alerts', $init_modules)) {
require_once $install_dir . '/includes/alerts.inc.php'; require_once $install_dir . '/includes/alerts.inc.php';
} }
// Display config.php errors instead of http 500
$display_bak = ini_get('display_errors');
ini_set('display_errors', 1);
if (!module_selected('nodb', $init_modules)) {
// Connect to database
try {
dbConnect();
} catch (\LibreNMS\Exceptions\DatabaseConnectException $e) {
if (isCli()) {
echo 'MySQL Error: ' . $e->getMessage() . PHP_EOL;
exit(2);
} else {
// punt to the Laravel error handler
throw $e;
}
}
}
if (module_selected('laravel', $init_modules)) { if (module_selected('laravel', $init_modules)) {
// make sure Laravel isn't already booted // make sure Laravel isn't already booted
if (!class_exists('App') || !App::isBooted()) { if (!class_exists('App') || !App::isBooted()) {
@ -118,10 +99,21 @@ if (module_selected('laravel', $init_modules)) {
$kernel = $app->make(Illuminate\Contracts\Console\Kernel::class); $kernel = $app->make(Illuminate\Contracts\Console\Kernel::class);
$kernel->bootstrap(); $kernel->bootstrap();
} }
} elseif (module_selected('eloquent', $init_modules)) {
\LibreNMS\DB\Eloquent::boot();
} }
if (!module_selected('nodb', $init_modules)) {
\LibreNMS\DB\Eloquent::boot();
if (!\LibreNMS\DB\Eloquent::isConnected()) {
echo "Could not connect to database, check logs/librenms.log.\n";
exit;
}
}
// Display config.php errors instead of http 500
$display_bak = ini_get('display_errors');
ini_set('display_errors', 1);
// Load config if not already loaded (which is the case if inside Laravel) // Load config if not already loaded (which is the case if inside Laravel)
if (!Config::has('install_dir')) { if (!Config::has('install_dir')) {
Config::load(); Config::load();

View File

@ -60,7 +60,7 @@ function post_notifications()
$notifs = get_notifications(); $notifs = get_notifications();
echo '[ '.date('r').' ] Updating DB '; echo '[ '.date('r').' ] Updating DB ';
foreach ($notifs as $notif) { foreach ($notifs as $notif) {
if (dbFetchCell('select 1 from notifications where checksum = ?', array($notif['checksum'])) != 1 && dbInsert('notifications', $notif) > 0) { if (dbFetchCell('select 1 from notifications where checksum = ?', array($notif['checksum'])) != 1 && dbInsert($notif, 'notifications') > 0) {
echo '.'; echo '.';
} }
} }
@ -134,7 +134,7 @@ function new_notification($title, $message, $severity = 0, $source = 'adhoc', $d
); );
if (dbFetchCell('SELECT 1 FROM `notifications` WHERE `checksum` = ?', array($notif['checksum'])) != 1) { if (dbFetchCell('SELECT 1 FROM `notifications` WHERE `checksum` = ?', array($notif['checksum'])) != 1) {
return dbInsert('notifications', $notif) > 0; return dbInsert($notif, 'notifications') > 0;
} }
return false; return false;

View File

@ -108,7 +108,7 @@ if ($device['os_group'] == 'unix') {
} }
} }
if (count($data) > 0) { if (count($data) > 0) {
dbBulkInsert('processes', $data); dbBulkInsert($data, 'processes');
} }
echo "\n"; echo "\n";
} }

View File

@ -18,18 +18,10 @@ use LibreNMS\Exceptions\LockException;
use LibreNMS\Util\FileLock; use LibreNMS\Util\FileLock;
use LibreNMS\Util\MemcacheLock; use LibreNMS\Util\MemcacheLock;
global $database_link;
if (!isset($init_modules) && php_sapi_name() == 'cli') { if (!isset($init_modules) && php_sapi_name() == 'cli') {
// Not called from within discovery, let's load up the necessary stuff. // Not called from within discovery, let's load up the necessary stuff.
$init_modules = array('nodb'); $init_modules = [];
require realpath(__DIR__ . '/../..') . '/includes/init.php'; require realpath(__DIR__ . '/../..') . '/includes/init.php';
try {
dbConnect();
} catch (DatabaseConnectException $e) {
echo $e->getMessage() . PHP_EOL;
exit;
}
} }
$return = 0; $return = 0;
@ -60,9 +52,7 @@ try {
echo 'Step #' . $step++ . ' ...' . PHP_EOL; echo 'Step #' . $step++ . ' ...' . PHP_EOL;
if (!empty($line)) { if (!empty($line)) {
$creation = dbQuery($line); if (!dbQuery($line)) {
if (!$creation) {
echo 'WARNING: Cannot execute query (' . $line . '): ' . mysqli_error($database_link) . "\n";
$return = 1; $return = 1;
} }
} }
@ -99,10 +89,9 @@ try {
d_echo("$line \n"); d_echo("$line \n");
if ($line[0] != '#') { if ($line[0] != '#') {
if (!mysqli_query($database_link, $line)) { if (!dbQuery($line)) {
$return = 2; $return = 2;
$err++; $err++;
d_echo(mysqli_error($database_link) . PHP_EOL);
} }
} }
} }

View File

@ -499,7 +499,7 @@
valueKey: 'name', valueKey: 'name',
templates: { templates: {
header: '<h5><strong>&nbsp;BGP Sessions</strong></h5>', header: '<h5><strong>&nbsp;BGP Sessions</strong></h5>',
suggestion: Handlebars.compile('<p><a href="@{{url}}"><small>@{{{bgp_image}}} @{{name}} - @{{hostname}}<br />AS@{{localas}} -> AS@{{remoteas}}</small></a></p>') suggestion: Handlebars.compile('<p><a href="@{{url}}"><small>@{{bgp_image}} @{{name}} - @{{hostname}}<br />AS@{{localas}} -> AS@{{remoteas}}</small></a></p>')
} }
}); });
$('#gsearch').bind('typeahead:open', function(ev, suggestion) { $('#gsearch').bind('typeahead:open', function(ev, suggestion) {

View File

@ -1 +0,0 @@
SELECT NOW();

View File

@ -164,7 +164,7 @@ class AuthSSOTest extends DBTestCase
// Retrieve it and validate // Retrieve it and validate
$dbuser = $a->getUser($a->getUserid($user)); $dbuser = $a->getUser($a->getUserid($user));
$this->assertTrue($a->authSSOGetAttr($config['sso']['realname_attr']) === $dbuser['realname']); $this->assertTrue($a->authSSOGetAttr($config['sso']['realname_attr']) === $dbuser['realname']);
$this->assertTrue($dbuser['level'] === "-1"); $this->assertTrue($dbuser['level'] == -1);
$this->assertTrue($a->authSSOGetAttr($config['sso']['email_attr']) === $dbuser['email']); $this->assertTrue($a->authSSOGetAttr($config['sso']['email_attr']) === $dbuser['email']);
// Change a few things and reauth // Change a few things and reauth
@ -202,7 +202,7 @@ class AuthSSOTest extends DBTestCase
// Retrieve it and validate the update persisted // Retrieve it and validate the update persisted
$dbuser = $a->getUser($a->getUserid($user)); $dbuser = $a->getUser($a->getUserid($user));
$this->assertTrue($a->authSSOGetAttr($config['sso']['realname_attr']) === $dbuser['realname']); $this->assertTrue($a->authSSOGetAttr($config['sso']['realname_attr']) === $dbuser['realname']);
$this->assertTrue($dbuser['level'] === "10"); $this->assertTrue($dbuser['level'] == 10);
$this->assertTrue($a->authSSOGetAttr($config['sso']['email_attr']) === $dbuser['email']); $this->assertTrue($a->authSSOGetAttr($config['sso']['email_attr']) === $dbuser['email']);
} }

View File

@ -140,12 +140,7 @@ class CommonFunctionsTest extends TestCase
public function testResolveGlues() public function testResolveGlues()
{ {
if (getenv('DBTEST')) { $this->dbSetUp();
dbConnect();
dbBeginTransaction();
} else {
$this->markTestSkipped('Database tests not enabled. Set DBTEST=1 to enable.');
}
$this->assertFalse(ResolveGlues(array('dbSchema'), 'device_id')); $this->assertFalse(ResolveGlues(array('dbSchema'), 'device_id'));
@ -166,9 +161,7 @@ class CommonFunctionsTest extends TestCase
$expected = array('ipv4_addresses.port_id', 'ports.device_id'); $expected = array('ipv4_addresses.port_id', 'ports.device_id');
$this->assertSame($expected, ResolveGlues(array('ipv4_addresses'), 'device_id')); $this->assertSame($expected, ResolveGlues(array('ipv4_addresses'), 'device_id'));
if (getenv('DBTEST')) { $this->dbTearDown();
dbRollbackTransaction();
}
} }
public function testFormatHostname() public function testFormatHostname()

View File

@ -122,12 +122,7 @@ class ConfigTest extends TestCase
public function testSetPersist() public function testSetPersist()
{ {
if (getenv('DBTEST')) { $this->dbSetUp();
Eloquent::boot();
Eloquent::DB()->beginTransaction();
} else {
$this->markTestSkipped('Database tests not enabled. Set DBTEST=1 to enable.');
}
$key = 'testing.persist'; $key = 'testing.persist';
@ -140,9 +135,7 @@ class ConfigTest extends TestCase
Config::set($key, 'two', true); Config::set($key, 'two', true);
$this->assertEquals('two', $query->value('config_value')); $this->assertEquals('two', $query->value('config_value'));
if (getenv('DBTEST')) { $this->dbTearDown();
Eloquent::DB()->rollBack();
}
} }
public function testHas() public function testHas()

View File

@ -113,21 +113,10 @@ class DBSetupTest extends DBTestCase
public function testSqlMode() public function testSqlMode()
{ {
global $sql_mode; $this->assertEquals(
$this->assertNotNull($sql_mode, 'Query to save SQL Mode in bootstrap.php failed'); 'ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION',
dbFetchCell("SELECT @@sql_mode")
// sql_mode can only be set by users with access
$access = array(
'GRANT ALL PRIVILEGES ON *.*',
'SUPER'
); );
if (str_contains(join(PHP_EOL, dbFetchColumn('SHOW GRANTS')), $access)) {
$this->assertEquals(
array('ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'),
dbFetchColumn("SELECT @@global.sql_mode")
);
}
} }
public function testValidateSchema() public function testValidateSchema()

View File

@ -43,8 +43,9 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
public function dbSetUp() public function dbSetUp()
{ {
if (getenv('DBTEST')) { if (getenv('DBTEST')) {
dbConnect(); \LibreNMS\DB\Eloquent::boot();
dbBeginTransaction(); \LibreNMS\DB\Eloquent::setStrictMode();
\LibreNMS\DB\Eloquent::DB()->beginTransaction();
} else { } else {
$this->markTestSkipped('Database tests not enabled. Set DBTEST=1 to enable.'); $this->markTestSkipped('Database tests not enabled. Set DBTEST=1 to enable.');
} }
@ -53,7 +54,7 @@ abstract class TestCase extends \PHPUnit_Framework_TestCase
public function dbTearDown() public function dbTearDown()
{ {
if (getenv('DBTEST')) { if (getenv('DBTEST')) {
dbRollbackTransaction(); \LibreNMS\DB\Eloquent::DB()->rollBack();
} }
} }

View File

@ -64,16 +64,18 @@ if (getenv('SNMPSIM')) {
if (getenv('DBTEST')) { if (getenv('DBTEST')) {
global $schema, $sql_mode; global $schema, $sql_mode;
try { // create testing table if needed
dbConnect(); $db_config = Config::getDatabaseSettings();
} catch (DatabaseConnectException $e) { $db_name = $db_config['db_name'];
echo $e->getMessage() . PHP_EOL;
} $connection = new PDO("mysql:", $db_config['db_user'], $db_config['db_pass']);
$connection->query("CREATE DATABASE IF NOT EXISTS $db_name");
unset($connection); // close connection
\LibreNMS\DB\Eloquent::boot();
\LibreNMS\DB\Eloquent::setStrictMode();
$sql_mode = dbFetchCell("SELECT @@global.sql_mode");
$db_name = dbFetchCell("SELECT DATABASE()");
$empty_db = (dbFetchCell("SELECT count(*) FROM `information_schema`.`tables` WHERE `table_type` = 'BASE TABLE' AND `table_schema` = ?", [$db_name]) == 0); $empty_db = (dbFetchCell("SELECT count(*) FROM `information_schema`.`tables` WHERE `table_type` = 'BASE TABLE' AND `table_schema` = ?", [$db_name]) == 0);
dbQuery("SET GLOBAL sql_mode='ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION'");
$cmd = $config['install_dir'] . '/build-base.php'; $cmd = $config['install_dir'] . '/build-base.php';
exec($cmd, $schema); exec($cmd, $schema);
@ -83,13 +85,10 @@ if (getenv('DBTEST')) {
register_shutdown_function(function () use ($empty_db, $sql_mode) { register_shutdown_function(function () use ($empty_db, $sql_mode) {
global $config; global $config;
dbConnect(); \LibreNMS\DB\Eloquent::boot();
echo "Cleaning database...\n"; echo "Cleaning database...\n";
// restore sql_mode
dbQuery("SET GLOBAL sql_mode='$sql_mode'");
$db_name = dbFetchCell('SELECT DATABASE()'); $db_name = dbFetchCell('SELECT DATABASE()');
if ($empty_db) { if ($empty_db) {
dbQuery("DROP DATABASE $db_name"); dbQuery("DROP DATABASE $db_name");

View File

@ -138,11 +138,11 @@ if (!file_exists(Config::get('install_dir').'/config.php')) {
// Connect to MySQL // Connect to MySQL
try { \LibreNMS\DB\Eloquent::boot();
dbConnect();
if (\LibreNMS\DB\Eloquent::isConnected()) {
$validator->ok('Database connection successful', null, 'database'); $validator->ok('Database connection successful', null, 'database');
} catch (\LibreNMS\Exceptions\DatabaseConnectException $e) { } else {
$validator->fail('Error connecting to your database. '.$e->getMessage(), null, 'database'); $validator->fail('Error connecting to your database. '.$e->getMessage(), null, 'database');
} }