Re: SQL enhancement request (GROOVY-11342)

2024-03-31 Thread Paul King
On Sat, Mar 30, 2024 at 6:21 AM  wrote:
> Do you have any thoughts around when this enhancement might come out in a 
> release?

Probably in the next couple of weeks pending feedback.

Paul.


RE: SQL enhancement request (GROOVY-11342)

2024-03-29 Thread steve.etchelecu
Ah, ok, so I wasn’t missing anything, it would just have to be added to the 
language.  

 

I’m just super happy to be getting the metadata with the sql execute so …  :)

 

-Steve

 

From: MG  
Sent: Friday, March 29, 2024 8:18 PM
To: users@groovy.apache.org; steve.etchel...@gmail.com
Subject: Re: SQL enhancement request (GROOVY-11342)

 

That would be eachRowWithIndex, which would imho be nice to have here, as well 
as for collect (i.e. collectWithIndex)... ;-)

Cheers,
mg



On 29/03/2024 19:17, steve.etchel...@gmail.com 
<mailto:steve.etchel...@gmail.com>  wrote:

Basically there's no way to get eachRow() to provide a counter...
 



Re: SQL enhancement request (GROOVY-11342)

2024-03-29 Thread MG
That would be eachRowWithIndex, which would imho be nice to have here, 
as well as for collect (i.e. collectWithIndex)... ;-)


Cheers,
mg


On 29/03/2024 19:17, steve.etchel...@gmail.com wrote:

Basically there's no way to get eachRow() to provide a counter...


RE: SQL enhancement request (GROOVY-11342)

2024-03-29 Thread steve.etchelecu
Paul,

I was able to download the Groovy snapshot and get it to work.  The new 
metadata support in execute() looks like it is working smoothly for me.  Nice 
learning day for me!

Do you have any thoughts around when this enhancement might come out in a 
release?

Thanks,
Steve

-Original Message-
From: steve.etchel...@gmail.com  
Sent: Friday, March 29, 2024 1:17 PM
To: users@groovy.apache.org
Subject: RE: SQL enhancement request (GROOVY-11342)

Thanks Paul!  I thought that eachrow iteration issue had something to do with 
eachRow() possibly not returning a List but when I saw it returned something 
that looked like Proxy$10 I got lost as I didn't know how to understand that.  
Normally I would try to look up the definition of the object, like when you 
previously explained the subtleties between ResultSet and GroovyResultSet.  The 
fix worked smoothly (of course) -- indices() was a new one for me.

--- eachRow():
row: 0
  column 0: column COL1='3' (width=11, type=4)
  column 1: column COL2='13' (width=11, type=4)
row: 1
  column 0: column COL1='2' (width=11, type=4)
  column 1: column COL2='12' (width=11, type=4)
row: 2
  column 0: column COL1='1' (width=11, type=4)
  column 1: column COL2='11' (width=11, type=4)

I went through the snapshot process and it downloaded a zip file - it looks 
like it is a Groovy 5 version, does that mean that this fix will be available 
via a release once version 5 releases?

I've seen the Groovy 5 alpha releases and have been interested in the next 
major release of Groovy.  I wasn't sure how stable the alpha releases are so 
I've stayed with version 4 up to this point.  Any idea when Groovy 5 might 
release?

Oh!  Any idea why the SQL that doesn't produce resultSets doesn't fail with 
eachRow() and rows() for hsqldb (only)?  That one threw me for a loop.  The 
only thing I can think of is that the hsqldb driver does produce a (empty) 
resultSet.

Finally (a little Java humor) - with eachRow() am I correct in thinking that my 
rowid handling is the only way to handle it if I want row numbers displayed?  
Basically there's no way to get eachRow() to provide a counter...

Integer rowid = 0

