Postgresql natural sort with numbers first - spring

In Postgres I need to sort text with natural order, but with one exception - if the string has only number, it should be placed at top.
So I need such order:
["98", "125", "134", "148", "265", "634", "1233", "5231", "1m1ds", "1m2", "1m3", "1n3", "1w3r", "2m3", "2n3ds", "9t6","12gh", "13jy","25hg", "123y", "des2", "nme", "wer5"]
I tried with this:
CREATE COLLATION IF NOT EXISTS numeric (provider = icu, locale = 'en#colNumeric=yes');
ALTER TABLE "baggage_belts" ALTER COLUMN "name" type TEXT COLLATE numeric;
and it is ok, but numbers are mixed into numbers+text:
[1m1ds, 1m2, 1m3, 1n3, 1w3r, 2m3, 2n3ds, 9t6, 12gh, 13jy, 25hg, 98, 123y, 125, 134, 148, 265, 634, 1233, 5231, des2, nme, wer5]
Anyone has knowledge is it possible make it works with "empty" numbers first?

Then you should add a second ORDER BY expression that checks for non-digits:
ORDER BY name ~ '[^[:digit:]]', name
This relies on FALSE < TRUE, and you can support it with a two-column index defined like the ORDER BY clause.

Finally, I resolved the problem by creating additional property into Entity with #Formula:
#Formula(value = "name ~ '[^[:digit:]]'")
public String nonDigitName;
and now I have
Sort.by(Sort.Direction.ASC, "nonDigitName", "name")
I have one more challenge. I would like to move this property to another class MySortClass and make my base entity class extends MySortClass. But when I moved the property, I have
Unable to locate Attribute with the the given name [nonDigitName] on this ManagedType [pl.ppl.szopl.app.baggagebelt.BaggageBeltEntity]
Is there any possibility to Sort by inherited fields?

Related

Incorrect sort of DB query results in micronaut project

I am passing this to the repository function:
Pageable.from(offset, limit).order(Sort.Order(orderBy, direction, true))
It works just fine if orderBy is the name of a String property. If I try to sort by a number property it will return the results ordered as:
1,
11,
12,
...
19,
2,
20,
21
Any suggestions on how to fix for the number ordering?
Doing the sort on the method name (such as findAllOrderByNameAsc) is not an option because this is a parameter that comes from the API. We need to support ordering by any property.
remove the ignoreCase=true parameter or pass it as false
Sort.Order(orderBy, direction, true)
you should use ignoreCase only on String fields

How to update table from JSON flowfile

I have a flow-files with the below structure
{
"PN" : "U0-WH",
"INPUT_DATE" : "44252.699895833335",
"LABEL" : "Marker",
"STATUS" : "Approved",
}
and I need to execute an update statement using some fields
update table1 set column1 = 'value' where pn=${PN}
I found convertJsonToSQL but am not sure how to use it in this case
You can use a processor namely ConvertjSONToSQL. Using this you can convert your json into an update query.
ConvertjSONToSQL Description
It takes the following parameters :
1. JDBC Connection Pool : Create a JDBC pool which takes DB connection information as input.
2. Statement Type : Here you need to provide type of statement you want to create. In your case its 'UPDATE'.
3. Table Name : Name of the table for which update query needed to be created
4. Schema Name : Name of the schema of your database.
5. Translate Field Names : If true, the Processor will attempt to translate JSON field names into the appropriate column names for the table specified. If false, the JSON field names must match the column names exactly, or the column will not be updated
6. Unmatched Field Behaviour : if an incoming JSON element has a field that does not map to any of the database table's columns, this property specifies how to handle the situation
7. Unmatched Column Behaviour : If an incoming JSON element does not have a field mapping for all of the database table's columns, this property specifies how to handle the situation
8. Update Keys : A comma-separated list of column names that uniquely identifies a row in the database for UPDATE statements. If the Statement Type is UPDATE and this property is not set, the table's Primary Keys are used. In this case, if no Primary Key exists, the conversion to SQL will fail if Unmatched Column Behaviour is set to FAIL. This property is ignored if the Statement Type is INSERT
Supports Expression Language: true (will be evaluated using flow file attributes and variable registry)
Read the description above and try to use the properties given. Detailed description of the processor is given in the link.
ConvertjSONToSQL Description

Scaffolding an Oracle table without an ID column in Grails

