Database Syntax error Codeigniter Grocery Crud with SQLite - php

I have created one application with Codeigniter Grocery Crud with SQLite. It is working fine at localhost. But when I hosted online by CPanel, it shows syntax error following,
A Database Error Occurred
Error Number: HY000/1
near "SHOW": syntax error
SHOW COLUMNS FROM 'epaper'
Filename: models/Grocery_crud_model.php
Line Number: 436
At File: models/Grocery_crud_model.php 436 line is following
foreach($this->db->query("SHOW COLUMNS FROM '$this->table_name' ")->result() as $db_field_type)
And Full Model is
function get_field_types_basic_table()
{
$db_field_types = array();
foreach($this->db->query("SHOW COLUMNS FROM '$this->table_name' ")->result() as $db_field_type)
{
$type = explode("(",$db_field_type->Type);
$db_type = $type[0];
if(isset($type[1]))
{
if(substr($type[1],-1) == ')')
{
$length = substr($type[1],0,-1);
}
else
{
list($length) = explode(" ",$type[1]);
$length = substr($length,0,-1);
}
}
else
{
$length = '';
}
$db_field_types[$db_field_type->Field]['db_max_length'] = $length;
$db_field_types[$db_field_type->Field]['db_type'] = $db_type;
$db_field_types[$db_field_type->Field]['db_null'] = $db_field_type->Null == 'YES' ? true : false;
$db_field_types[$db_field_type->Field]['db_extra'] = $db_field_type->Extra;
}
$results = $this->db->field_data($this->table_name);
foreach($results as $num => $row)
{
$row = (array)$row;
$results[$num] = (object)( array_merge($row, $db_field_types[$row['name']]) );
}
return $results;
}
For More Reference
https://github.com/scoumbourdis/grocery-crud/blob/master/application/models/Grocery_crud_model.php
Please help me to solve syntax error.

Related

How do I prevent the Undefined offset:1 Error Exception in php

