Обсуждение: ECPG: non-integer constant in group by

Поиск
Список
Период
Сортировка

ECPG: non-integer constant in group by

От
Poul Jensen
Дата:
I actually have two questions.

1) It seems like the fastest way to find the # of distinct elements in a
column is using GROUP BY. With ECPG, if I try
    EXEC SQL SELECT filenm FROM beamdata GROUP BY filenm;
    I will get "sql error Too few arguments". Why? Can I correct the
query to avoid the error message? (sqlca.sqlerrd[2] does contain the #
of elements in spite of error)

2) The code below was meant to find the # of distinct elements for many
columns, but fails with the message
    sql error 'non-integer constant in GROUP BY'
    thrown at the EXEC SQL EXECUTE statement. What is the problem? I
suspect it is the definition char *vars[NVARS], but couldn't find any
working alternatives. :-|

--------------------------

#define NVARS 24

int main(int argc, char *argv[]) {

  int i, n_occ[NVARS];

  EXEC SQL BEGIN DECLARE SECTION;
  char *vars[NVARS] = { "filenm", "yr", "mo", "dy", "hr", "mt", "sc",
              "us", "stat_id", "bmnum", "channel", "scnflag",
              "cp_id", "intt", "intt_us", "frang", "rsep",
              "tfreq", "noise", "natten", "nave", "nrang",
              "gsct", "isct" };
  char dbnm[50], *stmt = "SELECT ? FROM beamdata GROUP BY ?;";
  EXEC SQL END DECLARE SECTION;

  EXEC SQL WHENEVER SQLWARNING SQLPRINT;
  EXEC SQL WHENEVER SQLERROR SQLPRINT;

  sprintf(dbnm,"%s",argv[1]);

  EXEC SQL CONNECT TO :dbnm;

  EXEC SQL PREPARE query FROM :stmt;

  for (i=0; i<NVARS; i++)
  {
    EXEC SQL EXECUTE query USING $vars[i], $vars[i];
    n_occ[i] = sqlca.sqlerrd[2];
    fprintf(stderr,"# %s: %d\n", vars[i], n_occ[i]);
  }

  EXEC SQL DEALLOCATE PREPARE query;

  EXEC SQL COMMIT;

  EXEC SQL DISCONNECT;

  return 0;

}

Re: ECPG: non-integer constant in group by

От
Andrew - Supernews
Дата:
On 2006-09-15, Poul Jensen <flyvholm@gfy.ku.dk> wrote:
> 2) The code below was meant to find the # of distinct elements for many
> columns, but fails with the message
>     sql error 'non-integer constant in GROUP BY'
>     thrown at the EXEC SQL EXECUTE statement. What is the problem?

>   char dbnm[50], *stmt = "SELECT ? FROM beamdata GROUP BY ?;";

That statement is not legal - parameters can only be used to substitute
_data_, not identifiers or syntax.

You would have to interpolate the column name directly into the query
(remembering to quote it with "" if needed) rather than use a parameter
for it.

--
Andrew, Supernews
http://www.supernews.com - individual and corporate NNTP services

Re: ECPG: non-integer constant in group by

От
Joachim Wieland
Дата:
On Fri, Sep 15, 2006 at 02:40:49AM -0800, Poul Jensen wrote:
> 1) It seems like the fastest way to find the # of distinct elements in a
> column is using GROUP BY. With ECPG, if I try
>    EXEC SQL SELECT filenm FROM beamdata GROUP BY filenm;
>    I will get "sql error Too few arguments". Why? Can I correct the
> query to avoid the error message? (sqlca.sqlerrd[2] does contain the #
> of elements in spite of error)

The problem is that you are selecting a value but you don't say where ecpg
should store the result. You're missing the "INTO :var" part.


Joachim

--
Joachim Wieland                                              joe@mcknight.de
                                                           GPG key available

Re: ECPG: non-integer constant in group by

От
Poul Jensen
Дата:
Joachim Wieland wrote:
> On Fri, Sep 15, 2006 at 02:40:49AM -0800, Poul Jensen wrote:
>
>> 1) It seems like the fastest way to find the # of distinct elements in a
>> column is using GROUP BY. With ECPG, if I try
>>    EXEC SQL SELECT filenm FROM beamdata GROUP BY filenm;
>>    I will get "sql error Too few arguments". Why? Can I correct the
>> query to avoid the error message? (sqlca.sqlerrd[2] does contain the #
>> of elements in spite of error)
>>
> The problem is that you are selecting a value but you don't say where ecpg
> should store the result. You're missing the "INTO :var" part.
>
Thank you; that makes sense. I'm not sure why it's considered an error
though. Documentation says "Any SQL command can be run...", and why not.

The other problem I posted is worse and is what's really keeping me
stuck. Why are my text strings considered unacceptable "non-integer
constants"? Here are the relevant lines of code:

#define NVARS 24

EXEC SQL BEGIN DECLARE SECTION;
char *vars[NVARS] = { "filenm", "yr", "mo", "dy", "hr", "mt", "sc",
             "us", "stat_id", "bmnum", "channel", "scnflag",
             "cp_id", "intt", "intt_us", "frang", "rsep",
             "tfreq", "noise", "natten", "nave", "nrang",
             "gsct", "isct" };
