Know the result of 'insertIgnore' with Jetbrains Exposed - mysql

I'm using Jetbrains Exposed to interact with my MySQL 5.7 database.
The problem I have is with insertIgnore.
As I see it, there is no way of knowing the result of the statement. MySQL itself will return either 1 if a row was inserted, or 0 if it was ignored because of an error (in my case, duplicate key error).
But I can't see any way to see that from the result of the insert.
My code is basically just:
transaction(database) {
MyTable.insertIgnore {
it[uniqueColumn] = "foo"
}
}
Executed twice where uniqueColumn is unique. There is no difference in the results, although the first time is successful and the second time isn't.
It seems like an easy thing to have the resulted rows of that statement be represented somewhere, but I couldn't find anything myself or when googling.

I had a similar problem and I solved it using IntIdTable instead of Table
And insertIgnoreAndGetId instead of insertIgnore
Maybe it will help anyone

Related

Have MySQL return JSON keys which themselves contain certain values

The problem I am trying to solve is to have a MySQL query return the Keys within a JSON that has the value "stage":"Functioning". I've been trying to work this problem out for a while now but can't find a solution.
It's worth adding as well that there will be several JSONs within the database table.
One of the JSONs is as follows:
{
"1493510400":{
"stage":"Resting",
"dateAltered":"true"
},
"1508716800":{
"stage":"Functioning",
"dateAltered":"true"
},
"1522713600":{
"stage":"Functioning",
"dateAltered":"true",
"stageAltered":"true"
},
"1537315200":{
"stage":"Functioning",
"stageAltered":"true"
},
"1551916800":{
"stage":"Resting",
"stageAltered":"true"
},
"1566518400":{
"stage":"Resting",
"stageAltered":"true"
},
"1581120000":{
"stage":"Functioning"
},
"1595721600":{
"stage":"Resting"
}
}
Each level has a timestamp as its key. Within each level, there will always be a value for 'stage'. These are only ever going to be Resting or Functioning. From here, I need to create a query that will return all the keys (timestamps) that have a value "stage":"Functioning".
I've got SELECT JSON_KEYS(field_value) working fine and it returns an array of the timestamps but when I try adding on some WHERE statements, it fails to return anything.
Some of the queries I've tried are:
SELECT JSON_KEYS(field_value) WHERE JSON_EXTRACT(field_value, '$*.stage') = 'Functioning'
SELECT JSON_KEYS(field_value) WHERE JSON_CONTAINS(field_value, '{"stage":"Functioning"}', '$.stage')
I know I'm probably being an idiot here so apologies if this feels like a waste of time to people but I'm totally stumped right now.
Is what I'm trying to accomplish even possible within MySQL?
My current version of MySQL is 5.7.22
Thanks
I'm afraid your version doesn't support that functionality. If you can upgrade to MySQL 8.0.11, you can use JSON_TABLE, JSON_SEARCH or something similar, depending on your individual case (honestly no clue what exactly you want to achieve based on your post).

Force mysql to throw error if no rows deleted (trying to delete non-existent row)

