From 487c461832f5e9a55cb987a5224b33e11b6d4758 Mon Sep 17 00:00:00 2001 From: Jonas Date: Mon, 27 Jun 2016 16:08:28 +0200 Subject: [PATCH 01/13] For Issue #436: (Fixed now!) Added the loadData Method Added a private method for executing unprepared statements --- MysqliDb.php | 115 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/MysqliDb.php b/MysqliDb.php index f3bc1ca7..46e832e0 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -373,6 +373,32 @@ public function setPrefix($prefix = '') return $this; } + /** + * Pushes a unprepared statement to the mysqli stack. + * WARNING: Use with caution. + * This method does not escape strings by default so make sure you'll never use it in production. + * + * @author Jonas Barascu + * @param [[Type]] $query [[Description]] + */ + private function queryUnprepared($query, $escapeQuery = false) + { + // Should we escape? + if($escapeQuery) { + $query = $this->mysqli()->real_escape_string($query); + } + // Execute query + $stmt = $this->mysqli()->query($query); + + // Failed? + if(!$stmt){ + throw new Exception("Unprepared Query Failed, ERRNO: ".$this->mysqli()->errno." (".$this->mysqli()->error.")"); + }; + + // return stmt for future use + return $stmt; + } + /** * Execute raw SQL query. * @@ -856,6 +882,93 @@ public function join($joinTable, $joinCondition, $joinType = '') return $this; } + + + /** + * This is a basic method which allows you to import raw .CSV data into a table + * Please check out http://dev.mysql.com/doc/refman/5.7/en/load-data.html for a valid .csv file. + + * @author Jonas Barascu (Noneatme) + * @param string $importTable The database table where the data will be imported into. + * @param string $importFile The file to be imported. Please use double backslashes \\ and make sure you + * use an absolute path. + * @param string $terminateCharField The char which will be used to separate the data in a row. + * @param string $terminateCharLine The char which marks the EOL. (PHP_EOL is also possible) + * @param string $ignoreLines The ammount of lines to ignore. Useful if your #0 row marks the data structure. + * + * @return boolean + */ + public function loadData($importTable, $importFile, $importSettings = + Array("fieldChar" => ';', "lineChar" => '\r\n', "linesToIgnore" => 1)) + { + // Define default success var + $success = false; + + // We have to check if the file exists + if(file_exists($importFile)) { + // Create default values + $terminateCharField = ';'; // Default is ; + $terminateCharLine = PHP_EOL; // Default \r\n or PHP_EOL (*nix is \n) + $ignoreLines = 1; // Default 1 + + // Check the import settings + if(gettype($importSettings) == "array") { + if(isset($importSettings["fieldChar"])) { + $terminateCharField = $importSettings["fieldChar"]; + } + if(isset($importSettings["lineChar"])) { + $terminateCharLine = $importSettings["lineChar"]; + } + if(isset($importSettings["linesToIgnore"])) { + $ignoreLines = $importSettings["linesToIgnore"]; + } + } + + // Add the prefix to the import table + $table = self::$prefix . $importTable; + + // Add 1 more slash to every slash so maria will interpret it as a path + $importFile = str_replace("\\", "\\\\", $importFile); + + // Build SQL Syntax + $sqlSyntax = sprintf('LOAD DATA INFILE \'%s\' INTO TABLE %s', + $importFile, $table); + + // FIELDS + $sqlSyntax .= sprintf(' FIELDS TERMINATED BY \'%s\'', $terminateCharField); + if(isset($importSettings["fieldEnclosure"])){ + $sqlSyntax .= sprintf(' ENCLOSED BY \'%s\'', $importSettings["fieldEnclosure"]); + } + + // LINES + $sqlSyntax .= sprintf(' LINES TERMINATED BY \'%s\'', $terminateCharLine); + if(isset($importSettings["lineStarting"])){ + $sqlSyntax .= sprintf(' STARTING BY \'%s\'', $importSettings["lineStarting"]); + } + + // IGNORE LINES + $sqlSyntax .= sprintf(' IGNORE %d LINES', $ignoreLines); + + // Exceute the query unprepared because LOAD DATA only works with unprepared statements. + $result = $this->queryUnprepared($sqlSyntax); + + // Are there rows modified? + if($result) { + $success = true; + } + // Something went wrong + else { + $success = false; + } + } + else { + // Throw an exception + throw new Exception("importCSV -> importFile ".$importFile." does not exists!"); + } + + // Let the user know if the import failed / succeeded + return $success; + } /** * This method allows you to specify multiple (method chaining optional) ORDER BY statements for SQL queries. @@ -1908,4 +2021,4 @@ public function paginate ($table, $page, $fields = null) { } } -// END class +// END class \ No newline at end of file From 5ff94ccc08480d4d4654a79b79f5aaa5d8d96920 Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 28 Jun 2016 09:55:00 +0200 Subject: [PATCH 02/13] Added loadXML and tests --- MysqliDb.php | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/MysqliDb.php b/MysqliDb.php index 46e832e0..a7afbaf2 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -969,6 +969,65 @@ public function loadData($importTable, $importFile, $importSettings = // Let the user know if the import failed / succeeded return $success; } + + + public function loadXML($importTable, $importFile, $importSettings = + Array("linesToIgnore" => 0)) + { + // Define default success var + $success = false; + + // We have to check if the file exists + if(file_exists($importFile)) { + // Create default values + $ignoreLines = 0; // Default 0 + + // Check the import settings + if(gettype($importSettings) == "array") { + + if(isset($importSettings["linesToIgnore"])) { + $ignoreLines = $importSettings["linesToIgnore"]; + } + } + + // Add the prefix to the import table + $table = self::$prefix . $importTable; + + // Add 1 more slash to every slash so maria will interpret it as a path + $importFile = str_replace("\\", "\\\\", $importFile); + + // Build SQL Syntax + $sqlSyntax = sprintf('LOAD XML INFILE \'%s\' INTO TABLE %s', + $importFile, $table); + + // FIELDS + if(isset($importSettings["rowTag"])) { + $sqlSyntax .= sprintf(' ROWS IDENTIFIED BY \'%s\'', $importSettings["rowTag"]); + } + + // IGNORE LINES + $sqlSyntax .= sprintf(' IGNORE %d LINES', $ignoreLines); + + // Exceute the query unprepared because LOAD XML only works with unprepared statements. + $result = $this->queryUnprepared($sqlSyntax); + + // Are there rows modified? + if($result) { + $success = true; + } + // Something went wrong + else { + $success = false; + } + } + else { + // Throw an exception + throw new Exception("importXML -> importFile ".$importFile." does not exists!"); + } + + // Let the user know if the import failed / succeeded + return $success; + } /** * This method allows you to specify multiple (method chaining optional) ORDER BY statements for SQL queries. From 6059f7f2ed68201f34c9bc0022ac201ebf86543d Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 28 Jun 2016 10:04:46 +0200 Subject: [PATCH 03/13] Add tests/csvimport/test.import.php to .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 52d75990..47aa3968 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,4 @@ .DS_Store #Vim trash -*.swp \ No newline at end of file +*.swptests/csvimport/test.import.php From 415a91ffe4e151bf44cb55152bdfa43dacec7141 Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 28 Jun 2016 10:25:25 +0200 Subject: [PATCH 04/13] Added missing PHPDocs. Added missing test files. --- MysqliDb.php | 15 +++++++++---- tests/dataimport/data.csv | 6 +++++ tests/dataimport/data.xml | 8 +++++++ tests/dataimport/users.sql | 45 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 4 deletions(-) create mode 100644 tests/dataimport/data.csv create mode 100644 tests/dataimport/data.xml create mode 100644 tests/dataimport/users.sql diff --git a/MysqliDb.php b/MysqliDb.php index a7afbaf2..45437450 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -970,9 +970,16 @@ public function loadData($importTable, $importFile, $importSettings = return $success; } - - public function loadXML($importTable, $importFile, $importSettings = - Array("linesToIgnore" => 0)) + /** + * This method is usefull for importing XML files into a specific table. + * Check out the LOAD XML syntax for your MySQL server. + * + * @author Jonas Barascu + * @param string $importTable The table in which the data will be imported to. + * @param string $importFile The file which contains the .XML data. + * @return boolean Returns true if the import succeeded, false if it failed. + */ + public function loadXML($importTable, $importFile, $importSettings = Array("linesToIgnore" => 0)) { // Define default success var $success = false; @@ -2080,4 +2087,4 @@ public function paginate ($table, $page, $fields = null) { } } -// END class \ No newline at end of file +// END class diff --git a/tests/dataimport/data.csv b/tests/dataimport/data.csv new file mode 100644 index 00000000..5c0c627e --- /dev/null +++ b/tests/dataimport/data.csv @@ -0,0 +1,6 @@ +id;username;name +3;simon;Simon Jarred +4;martin;Martin Fuel +5;example;Example Name 1 +6;example2;Example Name 2 +7;example3;Example Name 4 \ No newline at end of file diff --git a/tests/dataimport/data.xml b/tests/dataimport/data.xml new file mode 100644 index 00000000..3cb5669c --- /dev/null +++ b/tests/dataimport/data.xml @@ -0,0 +1,8 @@ + + + + + Likame + Datataa + + diff --git a/tests/dataimport/users.sql b/tests/dataimport/users.sql new file mode 100644 index 00000000..04b48195 --- /dev/null +++ b/tests/dataimport/users.sql @@ -0,0 +1,45 @@ +-- phpMyAdmin SQL Dump +-- version 4.5.1 +-- http://www.phpmyadmin.net +-- +-- Host: 127.0.0.1 +-- Erstellungszeit: 27. Jun 2016 um 14:21 +-- Server-Version: 10.1.13-MariaDB +-- PHP-Version: 5.6.20 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- Datenbank: `db_test` +-- + +-- -------------------------------------------------------- + +-- +-- Tabellenstruktur für Tabelle `users` +-- + +CREATE TABLE `users` ( + `id` int(11) NOT NULL, + `username` varchar(32) NOT NULL, + `name` varchar(32) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=latin1; + +-- +-- Daten für Tabelle `users` +-- + +INSERT INTO `users` (`id`, `username`, `name`) VALUES +(1, 'test_1', 'John Doe'), +(2, 'test_2', 'Test User'); + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; From 77cc8fc78adcba5d8cfb486beb2de1f2bf69580a Mon Sep 17 00:00:00 2001 From: Noneatme Date: Tue, 28 Jun 2016 14:21:50 +0200 Subject: [PATCH 05/13] Update readme.md --- readme.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/readme.md b/readme.md index 8cc97059..84d3ce25 100644 --- a/readme.md +++ b/readme.md @@ -1,12 +1,16 @@ MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements
### Table of Contents +(All _italic_ categories has been implemented by me.) + **[Initialization](#initialization)** **[Objects mapping](#objects-mapping)** **[Insert Query](#insert-query)** **[Update Query](#update-query)** **[Select Query](#select-query)** **[Delete Query](#delete-query)** +**>> _[Insert Data](#insert-data)_** +**>> _[Insert XML](#insert-xml)_** **[Running raw SQL queries](#running-raw-sql-queries)** **[Query Keywords](#query-keywords)** **[Where Conditions](#where--having-methods)** @@ -20,6 +24,7 @@ MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements **[Helper Methods](#helper-methods)** **[Transaction Helpers](#transaction-helpers)** **[Error Helpers](#error-helpers)** +**>> _[Table Locking](#table-locking)_** ## Support Me @@ -212,6 +217,55 @@ foreach ($logins as $login) echo $login; ``` +###Insert Data +You can also load .CSV or .XML data into a specific table. +To insert .csv data, use the following syntax: +```php +$path_to_file = "/home/john/file.csv"; +$db->loadData("users", $path_to_file); +``` +This will load a .csv file called **file.csv** in the folder **/home/john/** (john's home directory.) +You can also attach an optional array of options. +Valid options are: + +```php +Array( + "fieldChar" => ';', // Char which separates the data + "lineChar" => '\r\n', // Char which separates the lines + "linesToIgnore" => 1 // Amount of lines to ignore at the beginning of the import +); +``` + +Attach them using +```php +$options = Array("fieldChar" => ';', "lineChar" => '\r\n', "linesToIgnore" => 1); +$db->loadData("users", "/home/john/file.csv", $options); +``` + +###Insert XML +To load XML data into a table, you can use the method **loadXML**. +The syntax is smillar to the loadData syntax. +```php +$path_to_file = "/home/john/file.xml"; +$db->loadXML("users", $path_to_file); +``` + +You can also add optional parameters. +Valid parameters: +```php +Array( + "linesToIgnore" => 0, // Amount of lines / rows to ignore at the beginning of the import + "rowTag" => "" // The tag which marks the beginning of an entry +) +``` + +Usage: +```php +$options = Array("linesToIgnore" => 0, "rowTag" => ""): +$path_to_file = "/home/john/file.xml"; +$db->loadXML("users", $path_to_file, $options); +``` + ###Pagination Use paginate() instead of get() to fetch paginated result ```php @@ -630,6 +684,7 @@ if (!$db->insert ('myTable', $insertData)) { } ``` + ### Error helpers After you executed a query you have options to check if there was an error. You can get the MySQL error string or the error code for the last executed query. ```php @@ -668,3 +723,27 @@ print_r ($db->trace); ) ``` + +##Table Locking +To lock tables, you can use the **lock** method together with **setLockMethod**. +The following example will lock the table **users** for **write** access. +```php +$db->setLockMethod("WRITE")->lock("users"); +``` + +Calling another **->lock()** will remove the first lock. +You can also use +```php +$db->unlock(); +``` +to unlock the previous locked tables. +To lock multiple tables, you can use an array. +Example: +```php +$db->setLockMethod("READ")->lock(array("users", "log")); +``` +This will lock the tables **users** and **log** for **READ** access only. +Make sure you use **unlock()* afterwards or your tables will remain locked! + + +Last edited by Noneatme on June 28. From 058f531956a47949ec8b5c48ebd041584429cae7 Mon Sep 17 00:00:00 2001 From: Noneatme Date: Tue, 28 Jun 2016 14:22:07 +0200 Subject: [PATCH 06/13] Update readme.md --- readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/readme.md b/readme.md index 84d3ce25..e603cfc9 100644 --- a/readme.md +++ b/readme.md @@ -23,7 +23,7 @@ MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements **[Has method](#has-method)** **[Helper Methods](#helper-methods)** **[Transaction Helpers](#transaction-helpers)** -**[Error Helpers](#error-helpers)** +**[Error Helpers](#error-helpers)** **>> _[Table Locking](#table-locking)_** ## Support Me From 867610195ba10fcd0a3b190ff411cad85e37bf2c Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 28 Jun 2016 14:21:54 +0200 Subject: [PATCH 07/13] Added table locking --- MysqliDb.php | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 2 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index 45437450..f7ea1353 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -81,7 +81,19 @@ class MysqliDb * @var array */ protected $_groupBy = array(); - + + /** + * Dynamic type list for tempromary locking tables. + * @var array + */ + protected $_tableLocks = array(); + + /** + * Variable which holds the current table lock method. + * @var string + */ + protected $_tableLockMethod = "READ"; + /** * Dynamic array that holds a combination of where condition/table data value types and parameter references * @var array @@ -1092,7 +1104,124 @@ public function groupBy($groupByField) $this->_groupBy[] = $groupByField; return $this; } + + + /** + * This method sets the current table lock method. + * + * @author Jonas Barascu + * @param string $method The table lock method. Can be READ or WRITE. + * + * @throws Exception + * @return MysqliDb + */ + public function setLockMethod($method) + { + // Switch the uppercase string + switch(strtoupper($method)) { + // Is it READ or WRITE? + case "READ" || "WRITE": + // Succeed + $this->_tableLockMethod = $method; + break; + default: + // Else throw an exception + throw new Exception("Bad lock type: Can be either READ or WRITE"); + break; + } + return $this; + } + + /** + * Locks a table for R/W action. + * + * @author Jonas Barascu + * @param string $table The table to be locked. Can be a table or a view. + * + * @throws Exception + * @return MysqliDb if succeeeded; + */ + public function lock($table) + { + // Main Query + $this->_query = "LOCK TABLES"; + + // Is the table an array? + if(gettype($table) == "array") { + // Loop trough it and attach it to the query + foreach($table as $key => $value) { + if(gettype($value) == "string") { + if($key > 0) { + $this->_query .= ","; + } + $this->_query .= " ".self::$prefix.$value." ".$this->_tableLockMethod; + } + } + } + else + { + // Build the table prefix + $table = self::$prefix . $table; + + // Build the query + $this->_query = "LOCK TABLES ".$table." ".$this->_tableLockMethod; + } + + // Exceute the query unprepared because LOCK only works with unprepared statements. + $result = $this->queryUnprepared($this->_query); + + // Reset the query + $this->reset(); + + // Are there rows modified? + if($result) { + // Return true + // We can't return ourself because if one table gets locked, all other ones get unlocked! + return true; + } + // Something went wrong + else { + throw new Exception("Locking of table ".$table." failed"); + } + + // Return the success value + return false; + } + + /** + * Unlocks all tables in a database. + * Also commits transactions. + * + * @author Jonas Barascu + * @return MysqliDb + */ + public function unlock() + { + // Build the query + $this->_query = "UNLOCK TABLES"; + + // Exceute the query unprepared because UNLOCK and LOCK only works with unprepared statements. + $result = $this->queryUnprepared($this->_query); + // Reset the query + $this->reset(); + + // Are there rows modified? + if($result) { + // return self + return $this; + } + // Something went wrong + else { + throw new Exception("Unlocking of tables failed"); + } + + + // Return self + return $this; + } + + /** * This methods returns the ID of the last inserted item * @@ -2087,4 +2216,4 @@ public function paginate ($table, $page, $fields = null) { } } -// END class +// END class \ No newline at end of file From dae696fde8fbdb3af0e0496151b075dca744203e Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 28 Jun 2016 14:27:00 +0200 Subject: [PATCH 08/13] Fixed readme.md for master branch --- readme.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/readme.md b/readme.md index e603cfc9..4c7c7666 100644 --- a/readme.md +++ b/readme.md @@ -1,7 +1,6 @@ MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements
### Table of Contents -(All _italic_ categories has been implemented by me.) **[Initialization](#initialization)** **[Objects mapping](#objects-mapping)** @@ -9,8 +8,8 @@ MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements **[Update Query](#update-query)** **[Select Query](#select-query)** **[Delete Query](#delete-query)** -**>> _[Insert Data](#insert-data)_** -**>> _[Insert XML](#insert-xml)_** +**[Insert Data](#insert-data)** +**[Insert XML](#insert-xml)** **[Running raw SQL queries](#running-raw-sql-queries)** **[Query Keywords](#query-keywords)** **[Where Conditions](#where--having-methods)** @@ -24,7 +23,7 @@ MysqliDb -- Simple MySQLi wrapper and object mapper with prepared statements **[Helper Methods](#helper-methods)** **[Transaction Helpers](#transaction-helpers)** **[Error Helpers](#error-helpers)** -**>> _[Table Locking](#table-locking)_** +**[Table Locking](#table-locking)** ## Support Me @@ -745,5 +744,3 @@ $db->setLockMethod("READ")->lock(array("users", "log")); This will lock the tables **users** and **log** for **READ** access only. Make sure you use **unlock()* afterwards or your tables will remain locked! - -Last edited by Noneatme on June 28. From 91beb07807c752b9fcd74e5d7ea55a4ae2fa2a96 Mon Sep 17 00:00:00 2001 From: Jonas Date: Tue, 28 Jun 2016 14:41:46 +0200 Subject: [PATCH 09/13] Fixed up formatting + removed gitignore + added tests for testing the import functions --- .gitignore | 5 --- MysqliDb.php | 19 ++++------ tests/dataimport/test.import.php | 61 ++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 17 deletions(-) delete mode 100644 .gitignore create mode 100644 tests/dataimport/test.import.php diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 47aa3968..00000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -#Mac OS X files -.DS_Store - -#Vim trash -*.swptests/csvimport/test.import.php diff --git a/MysqliDb.php b/MysqliDb.php index f7ea1353..2ad271f2 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -903,11 +903,7 @@ public function join($joinTable, $joinCondition, $joinType = '') * @author Jonas Barascu (Noneatme) * @param string $importTable The database table where the data will be imported into. * @param string $importFile The file to be imported. Please use double backslashes \\ and make sure you - * use an absolute path. - * @param string $terminateCharField The char which will be used to separate the data in a row. - * @param string $terminateCharLine The char which marks the EOL. (PHP_EOL is also possible) - * @param string $ignoreLines The ammount of lines to ignore. Useful if your #0 row marks the data structure. - * + * @param string $importSettings An Array defining the import settings as described in the README.md * @return boolean */ public function loadData($importTable, $importFile, $importSettings = @@ -987,8 +983,10 @@ public function loadData($importTable, $importFile, $importSettings = * Check out the LOAD XML syntax for your MySQL server. * * @author Jonas Barascu - * @param string $importTable The table in which the data will be imported to. - * @param string $importFile The file which contains the .XML data. + * @param string $importTable The table in which the data will be imported to. + * @param string $importFile The file which contains the .XML data. + * @param string $importSettings An Array defining the import settings as described in the README.md + * * @return boolean Returns true if the import succeeded, false if it failed. */ public function loadXML($importTable, $importFile, $importSettings = Array("linesToIgnore" => 0)) @@ -1003,7 +1001,6 @@ public function loadXML($importTable, $importFile, $importSettings = Array("line // Check the import settings if(gettype($importSettings) == "array") { - if(isset($importSettings["linesToIgnore"])) { $ignoreLines = $importSettings["linesToIgnore"]; } @@ -1018,7 +1015,6 @@ public function loadXML($importTable, $importFile, $importSettings = Array("line // Build SQL Syntax $sqlSyntax = sprintf('LOAD XML INFILE \'%s\' INTO TABLE %s', $importFile, $table); - // FIELDS if(isset($importSettings["rowTag"])) { $sqlSyntax .= sprintf(' ROWS IDENTIFIED BY \'%s\'', $importSettings["rowTag"]); @@ -1158,11 +1154,10 @@ public function lock($table) } } } - else - { + else{ // Build the table prefix $table = self::$prefix . $table; - + // Build the query $this->_query = "LOCK TABLES ".$table." ".$this->_tableLockMethod; } diff --git a/tests/dataimport/test.import.php b/tests/dataimport/test.import.php new file mode 100644 index 00000000..f637bdd8 --- /dev/null +++ b/tests/dataimport/test.import.php @@ -0,0 +1,61 @@ +loadData("users", "datanew.csv"); +} +catch(Exception $e) +{ + echo "Test 1 Succeeded!", PHP_EOL; + // goto newtest + goto test_import1; +} +test_import1: +{ + try + { + // Import the CSV + $db->loadData("users", // Table + "D:\\DEV\\git\\PHP-MySQLi-Database-Class\\tests\\dataimport\\data.csv", + Array("fieldEnclosure" => '', "lineStarting" => '')); + echo "Test 2 Succeeded!", PHP_EOL; + + goto test_import2; + } + catch(Exception $e) + { + echo($e); + } +} +test_import2: +{ + try + { + $db->setLockMethod("WRITE")->lock(array("users", "log")); + + $db->loadXML("users", + "D:\\DEV\\git\\PHP-MySQLi-Database-Class\\tests\\dataimport\\data.xml"); + echo "Test 3 Succeeded!", PHP_EOL; + + $db->unlock(); + + } + catch(Exception $e) + { + echo($e); + } +} \ No newline at end of file From 624dff9f77280c96d920c255dbd824ceba4a37dd Mon Sep 17 00:00:00 2001 From: Jonas Date: Wed, 29 Jun 2016 08:40:13 +0200 Subject: [PATCH 10/13] Forgot to free results (Ooops) --- MysqliDb.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/MysqliDb.php b/MysqliDb.php index 2ad271f2..ec71c698 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -968,6 +968,9 @@ public function loadData($importTable, $importFile, $importSettings = else { $success = false; } + + // Free result + $result->free(); } else { // Throw an exception @@ -1034,6 +1037,9 @@ public function loadXML($importTable, $importFile, $importSettings = Array("line else { $success = false; } + + // Free result + $result->free(); } else { // Throw an exception @@ -1178,6 +1184,9 @@ public function lock($table) else { throw new Exception("Locking of table ".$table." failed"); } + + // Free result + $result->free(); // Return the success value return false; @@ -1211,7 +1220,9 @@ public function unlock() throw new Exception("Unlocking of tables failed"); } - + // Free result + $result->free(); + // Return self return $this; } From 4d413e3bc285cf670f97d03330dd0f4daabe318d Mon Sep 17 00:00:00 2001 From: Jonas Date: Wed, 29 Jun 2016 08:41:40 +0200 Subject: [PATCH 11/13] Forgot to free results (Ooops) (reverted from commit 624dff9f77280c96d920c255dbd824ceba4a37dd) --- MysqliDb.php | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index ec71c698..2ad271f2 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -968,9 +968,6 @@ public function loadData($importTable, $importFile, $importSettings = else { $success = false; } - - // Free result - $result->free(); } else { // Throw an exception @@ -1037,9 +1034,6 @@ public function loadXML($importTable, $importFile, $importSettings = Array("line else { $success = false; } - - // Free result - $result->free(); } else { // Throw an exception @@ -1184,9 +1178,6 @@ public function lock($table) else { throw new Exception("Locking of table ".$table." failed"); } - - // Free result - $result->free(); // Return the success value return false; @@ -1220,9 +1211,7 @@ public function unlock() throw new Exception("Unlocking of tables failed"); } - // Free result - $result->free(); - + // Return self return $this; } From a3b3928609564105a5b8de9a1275d0d630530d21 Mon Sep 17 00:00:00 2001 From: Jonas Date: Fri, 8 Jul 2016 14:59:32 +0200 Subject: [PATCH 12/13] Added avbdr's stuff to fix stuff #1 --- MysqliDb.php | 189 ++++++++++++++++++++++----------------------------- 1 file changed, 82 insertions(+), 107 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index 2ad271f2..d502d1a8 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -393,12 +393,8 @@ public function setPrefix($prefix = '') * @author Jonas Barascu * @param [[Type]] $query [[Description]] */ - private function queryUnprepared($query, $escapeQuery = false) + private function queryUnprepared($query) { - // Should we escape? - if($escapeQuery) { - $query = $this->mysqli()->real_escape_string($query); - } // Execute query $stmt = $this->mysqli()->query($query); @@ -906,76 +902,63 @@ public function join($joinTable, $joinCondition, $joinType = '') * @param string $importSettings An Array defining the import settings as described in the README.md * @return boolean */ - public function loadData($importTable, $importFile, $importSettings = - Array("fieldChar" => ';', "lineChar" => '\r\n', "linesToIgnore" => 1)) + public function loadData($importTable, $importFile, $importSettings = null) { // Define default success var $success = false; // We have to check if the file exists - if(file_exists($importFile)) { - // Create default values - $terminateCharField = ';'; // Default is ; - $terminateCharLine = PHP_EOL; // Default \r\n or PHP_EOL (*nix is \n) - $ignoreLines = 1; // Default 1 - - // Check the import settings - if(gettype($importSettings) == "array") { - if(isset($importSettings["fieldChar"])) { - $terminateCharField = $importSettings["fieldChar"]; - } - if(isset($importSettings["lineChar"])) { - $terminateCharLine = $importSettings["lineChar"]; - } - if(isset($importSettings["linesToIgnore"])) { - $ignoreLines = $importSettings["linesToIgnore"]; - } - } - - // Add the prefix to the import table - $table = self::$prefix . $importTable; - - // Add 1 more slash to every slash so maria will interpret it as a path - $importFile = str_replace("\\", "\\\\", $importFile); - - // Build SQL Syntax - $sqlSyntax = sprintf('LOAD DATA INFILE \'%s\' INTO TABLE %s', - $importFile, $table); - - // FIELDS - $sqlSyntax .= sprintf(' FIELDS TERMINATED BY \'%s\'', $terminateCharField); - if(isset($importSettings["fieldEnclosure"])){ - $sqlSyntax .= sprintf(' ENCLOSED BY \'%s\'', $importSettings["fieldEnclosure"]); - } - - // LINES - $sqlSyntax .= sprintf(' LINES TERMINATED BY \'%s\'', $terminateCharLine); - if(isset($importSettings["lineStarting"])){ - $sqlSyntax .= sprintf(' STARTING BY \'%s\'', $importSettings["lineStarting"]); - } - - // IGNORE LINES - $sqlSyntax .= sprintf(' IGNORE %d LINES', $ignoreLines); - - // Exceute the query unprepared because LOAD DATA only works with unprepared statements. - $result = $this->queryUnprepared($sqlSyntax); - - // Are there rows modified? - if($result) { - $success = true; - } - // Something went wrong - else { - $success = false; - } - } - else { + if(!file_exists($importFile)) { // Throw an exception throw new Exception("importCSV -> importFile ".$importFile." does not exists!"); + return; + } + + // Define the default values + // We will merge it later + $settings = Array("fieldChar" => ';', "lineChar" => '\r\n', "linesToIgnore" => 1); + + // Check the import settings + if(gettype($importSettings) == "array") { + // Merge the default array with the custom one + $settings = array_merge($settings, $importSettings); + } + + echo(var_dump($settings)); + + // Add the prefix to the import table + $table = self::$prefix . $importTable; + + // Add 1 more slash to every slash so maria will interpret it as a path + $importFile = str_replace("\\", "\\\\", $importFile); + + // Build SQL Syntax + $sqlSyntax = sprintf('LOAD DATA INFILE \'%s\' INTO TABLE %s', + $importFile, $table); + + // FIELDS + $sqlSyntax .= sprintf(' FIELDS TERMINATED BY \'%s\'', $settings["fieldChar"]); + if(isset($settings["fieldEnclosure"])) { + $sqlSyntax .= sprintf(' ENCLOSED BY \'%s\'', $settings["fieldEnclosure"]); } + // LINES + $sqlSyntax .= sprintf(' LINES TERMINATED BY \'%s\'', $settings["lineChar"]); + if(isset($settings["lineStarting"])) { + $sqlSyntax .= sprintf(' STARTING BY \'%s\'', $settings["lineStarting"]); + } + + // IGNORE LINES + $sqlSyntax .= sprintf(' IGNORE %d LINES', $settings["linesToIgnore"]); + + echo($sqlSyntax); + + // Exceute the query unprepared because LOAD DATA only works with unprepared statements. + $result = $this->queryUnprepared($sqlSyntax); + + // Are there rows modified? // Let the user know if the import failed / succeeded - return $success; + return (bool) $result; } /** @@ -989,59 +972,51 @@ public function loadData($importTable, $importFile, $importSettings = * * @return boolean Returns true if the import succeeded, false if it failed. */ - public function loadXML($importTable, $importFile, $importSettings = Array("linesToIgnore" => 0)) + public function loadXml($importTable, $importFile, $importSettings = null) { // Define default success var $success = false; // We have to check if the file exists - if(file_exists($importFile)) { - // Create default values - $ignoreLines = 0; // Default 0 - - // Check the import settings - if(gettype($importSettings) == "array") { - if(isset($importSettings["linesToIgnore"])) { - $ignoreLines = $importSettings["linesToIgnore"]; - } - } - - // Add the prefix to the import table - $table = self::$prefix . $importTable; + if(!file_exists($importFile)) { + // Does not exists + throw new Exception("loadXml: Import file does not exists"); + return; + } + + + // Create default values + $settings = Array("linesToIgnore" => 0); - // Add 1 more slash to every slash so maria will interpret it as a path - $importFile = str_replace("\\", "\\\\", $importFile); + // Check the import settings + if(gettype($importSettings) == "array") { + $settings = array_merge($settings, $importSettings); + } - // Build SQL Syntax - $sqlSyntax = sprintf('LOAD XML INFILE \'%s\' INTO TABLE %s', + // Add the prefix to the import table + $table = self::$prefix . $importTable; + + // Add 1 more slash to every slash so maria will interpret it as a path + $importFile = str_replace("\\", "\\\\", $importFile); + + // Build SQL Syntax + $sqlSyntax = sprintf('LOAD XML INFILE \'%s\' INTO TABLE %s', $importFile, $table); - // FIELDS - if(isset($importSettings["rowTag"])) { - $sqlSyntax .= sprintf(' ROWS IDENTIFIED BY \'%s\'', $importSettings["rowTag"]); - } - - // IGNORE LINES - $sqlSyntax .= sprintf(' IGNORE %d LINES', $ignoreLines); - - // Exceute the query unprepared because LOAD XML only works with unprepared statements. - $result = $this->queryUnprepared($sqlSyntax); - - // Are there rows modified? - if($result) { - $success = true; - } - // Something went wrong - else { - $success = false; - } - } - else { - // Throw an exception - throw new Exception("importXML -> importFile ".$importFile." does not exists!"); + + // FIELDS + if(isset($settings["rowTag"])) { + $sqlSyntax .= sprintf(' ROWS IDENTIFIED BY \'%s\'', $settings["rowTag"]); } + + // IGNORE LINES + $sqlSyntax .= sprintf(' IGNORE %d LINES', $settings["linesToIgnore"]); + + // Exceute the query unprepared because LOAD XML only works with unprepared statements. + $result = $this->queryUnprepared($sqlSyntax); + // Are there rows modified? // Let the user know if the import failed / succeeded - return $success; + return (bool) $result; } /** From dbc51997ef552b36c192d8a30916ff6b578870f8 Mon Sep 17 00:00:00 2001 From: Jonas Date: Fri, 8 Jul 2016 15:35:47 +0200 Subject: [PATCH 13/13] Fixed stuff #2, removed echos, fixed data load error. --- MysqliDb.php | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/MysqliDb.php b/MysqliDb.php index d502d1a8..6c6b5580 100644 --- a/MysqliDb.php +++ b/MysqliDb.php @@ -904,9 +904,6 @@ public function join($joinTable, $joinCondition, $joinType = '') */ public function loadData($importTable, $importFile, $importSettings = null) { - // Define default success var - $success = false; - // We have to check if the file exists if(!file_exists($importFile)) { // Throw an exception @@ -916,16 +913,14 @@ public function loadData($importTable, $importFile, $importSettings = null) // Define the default values // We will merge it later - $settings = Array("fieldChar" => ';', "lineChar" => '\r\n', "linesToIgnore" => 1); + $settings = Array("fieldChar" => ';', "lineChar" => PHP_EOL, "linesToIgnore" => 1); // Check the import settings if(gettype($importSettings) == "array") { // Merge the default array with the custom one $settings = array_merge($settings, $importSettings); } - - echo(var_dump($settings)); - + // Add the prefix to the import table $table = self::$prefix . $importTable; @@ -950,12 +945,10 @@ public function loadData($importTable, $importFile, $importSettings = null) // IGNORE LINES $sqlSyntax .= sprintf(' IGNORE %d LINES', $settings["linesToIgnore"]); - - echo($sqlSyntax); - + // Exceute the query unprepared because LOAD DATA only works with unprepared statements. $result = $this->queryUnprepared($sqlSyntax); - + // Are there rows modified? // Let the user know if the import failed / succeeded return (bool) $result; @@ -974,9 +967,6 @@ public function loadData($importTable, $importFile, $importSettings = null) */ public function loadXml($importTable, $importFile, $importSettings = null) { - // Define default success var - $success = false; - // We have to check if the file exists if(!file_exists($importFile)) { // Does not exists @@ -984,7 +974,6 @@ public function loadXml($importTable, $importFile, $importSettings = null) return; } - // Create default values $settings = Array("linesToIgnore" => 0);