Converting MS SQL function to MySQL function - mysql

I'm trying to convert this MS SQL function to MYSQL, but I'm having syntax error.
Error: Syntaz error: Unexpected 'int' (int)
MS SQL Function:
CREATE FUNCTION [dbo].[f_ConvertIPV6to4]
(#AddrIPV6 varchar(50))
RETURNS varchar(17)
AS
BEGIN
declare #ipv4 varchar(17)
set #ipv4 = (
select
cast(convert(int, convert(varbinary, '0x' + substring(substring(#AddrIPV6, (len(#AddrIPV6)-charindex(':', #AddrIPV6)) - 3, 4), 1, 2), 1)) as varchar(3)) + '.' +
cast(convert(int, convert(varbinary, '0x' + substring(substring(#AddrIPV6, (len(#AddrIPV6)-charindex(':', #AddrIPV6)) - 3, 4), 3, 2), 1)) as varchar(3)) + '.' +
cast(convert(int, convert(varbinary, '0x' + substring(substring(#AddrIPV6, (len(#AddrIPV6)-charindex(':', #AddrIPV6)) + 2, 4), 1, 2), 1)) as varchar(3)) + '.' +
cast(convert(int, convert(varbinary, '0x' + substring(substring(#AddrIPV6, (len(#AddrIPV6)-charindex(':', #AddrIPV6)) + 2, 4), 3, 2), 1)) as varchar(3))
)
return #ipv4
END
GO
MySQL Function:
CREATE FUNCTION f_ConvertIPV6to4
(p_AddrIPV6 varchar(50))
RETURNS varchar(17)
BEGIN
declare v_ipv4 varchar(17);
set v_ipv4 = (
select
cast(convert(int, convert(varbinary, Concat('0x' , substring(substring(p_AddrIPV6, (char_length(rtrim(p_AddrIPV6))-charindex(':', p_AddrIPV6)) - 3, 4), 1, 2)), 1)) as varchar(3)) + '.' +
cast(convert(int, convert(varbinary, Concat('0x' , substring(substring(p_AddrIPV6, (char_length(rtrim(p_AddrIPV6))-charindex(':', p_AddrIPV6)) - 3, 4), 3, 2)), 1)) as varchar(3)) + '.' +
cast(convert(int, convert(varbinary, Concat('0x' , substring(substring(p_AddrIPV6, (char_length(rtrim(p_AddrIPV6))-charindex(':', p_AddrIPV6)) + 2, 4), 1, 2)), 1)) as varchar(3)) + '.' +
cast(convert(int, convert(varbinary, Concat('0x' , substring(substring(p_AddrIPV6, (char_length(rtrim(p_AddrIPV6))-charindex(':', p_AddrIPV6)) + 2, 4), 3, 2)), 1)) as varchar(3))
)
return v_ipv4;
END
Please anyone help me regarding this.

Related

Exact strings in a column in SQL

I am trying to use mysql to solve the question below.
Any idea how should I make it work? Thank you.
Tried to use the code below but extracted duplicate strings in two columns and it's hard-code so it's not working..
SELECT itemid, SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 1), ',', -1) 'type one',
SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 2), ',', -1) 'type two',
SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 3), ',', -1) 'type three',
SUBSTRING_INDEX(SUBSTRING_INDEX(item_variation, ',', 4), ',', -1) 'type four'
FROM data
Question:
To extract items with more than 3 types
|itemid|shopid|item_name|item_type|price|stock|creation_date|
|1|10000|clothes|{}|5|100|27/1/2018|
|2|10000|dress|{Pink: 20, Black: 20, Grey: 20}|20|100|20/2/2018|
|3|10001|t-shirt|{S: 2, M: 2, L: 2, XL: 2}|2|50|1/1/2018|
|4|10002|socks|{us5.5: 1, us9: 1, us4.5: 1, us10: 1, us7: 1, us6: 1, us5: 1}|1|1000|4/1/2018|
|5|10002|Gloves|{S: 2, M: 2}|2|500|6/1/2018|
Expected result
|itemid |item_name |item_type|
|3 |t-shirt |{S: 2, M: 2, L: 2, XL: 2}|
|4 |socks |{us5.5: 1, us9: 1, us4.5: 1, us10: 1, us7: 1, us6: 1, us5: 1}|
This ought to do:
select itemid, item_name, item_type
from t
where length(item_type) - length(replace(item_type, ',', '')) >= 3;
You need a special case to tell 0 and 1 apart. It would not work if item_type contains ',' in either key or value of the json-like field (missing quoted around strings to be json).
You just need to count number of comma(,)>=3. Try below code:
SELECT
Itemid,Item_Name,Item_type
FROM myjson
where ROUND (
(
LENGTH(item_type)
- LENGTH( REPLACE ( item_type, ",", "") )
) / LENGTH(",")
)>=3

In Ssrs 2019, how are TaskMask and RoleFlags to be interpreted?

If you do SELECT * FROM Roles WHERE 1=1; in the Ssrs database catalog, you see stuff like this:
How does one interpret the values in "TaskMask" and "RoleFlags"? I've found partial information here and there across the 'Net, but nothing from Microsoft.
There's nothing really easily discoverable out there on the 'Net, so I went and decompiled the ReportingServicesLibrary.dll (I used "dnSpy") and searched until I found what I was looking for in the Microsoft.ReportingServices.Library.AuthzData class.
I discovered the following about the "Roles" table in the Ssrs database catalog:
The values stored in Roles.RoleFlags are actually just underlying values of the SecurityScope enum. They indicate which enum to use to interpret TaskMask.
The values stored in Roles.TaskMask correspond to the members of either the CatalogItemTaskEnum, CatalogTaskEnum, or ModelItemTaskEnum enums. A "1" means the member/setting is "on" and "0" means it's "off. Reading the string from left-to-right, each position (0-based) corresponds to the enum member's underlying value. If a position is missing on the right end, it's assumed that the setting is "off".
Warning
If you are going to use Sql to change a Role's TaskMask, don't UPDATE it directly. Instead, use the SetRolePropertiesAndInvalidatePolicies sproc. That takes care of setting the SecData.NtSecDescState column to 1 on all the existing policies that are linked to the Role (which marks the data as "dirty"). The next time the Ssrs ReportServer service checks for policy updates, it'll update the serialized (AceCollection) data stored in the SecData.NtSecDescPrimary column for all "dirty" records in that table---for your Authorization Extension. (That SecData data is what an Authorization extension is presented with when checking permissions/access.)
E.g.
Consider the built-in "Folder Viewer" role. Since RoleFlags is "0", that corresponds to SecurityScope.CatalogItem and means TaskMask is interpreted using CatalogItemTaskEnum. Next, since TaskMask is "000000100000000000", that means the they have the ViewFolders "task" permission, because the "1" is at position/index 6 (zero-based) in the TaskMask string, and the underlying value of CatalogItemTaskEnum.ViewFolders is 6 .
Code definitions
internal enum SecurityScope
{
CatalogItem,
Catalog,
ModelItem
}
internal enum CatalogItemTaskEnum
{
Invalid = 268435455,
ConfigureAccess = 0,
CreateLinkedReports,
ViewReports,
ManageReports,
ViewResources,
ManageResources,
ViewFolders,
ManageFolders,
ManageSnapshots,
Subscribe,
ManageAnySubscription,
ViewDataSources,
ManageDataSources,
ViewModels,
ManageModels,
ConsumeReports,
Comment,
ManageComments
}
internal enum CatalogTaskEnum
{
Invalid = 268435455,
ManageRoles = 0,
ManageSystemSecurity,
ViewSystemProperties,
ManageSystemProperties,
ViewSharedSchedules,
ManageSharedSchedules,
GenerateEvents,
ManageJobs,
ExecuteReportDefinitions
}
internal enum ModelItemTaskEnum
{
Invalid = 268435455,
ViewModelItems = 0
}
They've added items over the years. E.g. CatalogItemTaskEnum.Comment didn't exist in Ssrs2012.
Based on #Granger answer, here is SQL code that gives each permission separetly.
SELECT
r.*,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 1), 1) = '1', 1, 0) AS BIT) AS ConfigureAccess,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 2), 1) = '1', 1, 0) AS BIT) AS CreateLinkedReports,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 3), 1) = '1', 1, 0) AS BIT) AS ViewReports,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 4), 1) = '1', 1, 0) AS BIT) AS ManageReports,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 5), 1) = '1', 1, 0) AS BIT) AS ViewResources,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 6), 1) = '1', 1, 0) AS BIT) AS ManageResources,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 7), 1) = '1', 1, 0) AS BIT) AS ViewFolders,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 8), 1) = '1', 1, 0) AS BIT) AS ManageFolders,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 9), 1) = '1', 1, 0) AS BIT) AS ManageSnapshots,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 10), 1) = '1', 1, 0) AS BIT) AS Subscribe,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 11), 1) = '1', 1, 0) AS BIT) AS ManageAnySubscription,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 12), 1) = '1', 1, 0) AS BIT) AS ViewDataSources,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 13), 1) = '1', 1, 0) AS BIT) AS ManageDataSources,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 14), 1) = '1', 1, 0) AS BIT) AS ViewModels,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 15), 1) = '1', 1, 0) AS BIT) AS ManageModels,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 16), 1) = '1', 1, 0) AS BIT) AS ConsumeReports,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 17), 1) = '1', 1, 0) AS BIT) AS Comment,
CAST(IIF(r.RoleFlags = 0 AND RIGHT(LEFT(r.TaskMask + '0', 18), 1) = '1', 1, 0) AS BIT) AS ManageComments,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 1), 1) = '1', 1, 0) AS BIT) AS ManageRoles,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 2), 1) = '1', 1, 0) AS BIT) AS ManageSystemSecurity,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 3), 1) = '1', 1, 0) AS BIT) AS ViewSystemProperties,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 4), 1) = '1', 1, 0) AS BIT) AS ManageSystemProperties,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 5), 1) = '1', 1, 0) AS BIT) AS ViewSharedSchedules,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 6), 1) = '1', 1, 0) AS BIT) AS ManageSharedSchedules,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 7), 1) = '1', 1, 0) AS BIT) AS GenerateEvents,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 8), 1) = '1', 1, 0) AS BIT) AS ManageJobs,
CAST(IIF(r.RoleFlags = 1 AND RIGHT(LEFT(r.TaskMask + '0', 9), 1) = '1', 1, 0) AS BIT) AS ExecuteReportDefinitions,
CAST(IIF(r.RoleFlags = 2 AND RIGHT(LEFT(r.TaskMask + '0', 1), 1) = '1', 1, 0) AS BIT) AS ViewModelItems
FROM dbo.Roles r