I am using Perl DBI (execute_array), but I think that this is more of a mysql issue.
I am trying to DELETE a few rows, and ran into the issue that the command completes successfully with no errors, but my rows are not being deleted (modified rows returns 0E0, i.e., "zero but true", i.e., "0 rows deleted"). When I tried via PHPMyAdmin, the rows deleted with no issue. After some debugging and long blank stares at my screen, I realized that one of the columns I was using in my DELETE statement had been truncated when added, which explained why the row could not be found by my script, but PHPMyAdmin had no problems with it. However, this did not explain why I was not getting any errors.
So, I guess this is by design, but am wondering if there is a way to get mysql to raise an error when you try to delete something that is not there. I know I can check to see if the number of affected rows is the same as the number of tuples supplied, but this does not tell me which rows were successfully removed, and which tuples referred to non-existent rows (since I am using execute_array for this very purpose). Any ideas?
I found a workaround for my specific use-case, and am posting as an answer in case it is useful for someone else out there.
In the return for execute_array
$sth->execute_array( { ArrayTupleStatus => \#return_vector } )
It actually returns a "rows modified" value per row (when successful; when it fails the result is an array ref), so though it is not really an error, I can just check whether each given tuple execution modified non-zero rows (you need to use == not eq though, since the return is '0E0').
if (ref $return_vector[$i])
{ print "DELETE failed, reason: $return_vector[$i][1]"; }
elsif ($return_vector[$i] == 0)
{ print "DELETE failed, no rows matched tuples"; }
else
{ print "DELETE successful"; }

Same ID which occurs multiple times with SQL-IN Operator at rails

I use the following sql statement:
Keyword.where("id IN (#{params[:keyword_ids]})").order("find_in_set(id, '#{params[:keyword_ids]}')")
The Problem at this statement is that if "keyword id" hold the same id more than ones, the call returns it only ones.
But I need the same number(not fulfilled) as well as the same order(which is fulfilled with this statement) which occurs in the array, independent if the same id occurs more than ones.
How should I change that statement to fix.
Thanks, dot
Well, that's not a bug, it's a feature ;)
My first recommendation would be to sanitize your input. Passing params[:keyword_ids] directly to the database, despite the help that the Rails framework does, is prone to lead to some kind of vulnerability sooner or later.
Secondly, the easiest solution is probably to keep the query as is, convert the results to a map and map the input params to the result.
Sth like
keywords = Keyword.where('id IN (?)', checked_keyword_ids)
keyword_map = Hash[keywords.map { |kw| [kw.id, kw] }]
checked_keyword_ids.map { |id| keyword_map[id] }

MySQL Query Error Validation

I running a Mysql Query to select some data, Sometimes i get a error called
mysql_fetch_assoc() expects parameter 1 to be resource, boolean given
when i executed this following code,
$result = $this->db->execute($sql);
for ($i = 0; $data[$i + 1] = mysql_fetch_assoc($result); $i++);
array_pop($data);
how do i optimize this coding to prevent any errors ?
is there anything wrong with it ? should i ignore this error ?
That means that the query is buggy, whyever, most likely because you construct it using components from sources which you do not really check enough. A buggy statement throws an error (since no result can be computed). That error is returned as false instead of a mysql result ressource. Since you do not check if the query succeeded but blindly try to retrieve details from the result, you get this second error.
So there are four things you have to invest into:
you should always check if a query succeeded at all:
enclose your query into a conditional: if (FALSE!==($result=$this->db->execute($sql))) and only retrieve from the result ressource if that condition resolves to true.
make sure you really (really!) check all input data you use to construct your query. Checking here also means to encode and escape it correctly, also see point 4. for this.
in cases like this it is important to analyze what exactly it is that is going wrong. There is little sense in guessing what might be going wrong. So in addition to checking if the query succeeded at all (1.) you should also take a look at the error message mysql throws if this is not the case. Use the method mysql_error() for this. It is well documented just as every other function too.
you should rework your code and migrate from phps old, long deprecated mysql extension to either mysqli or PDO. Both are php extensions that offer more security against constructing buggy statements. Read about "prepared statements" and "parameter binding" for this.

Get Redmine custom field value to a file

I'm trying to create a text file that contains the value of a custom field I added on redmine. I tried to get it from an SQL query in the create method of the project_controller.rb (at line 80 on redmine 1.2.0) as follows :
sql = Mysql.new('localhost','root','pass','bitnami_redmine')
rq = sql.query("SELECT value
FROM custom_values
INNER JOIN projects
ON custom_values.customized_id=projects.id
WHERE custom_values.custom_field_id=7
AND projects.name='#{#project.name}'")
rq.each_hash { |h|
File.open('pleasework.txt', 'w') { |myfile|
myfile.write(h['value'])
}
}
sql.close
This works fine if I test it in a separate file (with an existing project name instead of #project.name) so it may be a syntax issue but I can't find what it is. I'd also be glad to hear any other solution to get that value.
Thanks !
(there's a very similar post here but none of the solutions actually worked)
First, you could use Project.connection.query instead of your own Mysql instance. Second, I would try to log the SQL RAILS_DEFAULT_LOGGER.info "SELECT ..." and check if it's ok... And the third, I would use identifier instead of name.
I ended up simply using params["project"]["custom_field_values"]["x"] where x is the custom field's id. I still don't know why the sql query didn't work but well, this is much simpler and faster.