try {
m_connection.eachRow(sqlStatement, metaClosure) { row ->
println "row: $rowid"
colName.indices.each { colid ->
println "  column $colid: column 
${colName[colid]}='${row[colid]}' ...
}
rowid++
}

Thanks,
Steve

-----Original Message-----
From: Paul King 
Sent: Thursday, March 28, 2024 9:05 PM
To: users@groovy.apache.org
Subject: Re: SQL enhancement request (GROOVY-11342)

Well spotted for eachRow. You can fix that with:

colName.indices.each { colid ->
println "  column $colid: column 
${colName[colid]}='${row[colid]}' (width=${colWidth[colid]}, 
type=${colType[colid]})"
}

The eachRow method returns a resultset proxy which doesn't support 
eachWithIndex.

sdkman only supports releases. Snapshots are normally in various snapshot 
repositories but for a PR, you need to download the snapshot artifacts produced 
by the relevant GitHub action. Take a look here:
https://github.com/apache/groovy/actions/runs/8467245940/job/23197720603?pr=2070
And look for the URL under "Upload binary distribution".

Just remember, snapshots aren't releases, just useful for testing prior to 
official releases.

Cheers, Paul.

On Fri, Mar 29, 2024 at 11:28 AM  wrote:
>
> Awesome, super exciting to see progress so quickly, thanks!
>
> It's odd though, using your updated code with hsqldb I tried running 
> the eachrow test and it still fails to iterate over the columns 
> correctly for me - weird.  I noticed that you copied the code from
> exampleEachRow() to exampleExecute() so I see what you meant that the
> eachRow() column iteration was working (and I can see from your output 
> that it worked for you with exampleExecute()), but when I use the 
> actual exampleEachRow() code path I am not getting proper iteration 
> over the columns.  And this is using your updated code with the hsqldb 
> database and driver.  I'll be scratching my head on this one for a 
> while!  :)
>
> I noticed that you mentioned I could get early access to the updated Groovy 
> version by using a snapshot version.  I use sdkman to manage my Groovy 
> installation and not sure how to get the snapshot version.  Could you explain 
> how to get the snapshot?
>
> Here's what I see from sdkman -
>
> $ sdk list groovy
> ==
> ==
> Available Groovy Versions
> ==

RE: SQL enhancement request (GROOVY-11342)

2024-03-29 Thread steve.etchelecu
Thanks Paul!  I thought that eachrow iteration issue had something to do with 
eachRow() possibly not returning a List but when I saw it returned something 
that looked like Proxy$10 I got lost as I didn't know how to understand that.  
Normally I would try to look up the definition of the object, like when you 
previously explained the subtleties between ResultSet and GroovyResultSet.  The 
fix worked smoothly (of course) -- indices() was a new one for me.

--- eachRow():
row: 0
  column 0: column COL1='3' (width=11, type=4)
  column 1: column COL2='13' (width=11, type=4)
row: 1
  column 0: column COL1='2' (width=11, type=4)
  column 1: column COL2='12' (width=11, type=4)
row: 2
  column 0: column COL1='1' (width=11, type=4)
  column 1: column COL2='11' (width=11, type=4)

I went through the snapshot process and it downloaded a zip file - it looks 
like it is a Groovy 5 version, does that mean that this fix will be available 
via a release once version 5 releases?

I've seen the Groovy 5 alpha releases and have been interested in the next 
major release of Groovy.  I wasn't sure how stable the alpha releases are so 
I've stayed with version 4 up to this point.  Any idea when Groovy 5 might 
release?

Oh!  Any idea why the SQL that doesn't produce resultSets doesn't fail with 
eachRow() and rows() for hsqldb (only)?  That one threw me for a loop.  The 
only thing I can think of is that the hsqldb driver does produce a (empty) 
resultSet.

Finally (a little Java humor) - with eachRow() am I correct in thinking that my 
rowid handling is the only way to handle it if I want row numbers displayed?  
Basically there's no way to get eachRow() to provide a counter...

Integer rowid = 0

