I actually get very mad about PHP and SQLite3 and the way some of my strings behave there.
I try to save opening hours but in strings instead of numeric to prevent problem with leading zeros (and still have it now haha... -.-).
Hours and minutes have their own column but when I insert '0x' the zero is gone and whatever x is, is left in the database. :/
Im sure im just missing some little damn part somewhere...
I already checked the INSERT-statement but found nothing at all.
Example for an insert string:
INSERT INTO opening INSERT INTO opening (start_day, end_day, start_hour, start_minute, end_hour, end_minute) VALUES('Montag', 'Freitag', '00', '00', '01', '00')
But the output is:
11|Montag|Freitag|0|0|1|0
Part of the Code:
class Database_Opening_Hours extends SQLite3{
function __construct() {
if(!file_exists("../../data/opening_hours/opening_hours.sqlite")){
$this->open("../../data/opening_hours/opening_hours.sqlite");
$this->exec('CREATE TABLE opening (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, start_day STRING, end_day STRING, start_hour STRING, start_minute STRING, end_hour STRING, end_minute STRING)');
}
else{
$this->open("../../data/opening_hours/opening_hours.sqlite");
}
}
}
$db = new Database_Opening_Hours();
$insert = "INSERT INTO opening (start_day, end_day, start_hour, start_minute, end_hour, end_minute) VALUES('".htmlspecialchars($_GET["start_day"])."','".htmlspecialchars($_GET["end_day"])."','".$start_hour."','".$start_minute."','".$end_hour."','".$end_minute."')";
if($db->exec($insert)){
$db->close();
unset($db);
echo "Insert erfolgreich";
}else{
$db->close();
unset($db);
echo "Nicht wirklich...";
}
Fairly sure that the type of your columns is set to an integer (or any other number type) instead of TEXT.
Make sure to double check the column data type and actually dump the table for us to check if it's really set to TEXT.
This is caused by SQLite using dynamic typing. From the FAQ:
This is a feature, not a bug. SQLite uses dynamic typing. It does not enforce data type constraints. Data of any type can (usually) be inserted into any column. You can put arbitrary length strings into integer columns, floating point numbers in boolean columns, or dates in character columns. The datatype you assign to a column in the CREATE TABLE command does not restrict what data can be put into that column. Every column is able to hold an arbitrary length string.
And from the linked page (emphasis mine):
In order to maximize compatibility between SQLite and other database engines, SQLite supports the concept of "type affinity" on columns. The type affinity of a column is the recommended type for data stored in that column. The important idea here is that the type is recommended, not required. Any column can still store any type of data. It is just that some columns, given the choice, will prefer to use one storage class over another. The preferred storage class for a column is called its "affinity".
So SQLite is dynamically casting your values to integer.
I would suggest combining start_hour and start_minute into start_time (the same for the end_ fields) and storing the value in the format 00:00.
SQLite will store this 'as-is' but is smart enough to recognise a time value and allow you to perform date/time operations:
select time(start_time, '+1 hour') from opening
I had this problem with C/C++ because I did not quote the strings:
insert into test values('aa', 'bb');
use varchar instead of string, I had the same problem then I used varchar(length) and it worked fine
Related
I get the error message SQLite3::exec(): unrecognized token: "'Date" when I insert a command into a SQLite database.
If I have the SQL commands echoed and execute them via the console, this also works. The data for this comes from a dbase database.
If I enter a string for fieldname the insert commands will work.
$field=unpack( "a11fieldname/A1fieldtype/Voffset/Cfieldlen/Cfielddec", substr($buf,0,18));
$db = new SQLite3('databases/test.db');
$sqlCode .= "INSERT INTO HEADER (name) VALUES ('".$field['fieldname']."');";
$db-> exec($sqlCode);
Would be that much easy to use prepare satement against sql injections
If I enter a string for fieldname the insert commands will work
make sure if fieldname is a text value
I am using pdo :
$sqlCode = "INSERT INTO header VALUES (:name)";
$query = $db->prepare($sqlCode);
$query->bindValue(':name', $field['fieldname'], SQLITE3_TEXT);
$result = $query->execute();
EDIT : Error says unrecognized token Date, So, if fieldname is a date you might need to change SQLITE3_TEXT to SQLITE3_BLOB OR SQLITE3_INTEGER Usualy not needed.
But you need to insert date into date column not into name column
EDIT 2 :
it's a bit complicated.
See here for a full description of the dbf file format.
So it would be best if you could use a library to read and write the dbf files.
If you really need to do this yourself, here are the most important parts:
Dbf is a binary file format, so you have to read and write it as binary. For example the number of records is stored in a 32 bit integer, which can contain zero bytes.
You can't use string functions on that binary data. For example strlen() will scan the data up to the first null byte, which is present in that 32 bit integer, and will return the wrong value.
If you split the file (the records), you'll have to adjust the record count in the header.
When splitting the records keep in mind that each record is preceded by an extra byte, a space 0x20 if the record is not deleted, an asterisk 0x2A if the record is deleted. (for example, if you have 4 fields of 10 bytes, the length of each record will be 41) - that value is also available in the header: bytes 10-11 - 16-bit number - Number of bytes in the record. (Least significant byte first)
The file could end with the end-of-file marker 0x1A, so you'll have to check for that as well.
See asked : binary safe write on file with php to create a DBF file
Final Word : you need DBF library
Data File Header Structure
How should I use MySQL's FROM UNIXTIME correctly in CDbMigration in Yii 1.x?
I have borrowed solution of converting current time given as timestamp, to MySQL's DateTime field from this answer and when just printing it:
echo 'FROM_UNIXTIME('.$base.')'."\n";
echo 'FROM_UNIXTIME('.$sixDaysLater.')'."\n";
everything seems fine:
FROM_UNIXTIME(1418223600)
FROM_UNIXTIME(1418742000)
But, when I'm trying to use the same technique as a part of my migration:
$this->insert('contents', array
(
'author_id'=>1,
'type'=>5,
'status'=>1,
'category'=>1,
'title'=>'title',
'body'=>'body',
'creation_date'=>'FROM_UNIXTIME('.$base.')',
'modification_date'=>'FROM_UNIXTIME('.$base.')',
'availability_date'=>'FROM_UNIXTIME('.$sixDaysLater.')',
'short'=>'short'
));
This fails -- that is, migration goes fine, but I can see in phpMyAdmin, that related fields for this record has been populated with zeros (0000-00-00 00:00:00), not with the expected value.
What am I missing? Is it, because values in insert are being encoded / escaped?
You can use CDBExpression instead:
new CDbExpression("NOW()");
I mean:
'creation_date'=>new CDbExpression("NOW()")
Or if you want to use FROM UNIXTIME you can do the same.
CDbExpression represents a DB expression that does not need escaping.
This may sound a little stupid but I need some help.I should save some records in the database as follow by accessing the following link:
http://localhost/whatsapp/index.php?r=users/create&mobile=012345678900
This is what I have in the controller:
public function actionCreate()
{
$model=new Users;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
echo "hello"." hii";
if(!isset($_POST['number']))
{
echo "aho";
$model->number="012345678900";
//$model->number=$_POST['number'];
echo 'bye';
//$model->attributes=$_POST['Users'];
if($model->save())
echo "done";
return "Doneeee";
}
}
The data is saved correctly except the column number.Always a certain number is saved as follows:
2147483647
Any dea why this is happening?!
Sql engine generate this kind of number when data type is not bigint and length of col is less than the length of number you entered.
In your Users table change the type of number to varchar and set its length to 15 or 20 or whatever you want.
Try this query
ALTER TABLE `users` CHANGE `number` `number` VARCHAR( 15 )
Note:- You are getting this problem because you have set your number field as int type. and the biggest value int type can hold is what you are getting in the database. So changing it to the varchar type will solve the problem.
A number starting with 0 is regarding as the OCTAL representation of the number
http://en.wikipedia.org/wiki/Octal
What is happening here is that the octal number, when represented as a "normal" or "decimal" number, gets to large, and overflows in the space provided (kind of like the mileage counter in a motor vehicle). Therefore, when the number gets saved, it gets converted into a number, then overflows.
The correct treatment is to regard this as a string, as suggested by #Let me see
i am using mysqlclient,
in one of my query, as shown below
sprintf (query, "select user from pcloud_session where id = '%s'", sid);
here some time this sid is with % sign in it like the example
2Cq%yo4i-ZrizGGQGQ71eJQ0
but when there is this % this query always fail, i think i have to escape this %, but how ?
i tried with \ and %% , but both of this not working, please help me here
UPDATE:
When using session.hash_bits_per_character = 6, in php session ,the default charset contains a character (comma) that will always be urlencoded(here it is %2C). This results in cookie values having this %2C in it, but session db having a comma instead of it. any idea about fixing this problem ?.. sorry for the confusion
Thanks
There's no need to escape a literal '%' in MySQL query text.
When you say the query "always fail", is it the call to the mysql_query function that is returning an error? Does it return a SQL Exception code, or is it just not returning the resultset (row) you expect?
For debugging, I suggest you echo out the contents of the query string, after the call to sprintf. We'd expect the contents of the string to be:
select user from pcloud_session where id = '2Cq%yo4i-ZrizGGQGQ71eJQ0'
And I don't see anything wrong with that SQL construct (assuming the id column exists in pcloud_session and is of character datatype. Even if id was defined as an integer type, that statement wouldn't normally throw an exception, the string literal would just be interpreted as integer value of 2.)
There should be no problem including a '%' literal into the target format of an sprintf. And there should be no problem including a '%' literal within MySQL query text.
(I'm assuming, of course, that sid is populated by a call to mysql_real_escape_string function.)
Again, I suggest you echo out the contents of query, following the call to sprintf. I also suggest you ensure that no other code is mucking with the contents of that string, and that is the actual string being passed as an argument to mysql_query function. (If you are using the mysql_real_query function, then make sure you are passing the correct length.)
UPDATE
Oxi said: "It does not return a SQL Exception code, it just does not return the result[set] I expect. I did print the query, it prints with % in it."
#Oxi
Here's a whole bunch of questions that might help you track down the problem.
Have you run a test of that query text from the mysql command line client, and does that return the row(s) you expect?
Is that id column defined as VARCHAR (or CHAR) with a length of (at least) 24 characters? Is the collation on the column set as case insensitive, or is it case sensitive?
show create table pcloud_session ;
(I don't see any characters in there that would cause a problem with characterset translation, although that could be a source of a problem, if your application is not matching the database charactarset encoding.)
Have you tested queries using a LIKE predicate against that id column?
SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq\%yo4i-%' ESCAPE '\\'
ORDER BY id LIMIT 10 ;
SELECT id, user FROM pcloud_session WHERE id LIKE '2Cq%'
ORDER BY id LIMIT 10 ;
Are you getting no rows returned when you expect one row? Are you getting too many rows returned, or are you getting a different row than the one you expect?
That is an oddball value for an id column. At first, it looks almost as if the value is represented in a base-64 encoding, but it's not any standard encoding, since it includes the '%' and the '-' characters.
If you're going to do this in C without an interface library, you must use mysql_real_escape_string to do proper SQL escaping.
There shouldn't be anything intrinsically wrong with using '%inside of a string, though, as the only context in which it has meaning is either directly inprintftype functions or as an argument toLIKE` inside of MySQL.
This proves to be really annoying, but it's absolutely necessary. It's going to make your code a lot more complicated which is why using low-level MySQL in C is usually a bad idea. The C++ wrapper will give you a lot more support.
You really shouldn't escape the string yourself. The safest option is to let the MySQL API handle it for you.
For a string of maximum length n, start by allocating a string of length 2*n+1:
int sidLength = strlen(sid);
// worst-case, we need to escape every character, plus a byte for the ASCIIZ
int maxSafeSidLength = sidLength * 2 + 1;
char *safeSid = malloc(maxSafeSidLength);
// copy "sid" to "safeSid", escaping as appropriate
mysql_real_escape_string(mysql, safeSid, sid, sidLength);
// build the query
// ...
free(safeSid);
There's a longer example at the mysql_real_escape_string page on dev.mysql.com, in which they build the entire query string, but the above approach should work for supplying safeSid to sprintf.
I have a table which contains an field zoneShape of the type Polygon.
When inserting some geometry in this field, in phpmyadmin it says: affected 1 row. The row is added, but the geometry field says it's size is 0B.
This is the Insertion code:
SET #g = 'POLYGON(50.866753 5.686455, 50.859819 5.708942, 50.851475 5.722675, 50.841611 5.720615, 50.834023 5.708427, 50.840744 5.689373, 50.858735 5.673923, 50.866753 5.686455)';
INSERT INTO zone SET zoneShape = PolygonFromText(#g)
As you can see; the first and last point are the same, so the polygon is closed.
Can anyone help me with adding this polygon to the database?
Thanx
It turns out that you need to add some extra brackets around the Points; because the standard uses an outside and inside line aka holes or islands.
So:
SET #g = 'POLYGON((50.866753 5.686455, 50.859819 5.708942, 50.851475 5.722675, 50.841611 5.720615, 50.834023 5.708427, 50.840744 5.689373, 50.858735 5.673923, 50.866753 5.686455))';
^ outside ^
INSERT INTO zone SET zoneShape = PolygonFromText(#g) doesn't look like a valid INSERT statement to me. Did you mean INSERT INTO zone (zoneShape) VALUES (PolygonFromText(#g));?