Mysql month number to month name conversion

I have month value like "22018" in my column I need it like Feb-2018 in mysql workbench
You need to first extract the month from the date (considering it will have one or two digits), e.g.:
SELECT LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0');
This will give you 02. Now, you can extract the year with similar logic, e.g.:
SELECT SUBSTRING('22018', LENGTH('22018') - 4 + 1, LENGTH('22018'));
Finally, you can concatenate all these to get a string like 2018-02-01:
SELECT CONCAT(SUBSTRING('22018', LENGTH('22018') - 4 + 1, LENGTH('22018')),
'-',
LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0'), '-01');
Once this is done, you can use DATE_FORMAT function to get the required output:
SELECT DATE_FORMAT(CONCAT(SUBSTRING('22018', LENGTH('22018') - 4 + 1,
LENGTH('22018')),
'-',
LPAD(SUBSTRING('22018', 1, LENGTH('22018') - 4), 2, '0'), '-01'), '%M-%Y');

oracle11g regexp_replace for json

I have select:
select regexp_replace(regexp_substr('[{"date": "01_2016", "val":"100_22"},{"date": "02_2016","val": "200.10"}]'
,'"val":\s*("(\w| )*")', 1, level)
,'"val":\s*"((\w| )*)"', '\1', 1, 1) val
from dual
connect by regexp_substr('[{"date": "01_2016", "val":"100_22"},{"date": "02_2016","val": "200.10"}]', '"val":\s*("(\w| )*")', 1, level) is not null
;
If my value have format 100_10 it is ok. But I want 100.10 and this select not support this. How to write regexp_replace?
Use (\d+)_(\d+) to match only the numeric values separated by an underscore:
SELECT REGEXP_REPLACE(
'[{"date": "01_2016", "val":"100_22"},{"date": "02_2016","val": "200.10"}]',
'"val":"(\d+)_(\d+)"',
'"val":"\1.\2"'
)
FROM DUAL;
Thanks everybody. I found the solution
select regexp_replace(regexp_substr('[{"date": "01-2016", "val":"100.22"},{"date": "02-2016","val": "200.10"},{"date": "03-2016","val": "200.15"}]','"val":\s*("(\w|[..])*")', 1, level),'"val":\s*"((\w|[..])*)"', '\1', 1, 1) val, regexp_replace(regexp_substr('[{"date": "01-2016", "val":"100.22"},{"date": "02-2016","val": "200.10"},{"date": "03-2016","val": "200.15"}]' ,'"date":\s*("(\w|[-])*")', 1, level) ,'"date":\s*"((\w|[-])*)"', '\1', 1, 1) date_period from dual connect by regexp_substr('[{"date": "01-2016", "val":"100.22"},{"date": "02-2016","val": "200.10"},{"date": "03-2016","val": "200.15"}]', '"val":\s*("(\w|[..])*")', 1, level) is not null

How to format uuid string from binary column in MySQL/MariaDB

In MySQL/MariaDB the most efficient way to store uuid is in a BINARY(16) column. However, sometimes you want to obtain it as a formatted uuid string.
Given the following table structure, how would I obtain all uuids in a default formatted way?
CREATE TABLE foo (uuid BINARY(16));
The following would create the result I was after:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
FROM foo;
MySQL 8 adds two new UUID functions:
UUID_TO_BIN
BIN_TO_UUID - this is the one you're looking for
So:
SELECT BIN_TO_UUID(uuid) FROM foo
In earlier (prior to 8) versions you can create a function in MySQL like the following:
CREATE
FUNCTION uuid_of(uuid BINARY(16))
RETURNS VARCHAR(36)
RETURN LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
));
And then simply use it in your queries:
SELECT
uuid_of(id)
name,
age
FROM users
And it produces:
(c6f5703b-fec2-43fd-8f45-45f06583d450, Some name, 20)
If you are looking for the opposite, i.e., how to convert from string to binary, perhaps to do a join or something, this is covered here : Convert UUID to/from binary in Node
This piece of SQL run on Mysql 5.7 helped lock in the concept for me:
SELECT
LOWER(CONCAT(
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 1, 8), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 9, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 13, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 17, 4), '-',
SUBSTR(HEX(UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', ''))), 21)
))
The output is 43d597d7-2323-325a-90fc-21fa5947b9f3.
string -> binary
So UNHEX(REPLACE('43d597d7-2323-325a-90fc-21fa5947b9f3', '-', '')) to convert a UUID to binary during an INSERT / UPDATE / JOIN / SELECT whatever, and
binary -> string
LOWER(CONCAT(
SUBSTR(HEX(uuid), 1, 8), '-',
SUBSTR(HEX(uuid), 9, 4), '-',
SUBSTR(HEX(uuid), 13, 4), '-',
SUBSTR(HEX(uuid), 17, 4), '-',
SUBSTR(HEX(uuid), 21)
))
The correct result is generated by the script below, the other scrips generated a UUID however not the right one.
CONCAT(
substr(hex(Id), 7, 2), substr(hex(Id), 5, 2), substr(hex(Id), 3, 2), substr(hex(Id), 1, 2), '-'
, substr(hex(Id), 11, 2) , substr(hex(Id), 9, 2) , '-'
, substr(hex(Id), 15, 2) , substr(hex(Id), 13, 2) , '-'
, substr(hex(Id), 17, 4) , '-'
, substr(hex(Id), 21, 12)
)
Results running the other scripts generated wrong UUID as per below:
Expected UUID - 2e9660c2-1e51-4b9e-9a86-6db1a2770422
What was generated - c260962e-511e-9e4b-9a86-6db1a2770422
As you can see they are different.
Here's an alternative using concat_ws
Store raw uuid in a variable #x
SELECT #x := hex(uuid)
FROM foo;
Use CONCAT_WS and SUBSTR to parse human readable UUID
SELECT
LOWER(CONCAT_WS('-',
SUBSTR(#x, 1, 8),
SUBSTR(#x, 9, 4),
SUBSTR(#x, 13, 4),
SUBSTR(#x, 17, 4),
SUBSTR(#x, 21)
)) AS uuid;
According to this Jira ticket https://jira.mariadb.org/browse/MDEV-15854 UUID_TO_BIN and BIN_TO_UUID did not make into the Mariadb Server release 10.5. If you are using this version and under of Mariadb Server you will have to use a custom implementation mentioned above.