try {
m_connection.eachRow(sqlStatement, metaClosure) { row ->
println "row: $rowid"
colName.indices.each { colid ->
println "  column $colid: column 
${colName[colid]}='${row[colid]}' ...
}
rowid++
}

Thanks,
Steve

-----Original Message-----
From: Paul King  
Sent: Thursday, March 28, 2024 9:05 PM
To: users@groovy.apache.org
Subject: Re: SQL enhancement request (GROOVY-11342)

Well spotted for eachRow. You can fix that with:

colName.indices.each { colid ->
println "  column $colid: column 
${colName[colid]}='${row[colid]}' (width=${colWidth[colid]}, 
type=${colType[colid]})"
}

The eachRow method returns a resultset proxy which doesn't support 
eachWithIndex.

sdkman only supports releases. Snapshots are normally in various snapshot 
repositories but for a PR, you need to download the snapshot artifacts produced 
by the relevant GitHub action. Take a look here:
https://github.com/apache/groovy/actions/runs/8467245940/job/23197720603?pr=2070
And look for the URL under "Upload binary distribution".

Just remember, snapshots aren't releases, just useful for testing prior to 
official releases.

Cheers, Paul.

On Fri, Mar 29, 2024 at 11:28 AM  wrote:
>
> Awesome, super exciting to see progress so quickly, thanks!
>
> It's odd though, using your updated code with hsqldb I tried running 
> the eachrow test and it still fails to iterate over the columns 
> correctly for me - weird.  I noticed that you copied the code from 
> exampleEachRow() to exampleExecute() so I see what you meant that the 
> eachRow() column iteration was working (and I can see from your output 
> that it worked for you with exampleExecute()), but when I use the 
> actual exampleEachRow() code path I am not getting proper iteration 
> over the columns.  And this is using your updated code with the hsqldb 
> database and driver.  I'll be scratching my head on this one for a 
> while!  :)
>
> I noticed that you mentioned I could get early access to the updated Groovy 
> version by using a snapshot version.  I use sdkman to manage my Groovy 
> installation and not sure how to get the snapshot version.  Could you explain 
> how to get the snapshot?
>
> Here's what I see from sdkman -
>
> $ sdk list groovy
> ==
> ==
> Available Groovy Versions
> 
>  5.0.0-alpha-7   3.0.6   2.4.11  2.0.0
>  5.0.0-alpha-6   3.0.5   2.4.10  1.8.9
>  5.0.0-alpha-5   3.0.4   2.4.9   1.8.8
>  5.0.0-alpha-4   3.0.3   2.4.8   1.8.7
>  5.0.0-alpha-3   3.0.2   2.4.7   1.8.6
>  5.0.0-alpha-2   3.0.1   2.4.6

Re: SQL enhancement request (GROOVY-11342)

2024-03-28 Thread Paul King
  row: 2