char *stmt = "SELECT ? FROM beamdata GROUP BY ?;";
EXEC SQL END DECLARE SECTION;

EXEC SQL PREPARE query FROM :stmt;

for (i=0; i<NVARS; i++)
{
   EXEC SQL EXECUTE query USING :vars[i], :vars[i];
}

Fails at EXECUTE with error message:
sql error 'non-integer constant in GROUP BY'

Re: ECPG: non-integer constant in group by

От
Martijn van Oosterhout
Дата:
On Fri, Sep 15, 2006 at 02:44:33PM -0800, Poul Jensen wrote:
> The other problem I posted is worse and is what's really keeping me
> stuck. Why are my text strings considered unacceptable "non-integer
> constants"? Here are the relevant lines of code:

<snip>

That's because your query is expanding to:

SELECT 'filenm' FROM beamdata GROUP BY 'filenm';

Which is probably not what you're looking for. The reason postgres is
complaining is because grouping by a constant doesn't make any sense.
Integer constants are special-cased to mean column numbers, hence the
reference to non-integer constants.

Hope this helps,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> From each according to his ability. To each according to his ability to litigate.

Вложения

Re: ECPG: non-integer constant in group by

От
Poul Jensen
Дата:
Thank you for your replies. My next attempt was:

for (i=0; i<NVARS; i++)
{
    sprintf(stmt,"SELECT %s FROM beamdata GROUP BY %s;",vars[i],vars[i]);
    EXEC SQL EXECUTE IMMEDIATE :stmt;
    n_occ[i] = sqlca.sqlerrd[2];
}

It works, but throws error message "too few parameters" every time. I
need to add INTO <host variable> (I do need to retrieve the data for
later use anyway), but it appears I can't use EXECUTE IMMEDIATE with a
host variable in the statement. So now I can only think of one way:

  EXEC SQL SELECT filenm INTO :filenms FROM beamdata GROUP BY filenm;
  n_occ[0] = sqlca.sqlerrd[2];
  EXEC SQL SELECT yr INTO :yrs FROM beamdata GROUP BY yr;
  n_occ[1] = sqlca.sqlerrd[2];
  <Repeat for all variables!!>

Works and will get the job done, but so repetitive that it's hard to
accept. Is there no way to get away with a loop?

Poul Jensen

Re: ECPG: non-integer constant in group by

От
Martijn van Oosterhout
Дата:
On Sat, Sep 16, 2006 at 03:47:28AM -0800, Poul Jensen wrote:
> Thank you for your replies. My next attempt was:
>
> for (i=0; i<NVARS; i++)
> {
>    sprintf(stmt,"SELECT %s FROM beamdata GROUP BY %s;",vars[i],vars[i]);
>    EXEC SQL EXECUTE IMMEDIATE :stmt;
>    n_occ[i] = sqlca.sqlerrd[2];
> }

I've never used ECPG, but from the manual it seems the following should
work:

for (i=0; i<NVARS; i++)
{
   sprintf(stmt,"SELECT %s FROM beamdata GROUP BY %s;",vars[i],vars[i]);
   EXEC SQL PREPARE mystmt FROM :stmt;
   EXEC SQL EXECUTE mystmt INTO wherever;
   n_occ[i] = sqlca.sqlerrd[2];
}

I don't know what the n_occ line does, so I left it alone but maybe
that needs changing too.

Hope this helps,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> From each according to his ability. To each according to his ability to litigate.

Вложения

Re: ECPG: non-integer constant in group by

От
Poul Jensen
Дата:
Martijn van Oosterhout wrote:
> for (i=0; i<NVARS; i++)
> {
>    sprintf(stmt,"SELECT %s FROM beamdata GROUP BY %s;",vars[i],vars[i]);
>    EXEC SQL PREPARE mystmt FROM :stmt;
>    EXEC SQL EXECUTE mystmt INTO wherever;
>    n_occ[i] = sqlca.sqlerrd[2];
> }
>
Apologies. I already read this in the docs, but also forgot it again.
:-| There is a little more to the solution since I need another array to
save the retrieved data after each query. So in the hope to help others,
here's how I did it:

int *all_vars[NVARS];
int *tmp=NULL;

  for (i=0; i<NVARS; i++)
  {
    sprintf(stmt,"SELECT %s FROM beamdata GROUP BY %s;",vars[i],vars[i]);
    EXEC SQL PREPARE query FROM :stmt;
    EXEC SQL EXECUTE query INTO :tmp;
    n_occ[i] = sqlca.sqlerrd[2];   /* Number of rows processed in query */
    if ((all_vars[i]=(int *)malloc(n_occ[i]*sizeof(int)))==NULL)
    {
      fprintf(stderr,"Memory allocation failure\n");
      exit(-1);
    }
    memcpy(all_vars[i], tmp, n_occ[i]*sizeof(int));
    EXEC SQL DEALLOCATE PREPARE query;
    tmp=NULL;
  }

(Remember to free allocated memory when done)

Thanks so much for the help!