Propel case-insensitive order by usage problem - sql-order-by

I have been looking around for days and couldnt find anything helpfull.
my problem is; I couldn't set criteria case-insensitive ORDER (A a b B D d). Because when I try to fetch my records from DB, its not ordering properly since ascii problems (A B C a b c )
I want to set my ORDER criteria like this;
Criterias::setCriterias(Array('ORDER' => 'UPPER(name)'));
But propel doesnt let me to use UPPER in setting criterias.
So I have to set it like this;
Criterias::setCriterias(Array('ORDER' => 'name'));
I found something that may help, this function is doing what i want;
setIgnoreCase(true)
A new problem is coming with this function. If I set ORDER criteria without WHERE, it will working like a charm. But if I set 'WHERE' and 'ORDER' together, propel will giving me error.
Fatal error: Uncaught exception
'PropelException' with message 'Unable
to execute SELECT statement []
[wrapped: Cannot fetch TableMap for
undefined table: ]' in
/usr/local/share/pear/propel/query/ModelCriteria.php:1153
Stack trace: #0
/usr/local/share/pear/propel/query/ModelCriteria.php(1019):
ModelCriteria->getSelectStatement(NULL)
Thanks.

This is fixed in Propel 1.6.x. I pushed a few tests to prove that: https://github.com/propelorm/Propel/commit/3fc74ccffb05931ec3187b0dcff77dce732ef325

Related

laravel unique() dont work with paginating

i'm facing with an issue in laravel 5.7.28, i'm trying to get records with all of my fields and paginate them , sadly i got a bug in my code that cause registering users with duplicate phone number(a user registered itself more than one time and of course i fix the bug ) , for now i'm facing with a scenario that i want to fetch my (non-duplicate) distinct users on their phone, and paginate them . here is wishful scenario :
$users = User::distinct('phone')
->doesntHave('carrierUsers')
->doesntHave('thirdparty')
->latest()->paginate(40);
it returns all users (with duplicate phone number), seems distinct function not affected , so i tried unique function :
$users = User::doesntHave('carrierUsers')
->doesntHave('thirdparty')
->latest()->paginate(40)->unique('phone');
it works (for getting non-duplicate) but break paginating functionality
and for
$users = User::doesntHave('carrierUsers')
->doesntHave('thirdparty')
->latest()
->unique('phone')
->paginate(40);
i got error for undefined function on builder , means it works on collections ,
also i tried groupBy (search whole the web for solution) , it makes me confused till when i use it
User::doesntHave('carrierUsers')->doesntHave('thirdparty')
->latest()->groupBy('phone')
->paginate(40);
i got SELECT list is not in GROUP BY clause, is that mean in every phrase in my select statement (for now is all ('*') ) i should use it in my groupBy ?
i mean i need all columns , how can i have all those column in groupBy clause ? whats that mean by the way ?
, error is telling : this is incompatible with sql_mode=only_full_group_by. is she making this happen ? how can i fix it ?
1) excuse me for my english
2) Thanks for reading whole this
3) pleasure to reply and help me
Problem 1: Use distinct
For distinct() method, passing parameters is not supporteds, so distinct(phone) will not works.
You can use ->select('phone')->distinct() instead. However, support unique column is selected.
Problem 2: Use Group By
So if you want to select all columns and unique one column, you can use group by.
And because you are using mysql 5.7+.
The ONLY_FULL_GROUP_BY and STRICT_TRANS_TABLES modes were added in MySQL 5.7.5.
So if you select all columns and group one column, you will get the only_full_group_by error.
There are two options can solve this problem.
Solution1:
Use ANY_VALUE()
User::doesntHave('carrierUsers')->doesntHave('thirdparty')
->latest()
->selectRaw('phone, ANY_VALUE(id) AS id, ANY_VALUE(username) AS username, ...')
->groupBy('phone')
->paginate(40);
Solution2:
In config/database.php configuration, set strict mode to false(This is not very safty):
'mysql' => [
'driver' => 'mysql',
...
'strict' => false,
],

How can I sum one column from the same table, to produce three different aggregates, using Sequel ORM?

