ebean in play 2 framework with SQL dialect - sql

I'm trying to establish friendship between Teradata 13.10 and play 2 framework using ebean ORM layer. My app does try to query DB:
select t0.workflow_id c0, t0.CHNL_TYPE_CD c1, t0.WORKFLOW_NAME c2, t0.INFO_SYSTEM_TYPE_CD c3, t0.FOLDER_NAME c4 from ETL_WORKFLOW t0 order by name limit 11
The problem is... that Teradata does know nothing about LIMIT Is there any possibility to find implementation/override something and make underlying ORM work with Teradata?
UPD:
Seems like I have to do something with tese classes:
http://www.avaje.org/static/javadoc/pub/index.html
I'm looking for samples:
1. Set proper SQL dialect for ebean or make it work in SQL ANSI mode.
2. Override classes for ebean and write own implementation of LIMIT functionality.

Teradata supports both the TOP n operator and SAMPLE clause in your SELECT statement. TOP n being an extension to the ANSI SQL 2008 standard is the closest equivalent to the LIMIT n operator you are looking for.
TOP n is processed after all the other clauses in your SELECT statement have been satisfied. It is the functional replacement of using the QUALIFY ROW_NUMBER() or QUALIFY RANK() window aggregates to accomplish the same task providing at worst equivalent performance of the window aggregate functions.
SAMPLE provides you some additional flexibility by allowing you to returned multiple sample sets within a single result. It can also be used for simple, random samples from a resultset as well. Given the options that are available with SAMPLE you are best served with referring to the SQL Data Manipulation Language manual for Teradata for all of the details. The Teradata manuals can be downloaded from here. Just select which version of Teradata you wish to download the manuals for.
Edit:
Using the RawSQL feature with Ebean you may be able use either the SAMPLE or TOP n operators in your SQL explicitly and not allow Ebean to add expressions such as the LIMIT OFFSET clause automatically. Have you tried this approach yet?

Related

How to paginate results in Legacy SQL

We are using Legacy SQL on a specific request. We can't use standard SQL for some internal reasons.
We would like to paginate our results, because we have a lots of rows. Like that :
SELECT ... FROM ... LIMIT 10000 30000 // In standard SQL
But in Legacy SQL Offset don't exists. So how to do the same job ?
Edit :
I don't want to order. I want to paginate. For example get 1000 rows after skipping 2000 rows. A simple LIMIT clause with an offset, like in traditional SQL Database or like in BigQuery Standard SQL.
To do this, I want to use Big Query Legacy SQL.
The pagination you talking about is done via tabledata.list API
Based on your question and follow-up comments - It might be the way for you to go. Even though it does not involve querying. Just API or related method in client of your choice.
pageToken parameter allows you to page result
Btw, another benefit of this approach - it is free of charge
If you still need to do pagination via query - you option is using ROW_NUMBER()
In this case - you can prepare your data in temp table with below query
SELECT <needed fields>, ROW_NUMBER() OVER() num
FROM `project.dataset.table`
Then, you can page it using num
SELECT <needed fields>
FROM `project.dataset.temp`
WHERE num BETWEEN 10000 AND 30000

Programmatically detemine if a query is legacy or SQL 2011 syntax?

Hi is there a way to programmatically detect if a query string is in the legacy or SQL-2011 syntax? I know the former uses [project:dataset.table] for table references while the later uses `project.dataset.table` but this doesn't seem very bullet proof.
There's no way to tell just from the query text in all cases, which is why BigQuery has the "Use Legacy SQL" checkbox in the UI and the use_legacy_sql option for the query API. For example, consider this query:
SELECT *
FROM (SELECT 1 AS x), (SELECT 2), (SELECT 3);
The results are very different despite the query being valid in both dialects.
Standard SQL queries can still contain [], too, such as for array literals.
Assuming query is syntax-wise correct and expected to actually work - you can do Dry Run using both options (Legacy and Standard) and see which fails and which not. Based on result you can potentially derive the answer

Feature not implemented: WINDOW/ORDER BY