I'm creating a Grails 3 app with some tables from my Oracle 12c database scaffolded and while so far everything went fast, I came across one problematic table which doesn't have an ID column. It's just four VARCHAR2's. Also, in the Constraints tab of the Oracle SQL Developer, I don't see any of them defined as the Primary Key. How should one progress in such a scenario to successfully create a CRUD for this class?
I've tried telling Grails to use the row id as an ID but this only results in a "getLong not implemented for class oracle.jdbc.driver.T4CRowidAccessor" error when I try accessing the (to-be) scaffolded page. My code looks like this:
class AliasFrequencyDict {
String frequency
String unit
String description
String lang
static constraints = {
frequency maxSize: 10, sqlType: 'VARCHAR2'
unit maxSize: 1, sqlType: 'VARCHAR2'
description maxSize: 30, sqlType: 'VARCHAR2'
lang maxSize: 2, sqlType: 'VARCHAR2'
}
static mapping = {
sort 'frequency'
version false
id column: 'ROWID'
}
}
How should I solve this if I don't have an explicit ID column and I am not allowed to create one?
EDIT: So the only way I was able to progress so far was to use a composite key consisting of all the columns and then manually change the index view so that instead of this:
<f:table collection="${aliasFrequencyDict}" />
we now have this:
<f:table collection="${aliasFrequencyDictList}" properties="['frequency','unit','description','lang']"/>
This, however, doesn't let me access any of the existing entries or add new ones, as I guess I'd have to manually specify these properties there, too. It doesn't seem like it's nearly as easy to explicitly state them in the edit view, for example, as it is in the index, though (or to make the editing actually work, on top of that).
EDIT2: Also, from what I gathered, using ROWID isn't a good idea anyway. Oracle docs state:
Although you can use the ROWID pseudocolumn in the SELECT and WHERE
clause of a query, these pseudocolumn values are not actually stored
in the database. You cannot insert, update, or delete a value of the
ROWID pseudocolumn.
Thus, I'm out of ideas about how to progress :( Any help?

How to make doctrine ignore database column prefixes?

Typically i create my entities in symfony2/doctrine from this console commands :
$php app/console doctrine:mapping:import TestSiteBundle yml
$php app/console doctrine:generate:entities Test --path=src/
but my table columns have prefixes like this :
table: user
id_user
id_address (FK)
nm_name
dt_created
bl_active
and it generates entities like this :
$idUser
$idAdress
$nmName
$dtCreated
$blActive
how can i ignore my column prefixes ? do i need to change my entire database column names ?
I think you can add the name like this:
Doctrine\Tests\ORM\Mapping\User:
fields:
created:
name: dt_created
type: datetime
you can see:
http://www.doctrine-project.org/docs/orm/2.1/en/reference/yaml-mapping.html
https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/Driver/YamlDriver.php
Just so I understand, you want your database column name to be id_user and you want the entity property to be $user? If so, I don't think that's possible without doing some serious hacking of the core libraries. Basically you'd need to intercept the part that generates the entity properties and add your own rules on how to name them. You'd be much better off renaming your columns. IMHO, those prefixes are unnecessary. I would change id_user to user_id, nm_name to name, dt_created to created_at, and bl_active to is_active. Your column names and property names will not only match (this is a good thing) but they'll make more sense.
Hope this helps.
You can patch Doctrine to strip prefixes upon reverse engineering of your database.
Open this file in IDE: https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/Mapping/Driver/DatabaseDriver.php
Add method to class DatabaseDriver implements Driver :
private function deprefixFieldName( $fieldName ) {
return implode('_',array_slice(explode('_',$fieldName),1));
}
Edit method:
public function setFieldNameForColumn($tableName, $columnName, $fieldName)
{
/* ADD */ $fieldName = $this->deprefixFieldName($fieldName);
$this->fieldNamesForColumns[$tableName][$columnName] = $fieldName;
}
Edit method:
private function getFieldNameForColumn($tableName, $columnName, $fk = false)
{
/* ... */
/* ADD */ $columnName = $this->deprefixFieldName($columnName);
return Inflector::camelize($columnName);
}
My method is so simple because my prefixes are all consistent ( i took the idea from Media Wiki ), yours may be more complex.
Here's the actual patch taken by Git from working system, just in case i made a typo in description: http://pastebin.com/FHeTCUjZ ( i wonder if patches in posts are allowed).

Linq Query on int using string

I'm trying to query the unique reference number of a table using Linq to Entities. The ID is provided via a textbox and hence a string in my code. Obviously in the database table the field is an integer so I have tried using .ToString first and then .Contains in the same way you would with a varchar(). This doesn't seem to work, with the error coming from the .ToString method.
How do you do this? I have tried converting the textboxes content to an integer but this then means the user would have to enter the exact int instead of a partial number.
Many Thanks
I'm not sure why toString do not work for you. I've tried this to methods. Both returned answers:
List<int> ids = new List<int>() { 111, 211, 311, 422, 522, 622, 733, 833, 933 };
string query = "11";
var result = ids.Where(id => id.ToString().Contains(query));
var result2 = ids.ConvertAll<string>(i => i.ToString()).Where(id => id.Contains(query));
// Both return the first three items
int value;
if(int.TryParse(someTextString,out value))
{
//do work here using integer comparision with 'value'
}
Whatever do you mean by "partial" value? Whatever you are "adding" to the user supplied string, you can still do before you parse the value. Your explanation is not very clear.
If you are indeed trying to make a wildcard search, this will fail using Linq-to-entities against a DB int value. I doubt lte will make much sense of sometable.intvalue.ToString().Contains(). In this case, you might need to do some client side maths to figure out what ranges need retrieving, or to write a stored procedure that does the search at the SQL end..

Resources