My query is this:
DB[:expense_projects___p].where(:project_company_id=>user_company_id).
left_join(:expense_items___i, :expense_project_id=>:project_id).
select_group(:p__project_name, :p__project_id).
select_more{count(:i__item_id)}.
select_more{sum(:i__amount)}.to_a.to_json
which works.
However, payment methods include cash, card and invoice. So I would like to sum each of those for summary purposes to achieve a discrete total for payments by cash, card, and invoice repsectively. I included the following line into the query
select_more{sum(:i__amount).where(:i__mop => 'card')}.
and the error message was
NoMethodError - undefined method `where' for #<Sequel::SQL::Function:0x007fddd88b5ed0>:
so I created the dataset separately with
ds1 = expense_items.where(:mop=>'card', :expense_company_id=>user_company_id).sum(:amount)
and appended it, at the end of the original query, with
select_append{ds1}
which achieved partial success as the returned json is now:
{"project_name":"project 2","project_id":2,"count":4,"sum":"0.40501E3","?column?":"0.2381E2"}
as can be seen there is no name for this element which I need in order to reference it in my getJSON call. I tried to add an identifier by adding ___a
to the ds1 query as below
ds1 = expense_items.where(:mop=>'card', :expense_company_id=>user_company_id).sum(:amount___a)
but that failed.
In summary, is this the right approach and, in any case, how can I provide an identifier when doing a sequel sum query? In other words sum(:a_column).as(a_name)
Many thanks.
Dataset#sum returns the sum, not a modified dataset. You probably want something like:
ds1 = expense_items.where(:mop=>'card', :expense_company_id=>user_company_id).select{sum(:amount)}
select_append{ds1.as(:sum)}
I am not sure for approach ( better ask Jeremy Evans ) but it work.
You just change: .sum(... to .select_more{:amount___a).as(:desired_name)}
ds1 = expense_items.where(:mop=>'card', :expense_company_id=>user_company_id).select_more{:amount___a).as(:desired_name)}
and actually get that desired_name in db response.

Why do I get "ORA-00932: inconsistent datatypes: expected - got -" when using COLLECT() in a prepared statement?

I am using this query with the Perl DBI:
SELECT c.change_id
, COLLECT(t.tag) AS the_tags
FROM changes c
LEFT JOIN tags t ON c.change_id = t.change_id
WHERE c.project = ?
GROUP BY c.change_id
The DBI uses OCI to prepare this statement, bind the value I pass, and get the results. But Oracle, for some reason, does not like it. The error output is:
ORA-00932: inconsistent datatypes: expected - got - (DBD ERROR: error possibly near <*> indicator at char 41 in '
SELECT c.change_id
, <*>COLLECT(t.tag) AS the_tags
FROM changes c
LEFT JOIN tags t ON c.change_id = t.change_id
WHERE c.project = :p1
GROUP BY c.change_id
'
Not very informative. However, I can make this error go away not only by changing the call to COLLECT() also by replacing the placeholder with the actual value:
SELECT c.change_id
, COLLECT(t.tag) AS the_tags
FROM changes c
LEFT JOIN tags t ON c.change_id = t.change_id
WHERE c.project = 'tryoracle'
GROUP BY c.change_id
That version works perfectly. Why doesn't Oracle like the prepared statement with the COLLECT()?
In case it's any help, here is a trace of the OCI-related calls extracted via ora_verbose = 6 (h/t #bohica).
Finally got a solution to this issue, thanks to some digging by a user. The problem was not with the placeholder; why it worked without the placeholder on the VirtualBox image I have no idea. No, the issue was with the COLLECT(). Seems that both the values being collected need to be cast to a specific type, and the resulting array also needs to be cast to a pre-defined array data type. Just so happens that my code has a custom array type:
CREATE TYPE sqitch_array AS varray(1024) OF VARCHAR2(512);
So I'm able to get the query to work by casting the COLLECT() like so:
CAST(COLLECT(CAST(t.tags as VARCHAR2(512))) AS sqitch_array)

ElementAt() doesn't work in Linq to SubSonic

I have this query:
var iterator = criteria.binaryAssetBranchNodeIds.GetEnumerator();
iterator.MoveNext();
var binaryAssetStructures = from bas in db.BinaryAssetStructures
where bas.BinaryAssetStructureId == iterator.Current
select bas;
When I iterate over the binaryAssetStructureIds with a foreach loop no problems occur. When I try this
var binaryAssetStructure = binaryAssetStructures.ElementAt(0);
I get following error:
Unable to cast object of type 'System.Linq.Expressions.MethodCallExpression' to type 'SubSonic.Linq.Structure.ProjectionExpression'
First() for example does work... What am I missing here...
I don't know SubSonic at all, but FWIW a similar issue exists with the Entity Framework. In that case it boils down to the fact that there's no direct translation of ElementAt to SQL.
First() can be easily translated to SELECT TOP 1 FROM ... ORDER BY ..., but the same is not easily expressed for ElementAt.
You could argue that e.g. ElementAt(5) should be translated to SELECT TOP 5 FROM ... ORDER BY ... and then the first four elements simply discarded, but that doesn't work very well if you ask for ElementAt(100000).
In EF, you can partialle overcome this issue forcing the expression to be evaluated first, which can be done with calls to AsEnumerable, ToList or ToArray.
For example
var binaryAssetStructure = binaryAssetStructures.AsEnumerable().ElementAt(0);
I hope this helps although not explicitly directed at SubSonic.

Entity Framework - "Unable to create a constant value of type 'Closure type'..." error

Why do I get the error:
Unable to create a constant value of type 'Closure type'. Only
primitive types (for instance Int32, String and Guid) are supported in
this context.
When I try to enumerate the following Linq query?
IEnumerable<string> searchList = GetSearchList();
using (HREntities entities = new HREntities())
{
var myList = from person in entities.vSearchPeople
where upperSearchList.All( (person.FirstName + person.LastName) .Contains).ToList();
}
Update:
If I try the following just to try to isolate the problem, I get the same error:
where upperSearchList.All(arg => arg == arg)
So it looks like the problem is with the All method, right? Any suggestions?
It looks like you're trying to do the equivalent of a "WHERE...IN" condition. Check out How to write 'WHERE IN' style queries using LINQ to Entities for an example of how to do that type of query with LINQ to Entities.
Also, I think the error message is particularly unhelpful in this case because .Contains is not followed by parentheses, which causes the compiler to recognize the whole predicate as a lambda expression.
I've spent the last 6 months battling this limitation with EF 3.5 and while I'm not the smartest person in the world, I'm pretty sure I have something useful to offer on this topic.
The SQL generated by growing a 50 mile high tree of "OR style" expressions will result in a poor query execution plan. I'm dealing with a few million rows and the impact is substantial.
There is a little hack I found to do a SQL 'in' that helps if you are just looking for a bunch of entities by id:
private IEnumerable<Entity1> getByIds(IEnumerable<int> ids)
{
string idList = string.Join(",", ids.ToList().ConvertAll<string>(id => id.ToString()).ToArray());
return dbContext.Entity1.Where("it.pkIDColumn IN {" + idList + "}");
}
where pkIDColumn is your primary key id column name of your Entity1 table.
BUT KEEP READING!
This is fine, but it requires that I already have the ids of what I need to find. Sometimes I just want my expressions to reach into other relations and what I do have is criteria for those connected relations.
If I had more time I would try to represent this visually, but I don't so just study this sentence a moment: Consider a schema with a Person, GovernmentId, and GovernmentIdType tables. Andrew Tappert (Person) has two id cards (GovernmentId), one from Oregon (GovernmentIdType) and one from Washington (GovernmentIdType).
Now generate an edmx from it.
Now imagine you want to find all the people having a certain ID value, say 1234567.
This can be accomplished with a single database hit with this:
dbContext context = new dbContext();
string idValue = "1234567";
Expression<Func<Person,bool>> expr =
person => person.GovernmentID.Any(gid => gid.gi_value.Contains(idValue));
IEnumerable<Person> people = context.Person.AsQueryable().Where(expr);
Do you see the subquery here? The generated sql will use 'joins' instead of sub-queries, but the effect is the same. These days SQL server optimizes subqueries into joins under the covers anyway, but anyway...
The key to this working is the .Any inside the expression.
I have found the cause of the error (I am using Framework 4.5). The problem is, that EF a complex type, that is passed in the "Contains"-parameter, can not translate into an SQL query. EF can use in a SQL query only simple types such as int, string...
this.GetAll().Where(p => !assignedFunctions.Contains(p))
GetAll provides a list of objects with a complex type (for example: "Function"). So therefore, I would try here to receive an instance of this complex type in my SQL query, which naturally can not work!
If I can extract from my list, parameters which are suited to my search, I can use:
var idList = assignedFunctions.Select(f => f.FunctionId);
this.GetAll().Where(p => !idList.Contains(p.FunktionId))
Now EF no longer has the complex type "Function" to work, but eg with a simple type (long). And that works fine!
I got this error message when my array object used in the .All function is null
After I initialized the array object, (upperSearchList in your case), the error is gone
The error message was misleading in this case
where upperSearchList.All(arg => person.someproperty.StartsWith(arg)))

Resources