I am using an embedded Apache Derby database and execute the following query:
SELECT
someUniqueValue,
row_number() over(ORDER BY someUniqueValue) as ROWID
FROM
myTable;
someUniqueValue is a varchar.
I am getting the Exception:
java.sql.SQLFeatureNotSupportedException: Feature not implemented: WINDOW/ORDER BY
If i change the row_number() line in my query to:
row_number() over() as ROWID
The query runs fine (although the result is useless for me).
The Derby documentation states this is supported. What am I doing wrong?
The link you posted is just a draft to specify how the feature should be implemented.
If you scroll down a bit you find:
An implementation of the ROW_NUMBER() window function is included in Derby starting with the 10.4.1.3 release. Limitations and usage description may be found in the Derby Reference Manual
When you then look at Derby manual (your link is not the manual) http://db.apache.org/derby/docs/10.10/ref/rreffuncrownumber.html you'll find a list of limitations:
Derby does not currently allow the named or unnamed window specification to be specified in the OVER() clause, but requires an empty parenthesis. This means the function is evaluated over the entire result set.
The ROW_NUMBER function cannot currently be used in a WHERE clause.
Derby does not currently support ORDER BY in subqueries, so there is currently no way to guarantee the order of rows in the SELECT subquery. An optimizer override can be used to force the optimizer to use an index ordered on the desired column(s) if ordering is a firm requirement.

Are subqueries the only option to reuse variables?

I'd like to use MySQL in this form:
SELECT 1 AS one, one*2 AS two
because it's shorter and sweeter than
SELECT one*2 AS two FROM ( SELECT 1 AS one ) AS sub1
but the former doesn't seem to work because it expects one to be a column.
Is there any easier way to accomplish this effect without subqueries?
And no, SELECT 2 AS two is not an option. ;)
Considering this SQL code
SELECT 1 AS one, one*2 AS two
from the perspective of SQL the language (and why not; mysql has a good track record of compliance with the ISO/ANSI SQL Standards), your one is not a variable; rather it is a column correlation name. You cannot use the correlation name in the SELECT clause with the same scope, hence the error.
FWIW your 'shorter and sweeter' syntax does actually work when using the MS Access Database Engine -- is that where you learned it, perchance? Sadly, the Access Database Engine has a poor track record of compliance with the Standards. It is said to take a long time to un-learn Access-speak and learn SQL code ;)
select #one := 1 as one, 2 * #one as two;
user-defined variables

MS Access Limit

What's the equivalent of mysql Limit in ms access. TOP is not sufficient since I'm going to use it for pagination.
Thanks
There isn't one. Your best bet is to add an ID column as a primary key (if you don't already have one) and chunk output by looping through:
SELECT * FROM table
WHERE id >= offset AND id <= offset + chunk_size - 1
until you get all the rows.
Curiously, there are a few references in Microsoft documentation to a LIMIT TO nn ROWS syntax for the Access Database Engine:
ACC2002: Setting ANSI 92 Compatibility in a Database Does Not Allow DISTINCT Keyword in Aggregate Functions
About ANSI SQL query mode (MDB)
However, actual testing seems to confirm that this syntax has never existed in a release version of the Access Database Engine. Perhaps this is one of those features that the SQL Server team wanted to put into Jet 4.0 but were ordered to rollback by the Windows team? Whatever, it seem we must simply put it down to a bad documentation error that Microsoft won't take the time to correct :(
If you need to do pagination on the server** side then I suggest you consider a more capable, modern SQL product with better documentation ;)
** conceptually, that is: the Access Database Engine is not a server DBMS.
Since it doesn't appear that you have any type of sequencial unique key number for these rows, you'll need to create a ranking column: How to Rank Records Within a Query
You need to determine how many rows at a time you will return N = (10, 25,100).
You need to keep track of what "page" the user is on and the values of the first and last rank.
Then when you make the call for the next page it is either the next N rows that are > or < the first and last ranks (depending if the users is going to the previous or next page.).
I'm sure there is a way to calculate the last page, first page, etc.
Only way to achive paging SQL similar to Limit statement by using TOP keywords is as follows:
First Step:
sql = "select top "&LESS_COUNT&" * from (SELECT top "&(PAGE_COUNT*getPage)&" * FROM (SELECT "&COLUMNS&" FROM "&TABLENAME&") AS TBL "&getWhere&getOrderby("asc")&") as TBL "&getOrderby("desc")
Second step:
sql = "SELECT TOP "&PAGE_COUNT&" * FROM (" & sql & ") as TBL "&getOrderby("asc")
To summarize; you should re-order and make the results upside down for 3 times.
port your project to PHP & MySQL. Better support for these type of actions and queries and much much better online documentation. As a 16 year veteran DB developer, I have grown to dispise MS Access and MS SQL with a passion unmatched by anything else. This is due exclusively to their lack of support and documentation.