How to check version is greater than some base value? - mysql

When calling MySQL SELECT ##VERSION; or SELECT VERSION();, I get for instance '5.7.11-log'. Is there a "well-known" way to check if the version is greater (or smaller) than some major.minor.patch version? If not a well-known way, is there a way without using a temporary table or a user-defined function (there probably is, but for a reason or another currently eludes me)? I would use this to check if there's support for JSON type type that was introduced in version 5.7.8.
Upon researching this more, it appears this is a bit tougher nut for my skills to crack. For instance, I could write something like
SELECT
SUBSTRING_INDEX(##VERSION, '.', 1) AS major,
SUBSTRING_INDEX(SUBSTRING_INDEX(##VERSION,'.', 2), '.', -1) AS minor,
SUBSTRING_INDEX(SUBSTRING_INDEX(##VERSION,'.', -2), '.', -1) AS patch;
but that isn't entirely satisfactory (e.g. see -log) and it doesn't directly check the existence of the feature.
I cross-posted this to DBA overflow How to check if feature (JSON) exists, and/or version.

Use if condition with version
mysql> SELECT VERSION();
+-----------+
| VERSION() |
+-----------+
| 5.7.14 |
+-----------+
1 row in set (0.00 sec)
mysql> select if(VERSION() > '5.7.14' ,1,0);
+-------------------------------+
| if(VERSION() > '5.7.14' ,1,0) |
+-------------------------------+
| 0 |
+-------------------------------+
1 row in set (0.00 sec)
mysql> select if(VERSION() > '5.7.13' ,1,0);
+-------------------------------+
| if(VERSION() > '5.7.13' ,1,0) |
+-------------------------------+
| 1 |
+-------------------------------+
1 row in set (0.00 sec)

I'll cross reference the answer by Rick here. Specifically, there is special comments syntax in MySQL in which MySQL interprets a block of code either as effective MySQL SQL or as just a plain comments section. Here's a link to the documentation: http://dev.mysql.com/doc/refman/5.7/en/comments.html and a few notable examples:
SELECT /*!JSON_TYPE*/('["a", "b", 1]');
and
/*!40103 SET #OLD_TIME_ZONE=##TIME_ZONE */;.

Related

MySQL Point precision for large numbers (eg IPv6)

I am trying to do IPv6 address range matching using LineString and Point. But I believe this question is more related to how MySQL handles large number precision in general. (Note the following works without issues with smaller numbers, i.e. IPv4 decimal representation).
For IPv4, the ranges are defined as LineString(Point(-1, ip_start), Point(1, ip_end)).
I seem to be losing precision when creating a Point() with a large number, therefore my range matching is flawed.
MariaDB [mydb]> set #point=Point(0, 42541828702485584113142439188939931648);
Query OK, 0 rows affected (0.00 sec)
MariaDB [mydb]> select astext(#point);
+-------------------------------+
| astext(#point) |
+-------------------------------+
| POINT(0 4.254182870248558e37) |
+-------------------------------+
1 row in set (0.00 sec)
MariaDB [mydb]> select st_y(#point);
+----------------------+
| st_y(#point) |
+----------------------+
| 4.254182870248558e37 |
+----------------------+
1 row in set (0.00 sec)
MariaDB [mydb]> select cast(st_y(#point) as Decimal(39));
+----------------------------------------+
| cast(st_y(#point) as Decimal(39)) |
+----------------------------------------+
| 42541828702485580000000000000000000000 |
+----------------------------------------+
1 row in set (0.00 sec)
MariaDB [mydb]>
How can I use a Point() with large numbers accurately?
SPATIAL functions (st_x, point, etc) work with DOUBLEs, not DECIMAL.
DECIMAL(39) should work. But why not just keep it as a string or hex string (VARCHAR(39) CHARACTER SET ascii) or BINARY(16)?
Please explain your ultimate goal that led you to want to use Spatial tools.
Here is code to handle ranges of IP addresses (separate code for IPv4 or IPv6): http://mysql.rjweb.org/doc.php/ipranges

SQL query for detect columns with special characters?

here and in a lot of other websites I have find a lot of posts regarding this question but for some strange reason no one works.
I have a Wordpress database and I need to find all the terms contained in wp_terms that have any special character.
In fact I need to find all that contains anything else of number or letter.
Why this doesn't work? The MySQL query return 0 results.
SELECT * FROM wp_terms WHERE name LIKE '%[^0-9a-zA-Z ]%'
You can use REGEXP to find out this. Also the ^must be outside from [].
SELECT * FROM wp_terms WHERE name REGEXP '[^0-9a-zA-Z ]'
Test
MariaDB [(none)]> SELECT "Hello" REGEXP '[^0-9a-zA-Z ]' as resut;
+-------+
| resut |
+-------+
| 1 |
+-------+
1 row in set (0.00 sec)
MariaDB [(none)]> SELECT "-Hello" REGEXP '[^0-9a-zA-Z ]' as resut;
+-------+
| resut |
+-------+
| 0 |
+-------+
1 row in set (0.00 sec)
It does not work because MySQL supports the ANSI version of LIKE. The form that you are using is an extended form associated with SQL Server.
On the other hand, MySQL supports regular expressions which are much more powerful. The regular expression for what you want is:
WHERE name REGEXP '[^0-9a-zA-Z ]'
Note that regular expressions match the pattern anywhere in the string, so you do not need wildcards at the beginning and the end.

Mysql st_intersects + st_buffer doesn't work

I tried to test if a line is met in some distance from a point. St_distance just gives me what I want. However, I'm curious about st_intersects + st_buffer:
$ mysql --version
mysql Ver 14.14 Distrib 5.6.24, for Linux (x86_64) using EditLine wrapper
mysql> set #l4=st_geomfromtext('LINESTRING(50 50, 52 45)');
mysql> set #g4=st_geomfromtext('POINT(50 49)');
mysql> select st_distance(#l4, #g4);
--------------
select st_distance(#l4, #g4)
--------------
+-----------------------+
| st_distance(#l4, #g4) |
+-----------------------+
| 0.3713906763541037 |
+-----------------------+
1 row in set (0.00 sec)
I would think the point is very close to the line but obviously MySQL disagrees:
mysql> select st_intersects(st_buffer(#g4, 1), #l4);
--------------
select st_intersects(st_buffer(#g4, 1), #l4)
--------------
+---------------------------------------+
| st_intersects(st_buffer(#g4, 1), #l4) |
+---------------------------------------+
| 0 |
+---------------------------------------+
1 row in set (0.00 sec)
Why? Do I miss something?
P.S.
I have tried the commands above in H2GIS and it says it is indeed true!
ST_Intersects should return true in this case.
This appears to be the bug reported here: https://bugs.mysql.com/bug.php?id=71076, and fixed in MySQL 5.7.6, according to the release notes here: http://forums.mysql.com/read.php?3,629183,629183
"This work also corrected issues that [...], and that
ST_Intersects() sometimes incorrectly calculated the
result for intersections of LineString and Polygon."

Incorrect parameter count in the call to native function 'aes_decrypt'

I am trying to move our encryption from Code to the database to speed things up. When I attempt to decrypt the information using this select statement I get an incorrect parameter count error.
SELECT AES_DECRYPT(u.strFirstName,'usa2010') FROM EncryptingTest.tblUser u;
I've looked at the documentation and this should work. Can someone tell me what I am doing wrong??
EDIT
I have tried Restarting the MySQL Server to no avail. The server Version is 5.6.22
From the example you provided it seems ok. Can you see about casting it first?
SELECT CAST(AES_DECRYPT(u.strFirstName,'usa2010') AS CHAR(50)) FROM EncryptingTest.tblUser u;
Please check this link it has some great resources on the issue your facing...
http://mysqlblog.fivefarmers.com/2014/03/27/mysql-5-6-17-now-with-better-encryption/
EDIT - The actual fix
Using AES_ENCRYPT() or AES_DECRYPT() with block_encryption_mode set to a block cipher other than ECB will produce an error if the IV is not provided:
mysql> SET ##session.block_encryption_mode = 'aes-256-cbc';
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT HEX(AES_ENCRYPT('test', 'key'));
ERROR 1582 (42000): Incorrect parameter count in the call to native function 'aes_encrypt'
mysql> SELECT HEX(AES_ENCRYPT('test', 'key', RANDOM_BYTES(16)));
+---------------------------------------------------+
| HEX(AES_ENCRYPT('test', 'key', RANDOM_BYTES(16))) |
+---------------------------------------------------+
| 2EFBA8708925C1DF8B661E57938FAE5E |
+---------------------------------------------------+
1 row in set (0.00 sec)
Note that the IV isn’t itself stored in the resulting encrypted output – it’s an artifact that you’ll have to track separately to get the decrypted values back:
mysql> SET #iv = RANDOM_BYTES(16);
Query OK, 0 rows affected (0.01 sec)
mysql> SELECT HEX(AES_ENCRYPT('test', 'key', #iv));
+--------------------------------------+
| HEX(AES_ENCRYPT('test', 'key', #iv)) |
+--------------------------------------+
| 650CE9E699ECA922E09E80CEBE51BFC7 |
+--------------------------------------+
1 row in set (0.00 sec)
mysql> SELECT AES_DECRYPT(UNHEX('650CE9E699ECA922E09E80CEBE51BFC7'), 'key', #iv);
+--------------------------------------------------------------------+
AES_DECRYPT(UNHEX('650CE9E699ECA922E09E80CEBE51BFC7'), 'key', #iv) |
+--------------------------------------------------------------------+
| test |
+--------------------------------------------------------------------+
1 row in set (0.00 sec)

Should OPTIONAL User Settings be Lazy-Initialized into the DB or always created with a new registration?

Simple question: Should OPTIONAL User Settings be Lazy-Initialized into the DB or always created with a new registration?
A user can set additional settings which are optional, so should a row for that optional setting be created for every user upon registration or only created when a user makes use of those settings for the first time?
Lazy-Initialization saves space, so I'm leaning towards doing it this way, but I'm not sure if there are any drawbacks.
Do the lazy initialization. Here's why.. if you instead used default values for settings the user didn't actively choose, and then later the business rules changed to set the default to something else, you'd have users with what would appear to be non-default settings that they didn't actively choose.
Here is one particular drawback I ran into when using lazy initilization in MySQL. It all boils down to this quote from the MySQL docs:
User-defined variables are connection-specific.
First: The setup
Connect to your DB (in my case MySQL) Then create a simple function SetBarProperty() that sets the #bar property EXPLICITLY to the value passed to the function. The function itself simply returns the value passed to it.
$ mysql
mysql> DROP FUNCTION IF EXISTS SetBarProperty;
Query OK, 0 rows affected (0.01 sec)
mysql> DELIMITER $$
mysql> CREATE FUNCTION SetBarProperty( myValue INT(30) )
-> RETURNS INT(30)
-> DETERMINISTIC
-> READS SQL DATA
-> BEGIN
-> SET #bar := myValue;
-> RETURN myValue;
-> END $$
Query OK, 0 rows affected (0.01 sec)
mysql> DELIMITER ;
Now if we query for the #bar property, it will be NULL just as expected.
mysql> SELECT #bar;
+------+
| #bar |
+------+
| NULL |
+------+
1 row in set (0.00 sec)
Again, if we call the SetBarProperty(3); the result is just as expected.
mysql> SELECT SetBarProperty(3);
+-------------------+
| SetBarProperty(3) |
+-------------------+
| 3 |
+-------------------+
1 row in set (0.00 sec)
What do you think?
What do you think happens if we call the following query?
SELECT SetBarProperty(4), #bar;
You've guessed right! #bar is 4.
mysql> SELECT SetBarProperty(4), #bar;
+-------------------+------+
| SetBarProperty(4) | #bar |
+-------------------+------+
| 4 | 4 |
+-------------------+------+
1 row in set (0.00 sec)
And now the tricky part...
Disconnect from your DB server (this is very important):
Ctrl+C
Now re-connect and call the same query as before:
$ mysql
mysql> SELECT SetBarProperty(4), #bar;
+-------------------+------+
| SetBarProperty(4) | #bar |
+-------------------+------+
| 4 | NULL |
+-------------------+------+
1 row in set (0.00 sec)
Did you see what just has happened?
#bar was NULL and this is because it hasn't been initialized in the caller space of the function SetBarProperty().
If you disconnect from your DB and explicitly initialize the property BEFORE calling the function (that itself initializes it explicity) your query works just as expected:
Ctrl+C
$ mysql
mysql> SET #bar := NULL;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT SetBarProperty(4), #bar;
+-------------------+------+
| SetBarProperty(4) | #bar |
+-------------------+------+
| 4 | 4 |
+-------------------+------+
1 row in set (0.00 sec)
Recommendation
If you immediately use a property in a query just after you've called a function that modifies the same property you should initialize the property before calling the function.
I hope this helps!
Regards,
Konrad