>   column 0: column COL1='1' (width=11, type=4)
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- eachRow():
> Mar 28, 2024 1:08:49 PM groovy.sql.Sql eachRow
> WARNING: Failed to execute: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 
> 1) because: This SQL statement does not return a single ResultSet
> SQL did not produce a resultSet but unable to suppress warning
> java.sql.SQLException: This SQL statement does not return a single 
> ResultSet
>
> So the code accessing the column information for the three different examples 
> -
>
> println "  column $colid: column ${colName[colid]}='${element[colid]}' 
> (width=${colWidth[colid]}, type=${colType[colid]})" // from exampleExecute()
> println "  column $colid: column ${colName[colid]}='${element.value}' 
> (width=${colWidth[colid]}, type=${colType[colid]})" // from exampleEachRow()
> println "  column $colid: column ${colName[colid]}='${element.value}' 
> (width=${colWidth[colid]}, type=${colType[colid]})" // from exampleRows()
>
> is identical except that exampleEachRow() uses ${element[colid]} versus the 
> ${element.value} for the other two.  I tried converting exampleEachRow() to 
> use ${element.value} but that (surprisingly) generated an error -
>
> --- eachRow():
> row: 0
> Mar 28, 2024 4:04:21 PM groovy.sql.Sql eachRow
> WARNING: Failed to execute: SELECT * FROM MYTABLE because: Column not 
> found: value
>
> Given the strangeness of the two examples I have attached both versions, 
> being careful not to modify anything.  My version uses a Denodo database, 
> which is the target database that I need to use.  I've worked with Denodo for 
> a few years now and it's JDBC interface has seemed to be pretty standard from 
> what I've seen.  We use it with probably about 60-75 developers using Java 
> and Python (and PowerBI using ODBC) and have never run into any driver 
> anomalies, though Python has been somewhat painful with its weird JayDeBeApi 
> driver (basically it can be slow with very large resultSets, 1B+ rows).  It 
> was that JayDeBeApi driver that initially led me to Groovy since Groovy has a 
> smooth natural Java database driver integration.  These developers ported 
> their skillsets over to Denodo from earlier Oracle/Teradata/SQLServer/MySQL 
> environments and have basically found Denodo to be a plug-n-play drop-in 
> replacement for their earlier databases.
>
> I was happy to see that apparently I understood how to handle the two closure 
> calls correctly!  And you didn't (seem to) throw up when you saw my 
> metaClosure definition with its three parallel lists!  If there's a 
> better/groovier way to accomplish what I'm doing in that closure I'm open to 
> learning.   :)
>
> Apologies for the lengthy email and thanks again,
> Steve
>
> -Original Message-
> From: Paul King 
> Sent: Thursday, March 28, 2024 7:39 AM
> To: users@groovy.apache.org
> Subject: Re: SQL enhancement request (GROOVY-11342)
>
> Here is the result of running a slightly modified version of your script (I 
> attached it to the issue) after applying the PR I just
> created:
>
> > groovy SqlExamples2.groovy execute
> --- main():
> SQL: CREATE TABLE MYTABLE (COL1 integer, COL2 integer)
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 0
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 1
> --- main():
> SQL: DELETE FROM MYTABLE WHERE COL1=1
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 0
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 1
> --- main():
> SQL: SELECT * FROM MYTABLE
> --- execute() [no metadata available]:
> query produced a resultSet
> row 0:
>   column 0: column COL1='0' (width=11, type=4)
>   column 1: column COL2='1' (width=11, type=4) row 1:
>   column 0: column COL1='0' (width=11, type=4)
>   column 1: column COL2='1' (width=11, type=4)
> --- main():
> SQL: DELETE FROM MYTABLE WHERE COL1=0
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 2
>
> The eachRow variant worked fine for me. You could try yourself using the 
> modified script - it uses hsqldb, so no need to add your database driver. 
> Maybe the issue you wer

RE: SQL enhancement request (GROOVY-11342)

2024-03-28 Thread steve.etchelecu
prisingly) generated an error -

--- eachRow():
row: 0
Mar 28, 2024 4:04:21 PM groovy.sql.Sql eachRow
WARNING: Failed to execute: SELECT * FROM MYTABLE because: Column not 
found: value

Given the strangeness of the two examples I have attached both versions, being 
careful not to modify anything.  My version uses a Denodo database, which is 
the target database that I need to use.  I've worked with Denodo for a few 
years now and it's JDBC interface has seemed to be pretty standard from what 
I've seen.  We use it with probably about 60-75 developers using Java and 
Python (and PowerBI using ODBC) and have never run into any driver anomalies, 
though Python has been somewhat painful with its weird JayDeBeApi driver 
(basically it can be slow with very large resultSets, 1B+ rows).  It was that 
JayDeBeApi driver that initially led me to Groovy since Groovy has a smooth 
natural Java database driver integration.  These developers ported their 
skillsets over to Denodo from earlier Oracle/Teradata/SQLServer/MySQL 
environments and have basically found Denodo to be a plug-n-play drop-in 
replacement for their earlier databases.

I was happy to see that apparently I understood how to handle the two closure 
calls correctly!  And you didn't (seem to) throw up when you saw my metaClosure 
definition with its three parallel lists!  If there's a better/groovier way to 
accomplish what I'm doing in that closure I'm open to learning.   :)

Apologies for the lengthy email and thanks again,
Steve