I have the following code for importing excel data in my Controller
$row['cast'] = "Directed by:Tracie Pang;Written by:Dennis Kelly;Starring:Pinky Amador,Thomas Pang,Tess Pang,Salif Hardie";
$cast_types = explode(";", $row['cast']);
foreach ($cast_types as $cast_type) {
$cast = explode(":", $cast_type);
$cast_type_name = $cast[0];
// if there is more than 1 cast name
if (strpos($cast[1], ",") !== false) {
$cast_names = explode(",", $cast[1]);
$cast_names_str = implode("<br>", $cast_names);
} else {
$cast_names_str = $cast[1];
}
$cast[1] will look something like "Tracie Pang" or "Pinky Amador,Thomas Pang,Tess Pang" (managed to see it also by running dd($cast[1]) ) but Laravel throws me an "Error Exception : Undefined Offset 1" here
if (strpos($cast[1], ",") !== false) {
How can I prevent this error?
you can check if the array key exist using array_key_exists function to prevent the error
$row['cast'] = "Directed by:Tracie Pang;Written by:Dennis Kelly;Starring:Pinky
Amador,Thomas Pang,Tess Pang,Salif Hardie";
$cast_types = explode(";", $row['cast']);
foreach ($cast_types as $cast_type) {
$cast = explode(":", $cast_type);
$cast_type_name = $cast[0];
// if there is more than 1 cast name
if (array_key_exists(1, $cast)) {
$cast_names = explode(",", $cast[1]);
$cast_names_str = implode("<br>", $cast_names);
} else {
$cast_names_str = $cast[1];
}
}

Is there a way to update 12000+ rows from txt file in less then 2mins?

I need to update a table with more then 12000 row using php Codeigniter and a txt file.. reading the file and the foreach loop are fine but when updating line by line it takes like 30 mins, I guess the problem is I'm searching by name because I have no id in the txt file...
Here is my code:
controller:
$fn = fopen($this->upload->data('full_path'),"r");
$update = true;
while(! feof($fn) && $update) {
$pieces = explode("|", fgets($fn));
if(sizeof($pieces) == 9 && is_numeric(trim($pieces[1]))) {
$update = $this->model_products->update3s($pieces);
}
}
fclose($fn);
Model:
public function update3s($product) {
if ($product) {
$product[2] = trim(str_replace("'","''",$product[2]));
$product[1] = trim($product[1]);
$product[6] = trim($product[6]);
$product[3] = trim($product[3]);
$sql = "UPDATE products set qty = $product[3], price_vente = $product[6] where (name = '$product[2]')";
echo $sql.'<br>';
$update = $query = $this->db->query($sql);
return $update;
}
return false;
}
You can use transaction and add index for column name in database table.
$fn = fopen($this->upload->data('full_path'),"r");
$update = true;
$updatedCount = 0;
while(! feof($fn) && $update) {
$pieces = explode("|", fgets($fn));
if(sizeof($pieces) == 9 && is_numeric(trim($pieces[1]))) {
if ($updatedCount == 0) {
$databaseInstance->beginTransaction();
}
$update = $this->model_products->update3s($pieces);
++$updatedCount;
if ($updatedCount > 500) { //in one transaction update 500 rows
$databaseInstance->commit();
$updatedCount = 0;
}
}
}
if ($updatedCount > 0) { // if we have not commited transaction
$databaseInstance->commit();
}
fclose($fn);
Some tips
Add index to field name
Use prepared statements
Disable the MySQL forgeign key check Read more
writing sql function can do that even in much lesser time .
using feature like :
REPLACE()
cursors
SPLIT_STRING(custom)
in a mysql user defined function
CREATE FUNCTION update3s(hole_file_content LONGTEXT) RETURNS Boolean
BEGIN
-----Your implementation(same logic in sql ) ------
END
then coll it just by if it is CI 3
$this->db->call_function('update3s', file_get_contents($this->upload->data('full_path')));
else
$this->db->query("select update3s(".file_get_contents($this->upload->data('full_path')).")");

escaping numbers in array index in php

I was not having any luck with searching so if this is a duplicate please let me know rather than downvoting.
I have a script for a game server that fills a database with the character data (name, level, userid and character type).
Rather than deleting the whole sql table each time and recreating it, I have it perform a check on the character data in the table and compare and only update whats different. it all works nicely.
However, A certain few character names are causing issues.
[09-Sep-2017 02:16:34 America/New_York] PHP Notice: Undefined index: 1OO4 in C:\Scripts\charlist.php on line 56
[09-Sep-2017 02:16:34 America/New_York] PHP Notice: Undefined index: 1zxx in C:\Scripts\charlist.php on line 56
That is this part of the script:
if ($current[$charName] !== $level) {
Where $current is an array of all the characters already in the database, I have it populate the array as Name => Level
The characters are in the database but they are not updating due to the error its throwing (as seen above) I tried wrapping $charName in "" but it did not work.
If anyone can provide advice it would be greatly appreciated.
entire script for reference, can see where i've fixed it in here.
<?php
$ClanServer = "";
$SodServer = '';
$UID = "";
$PWD = "";
$file = 'C:\account.txt';
$errlog = ini_get('php_errors');
$ConnInfo = array("UID"=>"$UID", "PWD"=>"$PWD", "CharacterSet" => "UTF-8");
$ClanConn = sqlsrv_connect($ClanServer, $ConnInfo);
$SodConn = sqlsrv_connect($SodServer, $ConnInfo);
if (!$SodConn) {
die('Connection Failed!');
} else {
echo "Connection Successful!<br />".PHP_EOL;
$query = "SELECT * FROM soddb.dbo.levellist";
$result = sqlsrv_query($SodConn, $query, array(), array('Scrollable' => 'buffered'));
$current = array();
$files = array();
while ($row = sqlsrv_fetch_array($result)) {
$name = $row['CharName'];
$current["'".$name."'"] = $row['CharLevel'];
}
$rootDir = realpath('C:/PT-Server/DataServer/userdata/');
$objects = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($rootDir), RecursiveIteratorIterator::SELF_FIRST);
foreach($objects as $name => $object){
if (substr($name, -4) == '.dat') {
$fOpen = fopen($name, "r");
$fRead = fread($fOpen,filesize($name));
/* details */
$charLevel = substr($fRead,0xc8,1);
$charClass = substr($fRead,0xc4,1);
$charName = trim(substr($fRead,0x10,16),"\x00");
$charID = trim(substr($fRead,0x2d0,16),"\x00");
$level = ord($charLevel);
#fclose($fOpen);
$files[] = $charName;
if ($charName == "")
{
unlink($name); // Delete char file with no name...
}
switch (ord($charClass)){
case 1: $class = 'Fighter'; break;
case 2: $class = 'Mechanician'; break;
case 3: $class = 'Archer'; break;
case 4: $class = 'Pikeman'; break;
case 5: $class = 'Atalanta'; break;
case 6: $class = 'Knight'; break;
case 7: $class = 'Magician'; break;
case 8: $class = 'Priestess'; break;
case 9: $class = 'Assassin'; break;
case 10: $class = 'Shaman'; break;
}
if (in_array("'".$charName."'",array_keys($current))) {
if ($current["'".$charName."'"] !== $level) {
$dbentry = "UPDATE soddb.dbo.levellist SET CharLevel='$level',CharClass='$class' WHERE CharName='$charName'";
$clanupdate = "UPDATE clandb.dbo.ul SET ChLv='$level' WHERE ChName='$charName'";
$enter = sqlsrv_query($SodConn, $dbentry);
sqlsrv_query($ClanConn, $clanupdate);
if ($enter) {
echo "Update $charName, $level successful!<br />".PHP_EOL;
}
}
} else {
$dbentry = "INSERT INTO soddb.dbo.Levellist ([ID], [CharName], [CharClass], [CharLevel]) VALUES ('$charID', '$charName', '$class', '$level') ";
$clanupdate = "UPDATE clandb.dbo.ul SET ChLv='$level' WHERE ChName='$charName'";
$enter = sqlsrv_query($SodConn, $dbentry);
sqlsrv_query($ClanConn, $clanupdate);
if ($enter) {
echo "Insert $charName, $level successful!<br />".PHP_EOL;
}
}
}
}
/* Remove deleted characters */
foreach ($current as $k => $v) {
if (!in_array($k, $files)) {
$query = "DELETE FROM soddb.dbo.levellist WHERE CharName='$k'";
sqlsrv_query($SodConn, $query);
}
}
sqlsrv_close($ClanConn);
sqlsrv_close($SodConn);
}
?>
I've worked it out,
where I push the names to the array ($current[$name] = $level;)
I encapsulated that with '' which treats its as a string number a number (where the name was starting with a number)
so its now $current["'".$name."'"] = $level; and i did the same further down
if (in_array("'".$charName."'",array_keys($current))) {
if ($current["'".$charName."'"] !== $level) {
do stuff
}
}
I've now run the script about 15 times to test and its not giving the issue at all.

sqlite3 replacement for sqlite_has_more

First of thank you for your help.
The code piece "while (sqlite_has_more($dres))" is using sqlite2 and I need sqlite3. If there isn't a replacement for has_more is there another code I can use to still Find whether or not more rows are available?
F.Y.I. The server updated their stuff which included their sqlite and now I have to fix this last peice of code to get the schedule to populate and not give me this error.
Fatal error: Non-static method SQLite3::open() cannot be called statically in /home/server/public_html/current-list.php on line 57
$row_num = 0;
if ($dbh = SQLite3::open($sked_path))
{
$qsql = "SELECT rowid,* FROM sked ORDER BY sk_dow_num, sk_time_start, sk_time_end";
$dres = SQLite3::query($dbh, $qsql);
if (SQLite3::num_Rows($dres) > 0)
{
$last_dow = "";
$last_start = "0000";
$last_end = "0000";
while (sqlite_has_more($dres))
{
$ska = Sqlite3Result::fetchArray($dres, SQLITE3_ASSOC);
$rid = $ska['rowid'];
$dow = $ska['sk_dow_name'];
$start = $ska['sk_time_start'];
$end = $ska['sk_time_end'];
$title = preg_replace("/<br\s*\/*>/", " ", $ska['sk_show_title']);
$show_dow = strtoupper($dow);
$show_start = strtoupper(formatTimeAmPm($start));
$show_end = strtoupper(formatTimeAmPm($end));
$show_style = "";
if (stristr($title, "Encore Show"))
$show_style = " class=\"$text_style\"";
Something like ...
<?php
$dbh = new SQLite3;
if ( !$dbh->open($sked_path) ) {
trigger_error('...error handling...', E_USER_ERROR);
}
else {
$dres = $dbh->query('
SELECT
rowid,*
FROM
sked
ORDER BY
sk_dow_num, sk_time_start, sk_time_end
');
if ( !$dres ) {
trigger_error('...error handling...', E_USER_ERROR);
}
else {
$ska = $dres->fetchArray(SQLITE3_ASSOC);
if ( !$ska ) {
onNoRecords();
}
else {
do {
doSomethingWithRowData($ska);
}
while( false!=($ska=$dres->fetchArray(SQLITE3_ASSOC)) );
}
}
}
(completely untested)

CodeIgniter Sqlite not working

Whenever I query my database (sqlite) like this in my model (im using codeigniter, full code below):
$this->db->select('post');
$query = $this->db->get('posts');
return $query->result_array();
I get the following error:
Fatal error: Call to a member function rowCount() on a non-object in /codeigniter/system/database/drivers/pdo/pdo_result.php on line 42
When changing the query to something nonexistent I get a "proper" error, something like:
A Database Error Occurred
Error Number: HY000
no such column: posst
SELECT posst FROM posts
Filename: /codeigniter/models/post.php
Line Number: 8
Which leads me to believe the database is actually working, but there is something I am missing.
I have tried recreating the database. It literally has 1 table with 1 column, but I just cannot get any data out. I also tried creating it with different "admin" programs but to no avail. I made sure it is an Sqlite 3 db, which is supported by the webserver according to phpinfo.
Does anybody have a clue where I am making a mistake?
-------- full code:
my post model in models/post.php
<?php
class Post extends CI_Model{
function get_posts(){
$this->db->select('posst');
$query = $this->db->get('posts');
return $query->result_array();
}
}
My controller in controller/posts.php :
<?php
class Posts extends CI_Controller{
function index(){
$this->load->model('post');
$data['posts']=$this->post->get_posts();
echo"<pre>";
print_r($data['posts']);
echo"</pre>";
}
}
My database config in database.php :
$active_group = 'default';
$active_record = TRUE;
$db['default']['hostname'] = 'sqlite:/home/******/******/www/wtp3/codeigniter/db/wtp35.sqlite';
$db['default']['username'] = '';
$db['default']['password'] = '';
$db['default']['database'] = '';
$db['default']['dbdriver'] = 'pdo';
$db['default']['dbprefix'] = '';
$db['default']['pconnect'] = TRUE;
$db['default']['db_debug'] = TRUE;
$db['default']['cache_on'] = FALSE;
$db['default']['cachedir'] = '';
$db['default']['char_set'] = 'utf8';
$db['default']['dbcollat'] = 'utf8_general_ci';
$db['default']['swap_pre'] = '';
$db['default']['autoinit'] = TRUE;
$db['default']['stricton'] = FALSE;
Credits for this fix are with S. Stüvel, J. Bransen and S. Timmer. This is a fix for a specific server, so YMMV. It did the trick for me though.
In pdo_driver.php, starting line 81 change:
empty($this->database) OR $this->hostname .= ';dbname='.$this->database;
$this->trans_enabled = FALSE;
$this->_random_keyword = ' RND('.time().')'; // database specific random keyword
}
to
if(strpos($this->database, 'sqlite') !== FALSE) {
$this->hostname = $this->database;
$this->_random_keyword = ' RANDOM()';
}
else {
$this->hostname .= ";dbname=".$this->database;
$this->_random_keyword = ' RND('.time().')'; // database specific random keyword
}
$this->trans_enabled = FALSE;
}
On line 189 change the entire function _execute($sql) to
function _execute($sql)
{
$sql = $this->_prep_query($sql);
$result_id = $this->conn_id->query($sql);
if (is_object($result_id))
{
$this->affect_rows = $result_id->rowCount();
}
else
{
$this->affect_rows = 0;
}
return $result_id;
}
Then in pdo_result.php change":
On line 29 change
public $num_rows;
to
var $pdo_results = '';
var $pdo_index = 0;
on line 36 replace entire function
public function num_rows()
{
if (is_int($this->num_rows))
{
return $this->num_rows;
}
elseif (($this->num_rows = $this->result_id->rowCount()) > 0)
{
return $this->num_rows;
}
$this->num_rows = count($this->result_id->fetchAll());
$this->result_id->execute();
return $this->num_rows;
}
with:
function num_rows()
{
if ( ! $this->pdo_results ) {
$this->pdo_results = $this->result_id->fetchAll(PDO::FETCH_ASSOC);
}
return sizeof($this->pdo_results);
Then on line 60 change
function num_fields()
{
return $this->result_id->columnCount();
}
to:
function num_fields()
{
if ( is_array($this->pdo_results) ) {
return sizeof($this->pdo_results[$this->pdo_index]);
} else {
return $this->result_id->columnCount();
}
}
Then on line 94 change:
function field_data()
{
$data = array();
try
{
for($i = 0; $i < $this->num_fields(); $i++)
{
$data[] = $this->result_id->getColumnMeta($i);
}
return $data;
}
catch (Exception $e)
{
if ($this->db->db_debug)
{
return $this->db->display_error('db_unsuported_feature');
}
return FALSE;
}
}
to:
function field_data()
{
if ($this->db->db_debug)
{
return $this->db->display_error('db_unsuported_feature');
}
return FALSE;
}
then line 146 change:
return FALSE;
to
$this->pdo_index = $n;
then on line 159 change
function _fetch_assoc()
{
return $this->result_id->fetch(PDO::FETCH_ASSOC);
}
to
function _fetch_assoc()
{
if ( is_array($this->pdo_results) ) {
$i = $this->pdo_index;
$this->pdo_index++;
if ( isset($this->pdo_results[$i]))
return $this->pdo_results[$i];
return null;
}
return $this->result_id->fetch(PDO::FETCH_ASSOC);
}
And finally on line 174 change:
function _fetch_object()
{
return $this->result_id->fetchObject();
to
function _fetch_object()
{
if ( is_array($this->pdo_results) ) {
$i = $this->pdo_index;
$this->pdo_index++;
if ( isset($this->pdo_results[$i])) {
$back = new stdClass();
foreach ( $this->pdo_results[$i] as $key => $val ) {
$back->$key = $val;
}
return $back;
}
return null;
}
return $this->result_id->fetch(PDO::FETCH_OBJ);
}
This worked for me. Again, not my work, credit goes out to S. Stüvel, J. Bransen and S. Timmer.
Rather long answer, but i hope this helps.
There is a bug in CodeIgniter version 2.1.0 for PDO drivers (They had just added PDO driver in version 2.1.0)
You can see change log for version 2.1.1
Please try upgrading your CodeIgniter.
I have Codeigniter 2.2.1 and when I set application/config/database.php the same as OP I can use sqlite database, sort of. I can create new database/file, create new tables and insert data. The problem is that I can't read any.
$query = $this->db->get('table_name');
return $query->result_array();
Returns empty array. The same happens when I do.
$query = $this->db->query("SELECT...");
Apparently there are still some bugs. I'm just starting to explore Codeigniter, but when I switch to mysql the same exact Model works as it should.
For the record, everything on my server is set up OK. I can use my sqlite databases just fine, it is just Codeigniter that has problems.
I applied g_m solution after updating from 2.1.3 to 2.2.6, and as jimmy, I had to remove the first change in pdo_driver.php to make it work.

Categories