Using WSO2AM-2.1.0-update12 (carbon-apomgt tag v6.2.108) normally works well with mysql. We intend to switch the underlying database to Oracle DB (11g as far I know), looks simple.
Wen creating an API the apim throws an SQLException
ORA-00907: missing right parenthesis
we traced the exception to
org.wso2.carbon.apimgt.impl.dao.ApiMgtDAO:7652
executing following query:
SELECT
A.SCOPE_ID, A.NAME, A.DISPLAY_NAME,
A.DESCRIPTION, C.SCOPE_BINDING
FROM
((IDN_OAUTH2_SCOPE AS A INNER JOIN AM_API_SCOPES AS B ON A.SCOPE_ID = B.SCOPE_ID)
INNER JOIN IDN_OAUTH2_SCOPE_BINDING AS C ON B.SCOPE_ID = C.SCOPE_ID )
WHERE B.API_ID = 1;
Running this query itself against the APIM database indeed reproduces the exception, so the code hasn't been properly tested. For some customizations we rather try to fix the code if possible than migrate to a newer version (where we have no ensurance the issue is fixed or our customizations will work)
I suspect the query as been not tested as at all and correct query may look like
SELECT
A.SCOPE_ID, A.NAME, A.DISPLAY_NAME,
A.DESCRIPTION, C.SCOPE_BINDING
FROM
IDN_OAUTH2_SCOPE A INNER JOIN AM_API_SCOPES B ON A.SCOPE_ID = B.SCOPE_ID
INNER JOIN IDN_OAUTH2_SCOPE_BINDING C ON B.SCOPE_ID = C.SCOPE_ID
WHERE B.API_ID = 1;
I'd like to validate and correct me if the query is syntactically and semantically not equivalent
Could you please try the following?
SELECT A.SCOPE_ID, A.NAME, A.DISPLAY_NAME, A.DESCRIPTION, C.SCOPE_BINDING FROM ((IDN_OAUTH2_SCOPE A INNER JOIN AM_API_SCOPES B ON A.SCOPE_ID = B.SCOPE_ID) INNER JOIN IDN_OAUTH2_SCOPE_BINDING C ON B.SCOPE_ID = C.SCOPE_ID ) WHERE B.API_ID = ?
You can find this corrected query in https://github.com/wso2/carbon-apimgt/blob/6.x/components/apimgt/org.wso2.carbon.apimgt.impl/src/main/java/org/wso2/carbon/apimgt/impl/dao/constants/SQLConstants.java#L2068
Related
I had an issue with the LEft outer join and my query was little bit wierd. Tried searching for it , but did not get any clues.
This is happening due to were clause has been added.
The query below is not working as expected.
SELECT count(*) from
BN_DATA_TEMP.EDS_DELIVERYITEM_GBQ_SAMPLE_DATA A
LEFT OUTER JOIN BN_DATA_TEMP.TBL_EDS_DELIVERYITEMS_DATES B
on (
to_Date(substr(A.LASTUPDATEDTIME,1,10)) = '2020-05-31'
and to_Date(substr(B.LASTUPDATEDTIME,1,10)) = '2020-05-31'
and A.deliveryid = B.deliveryid )
where B.deliveryid is null;
Trying to get Records in A but not in B. But the count is very different and it is wrong.
I need to consider only the dates with 2020-05-31 from both the tables.
Modified like the below and it gave the correct result.
select count(*) from
(SELECT * from
BN_DATA_TEMP.EDS_DELIVERYITEM_GBQ_SAMPLE_DATA where to_Date(substr(LASTUPDATEDTIME,1,10)) = '2020-05-31' ) A
LEFT OUTER JOIN
(select * from
BN_DATA_TEMP.TBL_EDS_DELIVERYITEMS_DATES where to_Date(substr(LASTUPDATEDTIME,1,10)) = '2020-05-31' ) B
on A.deliveryid = B.deliveryid
where B.deliveryid is null;
I have never use much of Left outer joins for Data validation. So thought of posting over here and learn the same.
Thanks in Advance.
I have a Oracle command as
Select offers.OFR_STAT,OFFER_DETAILS.*,PrevData.*
From offers
INNER JOIN OFFER_DETAILS
ON OFFER_DETAILS.OFFER_ID=offers.OFFER_ID
INNER JOIN (
SELECT InnerOfrDtl.*
FROM OFFER_DETAILS as InnerOfrDtl
WHERE InnerOfrDtl.offer_id=offers.offer_id
) AS PrevData
ON PrevData.SCHEDULE_TYPE=OFFER_DETAILS.SCHEDULE_TYPE
While running I got an error message as "missing right parenthesis".
Here I wanted to use a sub-query for Inner join.
Try removing the AS after the close parenthesis and before PrevData. As I understand it, Oracle does not allow the keyword AS for table aliases.
The query does not require a sub-query. You could write:
SELECT o.OFR_STAT, d.*, p.*
FROM offers o
JOIN Offer_Details d ON d.Offer_ID = o.Offer_ID
JOIN Offer_Details p
ON p.Offer_ID = o.Offer_ID
AND p.Schedule_Type = d.Schedule_Type
I'm not wholly convinced that the query makes sense, but that's a different matter altogether.
Remove the AS keyword for the sub-query, this is not supported by Oracle:
Select offers.OFR_STAT,OFFER_DETAILS.*,PrevData.*
From offers
INNER JOIN OFFER_DETAILS
ON OFFER_DETAILS.OFFER_ID=offers.OFFER_ID
INNER JOIN (
SELECT InnerOfrDtl.*
FROM OFFER_DETAILS as InnerOfrDtl
WHERE InnerOfrDtl.offer_id=offers.offer_id
) PrevData -- <<<< here is the change
ON PrevData.SCHEDULE_TYPE=OFFER_DETAILS.SCHEDULE_TYPE
Older versions of Oracle (8i for sure, probably 9i too) have trouble with explicit INNER JOINs. Replacing them with implicit (non-ANSI?) inner joins can fix the problem.
https://forums.oracle.com/forums/thread.jspa?threadID=328028
I know there are lots of questions like these, but my question is not how to get rid of this error but to know how this worked earlier in 9-th version of Oracle.
I've got an old sources written in Ruby and Oracle DB which recently was upgraded to version=11.
I cannot edit data in Oracle DB, only read. so there are two tables lets say: table A(id, name, type, customer) and table B(id,a_id,type,person)
so. there is a query in the source code:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
so in Oracle 9 this worked perfectly but now i've got "column ambiguously defined" error.
What i'd like to know is:
where type = 'A'
is the same as
where a.type = 'A' AND b.type = 'A'
or
where a.type = 'A' OR b.type = 'A'
?
I think this was a bug with the ANSI style join. Use DBMS_XPLAN to find which table was being filtered in the old database.
Or better still, work out from the business logic what they query SHOULD have been.
No, and that's the problem: It could mean
where a.type = 'A'
or it could mean
where b.type = 'A'
with potentially different results; hence the error saying it is ambiguously defined.
I think you should test in Oracle 9 (where you say it works) and compare the output of the ambiguous query:
--- Base
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
with both the non-ambiguous ones:
--- QueryA
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
and:
--- QueryB
select a.id,b.id from a join b on a.id = b.a_id where b.type = 'A'
Something like this would do:
select a.id,b.id from a join b on a.id = b.a_id where type = 'A'
MINUS
select a.id,b.id from a join b on a.id = b.a_id where a.type = 'A'
(in short):
(Base)
MINUS
(QueryA)
and then:
(QueryA)
MINUS
(Base)
If both of the above MINUS queries return 0 rows, then BASE query is interpreted as QueryA.
Check similarly and compare Base with QueryB.
Another plausible reason for this error is that during (or about the same period with ) the migration, a type column was added in the 2nd table. Do you have old versions of the database tables' definitions to check that?
All - keep in mind there was a major change to the optimization engine for 11g. If you set your query optimizer level to 10.2.x on your 11g instance I bet the query would start working again.
That being said you should provide the alias for it so it's not ambiguous to the database server or the DBA / Developer coming behind you. :)
I need compute some join operations on my data, on the result of these operations I need to use a WHERE statement.
At the moment I use this syntax below, no errors, but result is not as expected.
For sure I need Group the result for my join and apply a query on it.
Could you please provide me an example of code? Unfortunately I'm pretty new at Linq and I'm not able to do it.
var myImagesForUser = from i in context.CmsImagesContents
join c in context.CmsContents on i.ContentId equals c.ContentId
join a in context.CmsAuthors on c.AuthorId equals a.AuthorId
join u in context.aspnet_Users on a.UserId equals u.UserId
where u.UserId == (Guid)myLoggedInUser.ProviderUserKey
select i;
Probably related data for current logged in user is not present in any one or more tables (Authors, Contents, ImagesContents) and you are not getting any result due to inner join on these tables. you can try outer join instead. Look at this article for left outer join in Linq queries
Hmm. I see two things which I would do different.
1.) You forgot to call .ToList() at the end in order to execute the query. Otherwise it can be, that you misuse the LINQ Statement in the processing afterwords.
var myImagesForUser = (YOUR LINQ STATEMENT).ToList();
2.) It's strange that you need to convert the UserKey to GUID. If really needed I would do it prior the LINQ Statement and check against a local variable.
var userId = (Guid)myLoggedInUser.ProviderUserKey;
var myImagesForUser = (YOUR LINQ STATEMENT ... where u.UserId == userId ).ToList();
Perhaps this helps you to get the expected result.
where a.UserId == (Guid)myLoggedInUser.ProviderUserKey.
I want to achieve the following in Linq to Entities:
Get all Enquires that have no Application or the Application has a status != 4 (Completed)
select e.*
from Enquiry enq
left outer join Application app
on enq.enquiryid = app.enquiryid
where app.Status <> 4 or app.enquiryid is null
Has anyone done this before without using DefaultIfEmpty(), which is not supported by Linq to Entities?
I'm trying to add a filter to an IQueryable query like this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where e.Applications.DefaultIfEmpty()
.Where(app=>app.Status != 4).Count() >= 1
select e);
Thanks
Mark
In EF 4.0+, LEFT JOIN syntax is a little different and presents a crazy quirk:
var query = from c1 in db.Category
join c2 in db.Category on c1.CategoryID equals c2.ParentCategoryID
into ChildCategory
from cc in ChildCategory.DefaultIfEmpty()
select new CategoryObject
{
CategoryID = c1.CategoryID,
ChildName = cc.CategoryName
}
If you capture the execution of this query in SQL Server Profiler, you will see that it does indeed perform a LEFT OUTER JOIN. HOWEVER, if you have multiple LEFT JOIN ("Group Join") clauses in your Linq-to-Entity query, I have found that the self-join clause MAY actually execute as in INNER JOIN - EVEN IF THE ABOVE SYNTAX IS USED!
The resolution to that? As crazy and, according to MS, wrong as it sounds, I resolved this by changing the order of the join clauses. If the self-referencing LEFT JOIN clause was the 1st Linq Group Join, SQL Profiler reported an INNER JOIN. If the self-referencing LEFT JOIN clause was the LAST Linq Group Join, SQL Profiler reported an LEFT JOIN.
Do this:
IQueryable<Enquiry> query = Context.EnquirySet;
query = (from e in query
where (!e.Applications.Any())
|| e.Applications.Any(app => app.Status != 4)
select e);
I don't find LINQ's handling of the problem of what would be an "outer join" in SQL "goofy" at all. The key to understanding it is to think in terms of an object graph with nullable properties rather than a tabular result set.
Any() maps to EXISTS in SQL, so it's far more efficient than Count() in some cases.
Thanks guys for your help. I went for this option in the end but your solutions have helped broaden my knowledge.
IQueryable<Enquiry> query = Context.EnquirySet;
query = query.Except(from e in query
from a in e.Applications
where a.Status == 4
select e);
Because of Linq's goofy (read non-standard) way of handling outers, you have to use DefaultIfEmpty().
What you'll do is run your Linq-To-Entities query into two IEnumerables, then LEFT Join them using DefaultIfEmpty(). It may look something like:
IQueryable enq = Enquiry.Select();
IQueryable app = Application.Select();
var x = from e in enq
join a in app on e.enquiryid equals a.enquiryid
into ae
where e.Status != 4
from appEnq in ae.DefaultIfEmpty()
select e.*;
Just because you can't do it with Linq-To-Entities doesn't mean you can't do it with raw Linq.
(Note: before anyone downvotes me ... yes, I know there are more elegant ways to do this. I'm just trying to make it understandable. It's the concept that's important, right?)
Another thing to consider, if you directly reference any properties in your where clause from a left-joined group (using the into syntax) without checking for null, Entity Framework will still convert your LEFT JOIN into an INNER JOIN.
To avoid this, filter on the "from x in leftJoinedExtent" part of your query like so:
var y = from parent in thing
join child in subthing on parent.ID equals child.ParentID into childTemp
from childLJ in childTemp.Where(c => c.Visible == true).DefaultIfEmpty()
where parent.ID == 123
select new {
ParentID = parent.ID,
ChildID = childLJ.ID
};
ChildID in the anonymous type will be a nullable type and the query this generates will be a LEFT JOIN.