-Original Message-
From: Paul King  
Sent: Thursday, March 28, 2024 7:39 AM
To: users@groovy.apache.org
Subject: Re: SQL enhancement request (GROOVY-11342)

Here is the result of running a slightly modified version of your script (I 
attached it to the issue) after applying the PR I just
created:

> groovy SqlExamples2.groovy execute
--- main():
SQL: CREATE TABLE MYTABLE (COL1 integer, COL2 integer)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 0
--- main():
SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 1
--- main():
SQL: DELETE FROM MYTABLE WHERE COL1=1
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 0
--- main():
SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 1
--- main():
SQL: SELECT * FROM MYTABLE
--- execute() [no metadata available]:
query produced a resultSet
row 0:
  column 0: column COL1='0' (width=11, type=4)
  column 1: column COL2='1' (width=11, type=4) row 1:
  column 0: column COL1='0' (width=11, type=4)
  column 1: column COL2='1' (width=11, type=4)
--- main():
SQL: DELETE FROM MYTABLE WHERE COL1=0
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 2

The eachRow variant worked fine for me. You could try yourself using the 
modified script - it uses hsqldb, so no need to add your database driver. Maybe 
the issue you were having is specific to your database/driver. To test the 
execute path, you'd need to use a snapshot version.

Paul.

On Thu, Mar 28, 2024 at 10:46 AM  wrote:
>
> Paul, I created that example (attached) attempting to illustrate my 
> situation with the various (3 anyway) Sql methods.  Hopefully my code 
> makes some sense, happy to answer any questions that it raises.  :)
>
> Running the example with 'execute' which does not provide metadata but does 
> handle SQL that does not produce a resultSet.
>
> $ groovy -cp $DBJAR SqlExamples.groovy execute
> --- main():
> SQL: SELECT 1 AS "COL1", 11 AS "COL2" UNION ALL SELECT 2 AS "COL1", 12 
> AS "COL2" UNION ALL SELECT 3 AS "COL1", 13 AS "COL2" ORDER BY 1 DESC
> --- execute() [no metadata available]:
> query produced a resultSet
> row 0:
>   col COL1='3' (width=?, type=?)
>   col COL2='13' (width=?, type=?)
> row 1:
>   col COL1='2' (width=?, type=?)
>   col COL2='12' (width=?, type=?)
> row 2:
>   col COL1='1' (width=?, type=?)
>   col COL2='11' (width=?, type=?)
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 1
> --- main():
> SQL: DELETE FROM MYTABLE WHERE COL1=1
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 0
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated =

Re: SQL enhancement request (GROOVY-11342)

2024-03-28 Thread Paul King
Here is the result of running a slightly modified version of your
script (I attached it to the issue) after applying the PR I just
created:

> groovy SqlExamples2.groovy execute
--- main():
SQL: CREATE TABLE MYTABLE (COL1 integer, COL2 integer)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 0
--- main():
SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 1
--- main():
SQL: DELETE FROM MYTABLE WHERE COL1=1
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 0
--- main():
SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 1
--- main():
SQL: SELECT * FROM MYTABLE
--- execute() [no metadata available]:
query produced a resultSet
row 0:
  column 0: column COL1='0' (width=11, type=4)
  column 1: column COL2='1' (width=11, type=4)
row 1:
  column 0: column COL1='0' (width=11, type=4)
  column 1: column COL2='1' (width=11, type=4)
--- main():
SQL: DELETE FROM MYTABLE WHERE COL1=0
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 2

The eachRow variant worked fine for me. You could try yourself using
the modified script - it uses hsqldb, so no need to add your database
driver. Maybe the issue you were having is specific to your
database/driver. To test the execute path, you'd need to use a
snapshot version.

Paul.

