How to parse json column in MySQL Version < 5.7 - mysql

I have a column called inventory.
id ..... inventory
the content of this column is:
{"STC1":{"count":"1"},"STC2":{"count":0}}
the count value is variable.
I don't want to use application side, I want to use sql.
for example
what I want:
... where STC1.count > 0
or
... where STC1.count > 1 or STC2.count < 5

You can't, according to the official MySQL website, the JSON support has been introduced for the 5.7.8 version, it isn't available natively for older versions.
For MySQL < 5.7.8, this JSON content is just a string, MySQL has nothing to extract structured data from it.
At best you'll be abble to check WHERE inventory LIKE '%"STC1":{"count":"0"%' to detect the row with a STC1 at 0 or something like that but not much more, and it will rapidly becoming really hairy to do anything complex.
In general it's better to store atomic data to avoid this kind of problem.

Related

Trying to store the data type "bit" in phpmyadmin. I keep getting 1111111111111111111111111111111 for 0 and 1111111111111111111111111111111 for 1

Trying to store the data type "bit" in phpmyadmin. I keep getting 1111111111111111111111111111111 for 0 and 1111111111111111111111111111111 for 1. I have tried four different import methods and two different viewing methods, but always the same error. (It wouldn't be such a problem if I got two different values, but they are both 1111111111111111111111111111111.)
What am I doing wrong? I just want to store some true/false values.
This seems to be an issue with your PHP version. If you are on PHP version 7.1.x, try upgrading to a later version of PHP. I just switched to version 7.4.4 and it fixes this problem - storing as 1 or 0 instead of 1111111111111111111111111111111.

TOS DI variable in tMySqlInput

I'm relatively new to Talend OSDI. I managed to do simple request in MySql with tMySqlInput component. However today I have a more ambitious request and have some trouble to make it work.
Indeed I need a request where the result depends on the previous line. I made it on MySQLWorkbench but not on Talend. Exemple : delay time between two dates.
Here is the request :
SET #var = NULL;
SELECT id, start_date, end_date, #var precedent, UNIX_TIMESTAMP(TIMEDIFF(start_date,#var)) AS diff, #var:=start_date AS temp
FROM ma_table
ORDER BY start_date;
and errors are :
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SELECT id, start_date, end_date, id_process_type, #var precedent, UNIX_TIMESTAMP' at line 2
...Not very usefull, Is this syntax forbidden on Talend ? Do it exists others solutions to do such requests on Talend ? (for delay time between two dates for examples) or other component maybe ? I am searching with tMysqlRow.
Thanks for ideas !
As #Gabriele B mentions, you might want to consider doing this in a more "Talend" way.
I'd personally make use of the tMemorizeRows component to do this though.
To simplify this I've gone and made the start and end dates as integers but it should be trivial to handle this using proper dates.
If we have some data that shows the start and end date of a process and we want to work out the delay between finishing the last one and starting the next process we can read all of the data in and then use the tMemorizeRows component to remember the last 2 rows:
We then access the memorized data by looking at the array index. So here we go to a tJavaRow component that has an extra output column, startdelay. We then calculate it by comparing the current process' start day minus the last process' end date:
output_row.id = input_row.id;
output_row.startdate = input_row.startdate;
output_row.enddate = input_row.enddate;
if (id_tMemorizeRows_1[0] != 1) {
output_row.startDelay = startdate_tMemorizeRows_1[0] - enddate_tMemorizeRows_1[1];
} else {
output_row.startDelay = 0;
}
The conditional statement it to avoid null pointer errors on the first run of the data as the enddate_tMemorizeRows_1[1] will be null at that point. You could handle the null in other ways of course.
This process is reasonably easy to understand and maintain (although there is that small bit of Java code in there) and has the benefits of only needing the load the data once and only keep a small part of it in memory at any one time. It should also be very fast.
You should consider a statement refactory to do it in a "Talend" way, maybe little slower but most portable and robust.
If your table is not huge, for example, I would recommend to load it in memory using tCacheOutput/tCacheInput (you can find them on Talend Exchange) and this design:
tMySqlLoad----->tCacheOutput_1
|
|
|
OnSubjobOk
|
|
v
tCacheInput_1------->tMap_1--------+
|
|
tJoin-------------->tMap_3------------>[output]
|
|
tCacheInput_2------->tMap_2--------'
First of all you dump your table on a memory buffer
Then, you read two times this buffer. It's in memory, so it won't hurt performances
In tMap_1 you add a auto_increment index using a Numeric.sequence
You do the same in tMap_2 but with a starting number of 2 (basically, you shift the index)
Then you auto-join the table using these brand new columns
Finally in tMap_3 you're going to release your payload (ie make the diff)
This is going to be a verbose but robust solution if your table is small. If it's not and performance is not a issue you can try an even more verbose solution like Prepared Statements.

Rails SQLite vs MySQL Booleans

I'm working with Rails 3.2. My development box is using SQLite3 and my production host is using MySQL. Rails SQLite ActiveRecord connector will not save booleans as 1 or 0 and will only save it as 't' or 'f'. Of course I want DB neutral code but I cannot find any way around the following. I have a user model and a shift model. In this query I need all the shifts (work schedules) and I need to order the results by the related table as well as apply the boolean conditions.
#sh= Shift.find(:all, :include=>:user, :order=>'users.rating DESC', :conditions=>["a1=1 or a1='t'"])
I have also learned about ActiveRecord::Base.connection.quoted_true and quoted_false. I suspect I could change them but that also seems non portable and would probably be silently overridden if I upgrade.
I don't want to test for both 1 and 't' (or 0 and 'f'). Is there any way around doing this besides changing my dev environment to mysql?
You should be able to pass the following as a conditions:
:conditions => [["a1 = ?", true]]

Drupal : How can I know if the db is mysql or postgres

I have a complicated query and since I need that my module work on both mysql and postgres, I need to write two version of it.
Unfortunately, I don't know how I can check if the db I use is mysql or postgres, to know which query use. Do you know if a function can return this value?
As #kordirko says, one option is to query the server version: SELECT version(); will work on both MySQL and PostgreSQL, though not most other database engines.
Parsing version strings is always a bit fragile though, and MySQL returns just a version number like 5.5.32 wheras PostgreSQL returns something like PostgreSQL 9.4devel on x86_64-unknown-linux-gnu, compiled by gcc (GCC) 4.7.2 20121109 (Red Hat 4.7.2-8), 64-bit. What do you do if you're connecting to a PostgreSQL-compatible database like EnterpriseDB Postgres Plus, or a MySQL-compatible database?
It's much safer to use the Drupal function for the purpose, DatabaseConnection::databaseType. This avoids a query round-trip to the DB, will work on databases that won't understand/accept SELECT version(), and will avoid the need to parse version strings.
You'll find this bug report useful; it suggests that the correct usage is Database::getConnection()->databaseType().
(I've never even used Drupal, I just searched for this).
As long as the abstract DatabaseConnection class extends PDO class, you can invoking pdo methods in order to know the current database driver.
For instance:
$conn = Database::getConnection();
print $conn->getAttribute($conn::ATTR_DRIVER_NAME); #returns mysql, pgsql...
There is a second way to do it using DatabaseConnection::driver():
print $conn->driver();
or DatabaseConnection::databaseType();
print $conn->databaseType();
Note that DatabaseConnection::driver() and DatabaseConnection::databaseType() are similar functions but not equals!
The return value from DatabaseConnection::driver() method depends on the implementation and other factors.
in the Drupal Database API page:
database.inc abstract public DatabaseConnection::driver()
This is not necessarily the same as the type of the database itself. For instance, there could be two MySQL drivers, mysql and mysql_mock. This function would return different values for each, but both would return "mysql" for databaseType().
In the most cases you just gonna want to use only
$conn->getAttribute($conn::ATTR_DRIVER_NAME)
or $conn->databaseType()
If you want get more specific properties, you should take advantage the PHP ReflectionClass features:
$conn = Database::getConnection();
$ref = new ReflectionClass($conn);
#ref->getProperties, ref->getConstants $ref->isAbstract...
Reference:
PDO::getAttribute
PDO::ATTR_DRIVER_NAME
Drupal Database API
Drupal Base Database API class

How can i repeat MySQL's WHERE 1 query in MongoDB?

I can do this in MySQL:
WHERE 1 AND 1 AND 1
How can i repeat it in MongoDB? What is MongoDB's equivalent for WHERE 1 ?
UPDATE:
So. I don't know how choose best answer ^^ and expanded question. As #mark-hillick noticed - i'm searching the best way to build query.
Now I'm using this way (express+mongoose):
//req.query - get/post object in Express
for (var q in req.query) {
if (req.query[q]) { //simplified example
query[q] = req.query[q];
};
}
Collection.find(query)
Your suggestions?
There is a SQL-MongoDB Mapping Chart here that you will find useful.
It has a tonne of examples on what you do within MongoDB when you want to do the same operation as "WHERE" in MySQL. For example -
SELECT a,b FROM users WHERE age=33
is
db.users.find({age:33}, {a:1,b:1})
or
SELECT * FROM users WHERE a=1 and b=1
is
db.users.find({a:1,b:1})
MongoDB is document oriented database and documents in MongoDB consists key-value pairs. So, in MongoDB you can't run single value query as you did in MySql. Assuming you hold your data in the field name a, similar query in MongoDB could be like :
db.test.find({$and : [{a:1},{a:1}, {a:1}]});
If' you're trying to build query clauses, AND is implicit in Mongo. Therefore, if you have the following;
db.col.find({name:"dave"})
you could just add another;
db.col.find({name:"dave", age:33})
and so on.