[Gambas-user] PostgreSQL multiple column problem

Fabien Bodard gambas.fr at ...626...
Thu Oct 18 09:19:43 CEST 2012


Have you try your sql request in the gambas3 IDE database manager?
Le 18 oct. 2012 02:54, "Markus Schatten" <markus.schatten at ...2005...> a écrit :

> Dear Fabien and Ian,
>
> thank you for your reply. I was kind of hoping that there is a way to
> index the results. I started of to write a query rewriter, but got
> soon into trouble with lots of possible ways of writing a query. I
> would probably need a grammar parser to do that ;-)
>
> Anyways, after looking up the SELECT syntax, I found another way. I
> wasn't aware of the WITH clause in a select statement which allows you
> (at least in PostgreSQL) to create an alias for a subquery with
> specified column names. I used this to create a rewrite. The idea is
> to construct a query like:
>
> WITH query(a0, a1) AS (SELECT * FROM test t1, test t2) SELECT * FROM query
>
> which replaces the initial column names with a0 and a1. Afterwards I
> put the original column names into the TableView header (datasource +
> dataview doesn't work since the table attribute doesn't seem to accept
> WITH queries - is there a reason for that, or is that a bug?). Here is
> the solution if anyone might need it:
>
>
> Public con As New Connection
> Public original As New String[]
>
> Public Sub _new()
>   With con
>     .Type = "postgresql"
>     .Name = "db"
>     .User = "markus"
>     .Password = "secret"
>     .Open
>   End With
>   execute(rewrite_query("SELECT * FROM test t1, test t2"))
> End
>
> Public Sub execute(query As String)
>   ' execute the query and show the results
>   Dim res As Result
>   Dim rfield As ResultField
>   Dim col_counter, row_counter, i As Integer
>   Dim context As New Collection
>   res = con.Exec(query)
>   TableView1.Rows.Count = res.Count
>   TableView1.Columns.Count = res.Fields.Count
>   For i = 0 To original.Max
>     TableView1.Columns[i].Title = original[i]
>   Next
>   row_counter = 0
>   For Each res
>     col_counter = 0
>     context["res"] = res
>     TableView1.Row = row_counter
>     For Each rfield In res.Fields
>      TableView1.Column = col_counter
>       TableView1.Current.Text = Eval("res!" & rfield.Name, context)
>       col_counter += 1
>     Next
>     row_counter += 1
>   Next
> End
>
>
> Public Function find_all(subj As String, pattern As String, Optional
> submatchindex As Integer = 0) As String[]
>   ' findall matches of a given regex in a given string, return only
> submatches if submatchindex is specified
>   Dim re As Regexp
>   Dim matches As New String[]
>   re = New Regexp(subj, pattern)
>
>   Do While re.offset >= 0 And subj <> ""
>     If submatchindex = 0 Then
>       matches.push(re.Text)
>     Else
>       matches.push(re.SubMatches[submatchindex].Text)
>     End If
>     If Len(subj) > Len(re.text) Then
>       subj = Mid(subj, re.offset + Len(re.text) + 1)
>     Else
>       subj = ""
>     End If
>       If subj <> "" Then re.exec(subj)
>   Loop
>   Return matches
> End
>
> Public Function rewrite_query(query As String) As String
>   ' rewrite the query to return distinct column names
>   Dim has_asterisk As String[]
>   Dim defined_limit As String[]
>   Dim replace_limit As String
>   Dim query_copy As String
>   Dim res As Result
>   Dim rfield As ResultField
>   Dim counter As Collection
>   Dim with_string As String
>   Dim i As Integer
>   has_asterisk = find_all(query, "(?i)select (.*?[\\*].*?) from", 1)
>   If has_asterisk.Count > 0 Then
>     query_copy = query
>     defined_limit = find_all(query, "(?i)(limit +[0-9]+)", 1)
>     If defined_limit.Count > 0 Then
>       For Each replace_limit In defined_limit
>         query = Replace(query, replace_limit, "LIMIT 1")
>       Next
>     Else
>       query &= " LIMIT 1"
>     Endif
>     res = con.Exec(query)
>     For Each res
>       counter = New Collection
>       For Each rfield In res.Fields
>         original.Push(rfield.name)
>       Next
>     Next
>     with_string = "WITH query("
>     For i = 0 To original.Max
>       with_string &= "a" & Str(i) & ", "
>     Next
>     with_string = Left$(with_string, -2) & ") AS (" & query_copy & ")
> SELECT * FROM query"
>     Print with_string
>     Return with_string
>   Else
>     Return query
>   Endif
> End
>
> On Wed, Oct 17, 2012 at 10:33 AM, Ian Haywood <ihaywood at ...1979...>
> wrote:
> > No, I think its your best solution
> > Maybe your users can just type in the "where" part of the query and
> > then you add the rest?
>
> The app is a database development environment, so users have to enter
> the whole query. I will try to find solutions for other dbms' (I'm
> planning to support SQLite and MySQL as well) so if anyone has another
> idea on how to approach the matter, I'll be happy to see a solution.
>
> All the best,
>
> M.
>
> --
> Markus Schatten, PhD
> Assistant professor
> University of Zagreb
> Faculty of Organization and Informatics
> Pavlinska 2, 42000 Varazdin, Croatia
> http://www.foi.hr/nastavnici/schatten.markus/index.html
> http://www.researchgate.net/profile/Markus_Schatten1
>
>
> ------------------------------------------------------------------------------
> Everyone hates slow websites. So do we.
> Make your web apps faster with AppDynamics
> Download AppDynamics Lite for free today:
> http://p.sf.net/sfu/appdyn_sfd2d_oct
> _______________________________________________
> Gambas-user mailing list
> Gambas-user at lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/gambas-user
>



More information about the User mailing list