On Thu, Mar 28, 2024 at 10:46 AM  wrote:
>
> Paul, I created that example (attached) attempting to illustrate my situation 
> with the various (3 anyway) Sql methods.  Hopefully my code makes some sense, 
> happy to answer any questions that it raises.  :)
>
> Running the example with 'execute' which does not provide metadata but does 
> handle SQL that does not produce a resultSet.
>
> $ groovy -cp $DBJAR SqlExamples.groovy execute
> --- main():
> SQL: SELECT 1 AS "COL1", 11 AS "COL2" UNION ALL SELECT 2 AS "COL1", 12 AS 
> "COL2" UNION ALL SELECT 3 AS "COL1", 13 AS "COL2" ORDER BY 1 DESC
> --- execute() [no metadata available]:
> query produced a resultSet
> row 0:
>   col COL1='3' (width=?, type=?)
>   col COL2='13' (width=?, type=?)
> row 1:
>   col COL1='2' (width=?, type=?)
>   col COL2='12' (width=?, type=?)
> row 2:
>   col COL1='1' (width=?, type=?)
>   col COL2='11' (width=?, type=?)
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 1
> --- main():
> SQL: DELETE FROM MYTABLE WHERE COL1=1
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 0
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 1
> --- main():
> SQL: DELETE FROM MYTABLE WHERE COL1=0
> --- execute() [no metadata available]:
> successful execution (with no resultSet)
>   rows updated = 2
>
> ===
> And then here's an execution with 'rows' which does provide metadata but 
> cannot handle SQL that does not produce a resultSet.
>
> $ groovy -cp $DBJAR SqlExamples.groovy rows
> --- main():
> SQL: SELECT 1 AS "COL1", 11 AS "COL2" UNION ALL SELECT 2 AS "COL1", 12 AS 
> "COL2" UNION ALL SELECT 3 AS "COL1", 13 AS "COL2" ORDER BY 1 DESC
> --- rows():
> row 0:
>   column 0: column COL1='3' (width=11, type=4)
>   column 1: column COL2='13' (width=11, type=4)
> row 1:
>   column 0: column COL1='2' (width=11, type=4)
>   column 1: column COL2='12' (width=11, type=4)
> row 2:
>   column 0: column COL1='1' (width=11, type=4)
>   column 1: column COL2='11' (width=11, type=4)
> --- main():
> SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
> --- rows():
> Mar 27, 2024 7:01:46 PM groovy.sql.Sql$AbstractQueryCommand execute
> WARNING: Failed to execute: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1) 
> because: This SQL statement does not return a single ResultSet
> SQL did not produce a resultSet but unable to suppress warning
>
> Hopefully this is what you meant when you said an example would be helpful.  
> The example should work with all/most JDBC-compliant databases though the 
> SELECT query might need a little tweaking as some databases don't allow 
> queries without a FROM clause.
>
> Putting together the example was an educational experience and ended up 
> helping me to improve my understanding of Groovy - still have a long way to 
> go!  For example, I never could get the exampleEachRow() to completely work; 
> it processes the rows but I couldn't get it to iterate over the columns the 
> way that the other two methods do.
>
> And any educational feedback you might have would be greatly appreciated!  
> After all I'm sure you have plenty of free time to donate!  :D
>
> So the approach you menti

RE: SQL enhancement request (GROOVY-11342)

2024-03-27 Thread steve.etchelecu
Paul, I created that example (attached) attempting to illustrate my situation 
with the various (3 anyway) Sql methods.  Hopefully my code makes some sense, 
happy to answer any questions that it raises.  :)

Running the example with 'execute' which does not provide metadata but does 
handle SQL that does not produce a resultSet.

$ groovy -cp $DBJAR SqlExamples.groovy execute
--- main():
SQL: SELECT 1 AS "COL1", 11 AS "COL2" UNION ALL SELECT 2 AS "COL1", 12 AS 
"COL2" UNION ALL SELECT 3 AS "COL1", 13 AS "COL2" ORDER BY 1 DESC
--- execute() [no metadata available]:
query produced a resultSet
row 0:
  col COL1='3' (width=?, type=?)
  col COL2='13' (width=?, type=?)
row 1:
  col COL1='2' (width=?, type=?)
  col COL2='12' (width=?, type=?)
row 2:
  col COL1='1' (width=?, type=?)
  col COL2='11' (width=?, type=?)
--- main():
SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 1
--- main():
SQL: DELETE FROM MYTABLE WHERE COL1=1
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 0
--- main():
SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 1
--- main():
SQL: DELETE FROM MYTABLE WHERE COL1=0
--- execute() [no metadata available]:
successful execution (with no resultSet)
  rows updated = 2

===
And then here's an execution with 'rows' which does provide metadata but cannot 
handle SQL that does not produce a resultSet.

$ groovy -cp $DBJAR SqlExamples.groovy rows
--- main():
SQL: SELECT 1 AS "COL1", 11 AS "COL2" UNION ALL SELECT 2 AS "COL1", 12 AS 
"COL2" UNION ALL SELECT 3 AS "COL1", 13 AS "COL2" ORDER BY 1 DESC
--- rows():
row 0:
  column 0: column COL1='3' (width=11, type=4)
  column 1: column COL2='13' (width=11, type=4)
row 1:
  column 0: column COL1='2' (width=11, type=4)
  column 1: column COL2='12' (width=11, type=4)
row 2:
  column 0: column COL1='1' (width=11, type=4)
  column 1: column COL2='11' (width=11, type=4)
--- main():
SQL: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1)
--- rows():
Mar 27, 2024 7:01:46 PM groovy.sql.Sql$AbstractQueryCommand execute
WARNING: Failed to execute: INSERT INTO MYTABLE (COL1, COL2) VALUES (0, 1) 
because: This SQL statement does not return a single ResultSet
SQL did not produce a resultSet but unable to suppress warning

Hopefully this is what you meant when you said an example would be helpful.  
The example should work with all/most JDBC-compliant databases though the 
SELECT query might need a little tweaking as some databases don't allow queries 
without a FROM clause.

Putting together the example was an educational experience and ended up helping 
me to improve my understanding of Groovy - still have a long way to go!  For 
example, I never could get the exampleEachRow() to completely work; it 
processes the rows but I couldn't get it to iterate over the columns the way 
that the other two methods do.

And any educational feedback you might have would be greatly appreciated!  
After all I'm sure you have plenty of free time to donate!  :D

So the approach you mentioned of adding a new variant to execute() that adds a 
metaClosure would be perfect, though I've really gotten comfortable with the 
rows() method - not sure how it scales when resultSets go to billions of rows 
though...  I expect execute() would perform like a streaming interface and not 
have any problems at scale.

Thanks for all your help, couldn't have made it this far otherwise,
Steve
-Original Message-
From: Paul King  
Sent: Monday, March 25, 2024 8:03 PM
To: users@groovy.apache.org
Subject: Re: SQL enhancement request

Adding a metaClosure to execute seems the easiest change. I created
GROOVY-11342 to track here:

https://issues.apache.org/jira/browse/GROOVY-11342

Would the expectation be that the metaClosure is called for each result 
producing a ResultSet?

Paul.

On Sat, Mar 23, 2024 at 3:40 AM  wrote:
>
> Thanks Jörg,
>
> Yes, that's one of the approaches I tried but the execute() method doesn't 
> appear to provide metadata (column names, types, etc) and my application 
> needs that information.
>
> That's why my request was to either
>
>   - add the "hasResults" argument to the rows() and eachRow() methods
>
> OR
>
>   - add metadata results to the execute() method.
>
> The relevant variants that I'm seeing are:
>
> eachRow(String sql, Closure metaClosure, Closure rowClosure)
> eachRow(GString gstring, Closure metaClosure, Closure rowClosure)
>
> rows(String sql, Closure metaClosure)
> rows(GString gstring, Closure metaClosure)
>
> execute(String sql, Closure processResults)
> execute(GString gstring, Closure processResults)
>
> where for the eachRow() and rows() methods -
>
> sql - the sql statement
> metaClosure - called for metadata (only once after sql execution)
> rowClosu