return HeapTuple

Started by Werner Echezuriaover 16 years ago1 messages
#1Werner Echezuria
wercool@gmail.com
1 attachment(s)

Hi, I wanna return a group of rows, like when you do "SELECT columns FROM
table", but I'm getting some troubles, I don't know if I have to use
HeapTuple or Datum. I'm using bison to parse sqlf to sql this way:

-- some code

%%

query: /* empty string */

| query command

;

command: '\n'

| CreateFuzzyPredStmt

| DropFuzzyPredStmt

| SelectStmt

{

int i;

*((void **)result) = return_query(fuzzy_query[real_length-1]);

for (i=0;i<real_length;i++)

pfree(fuzzy_query[i]);

}

| error '\n' { yyerrok;}

;

-- some code

HeapTuple

return_query(char *str){

HeapTuple rettuple;

int ret, proc;

SPI_connect();

ret=SPI_execute(str,true,1);

proc=SPI_processed;

if (ret > 0 && SPI_tuptable != NULL){

SPITupleTable *tuptable = SPI_tuptable;

rettuple = tuptable->vals;

}

SPI_finish();

return rettuple;

}

This I have the function:

#include "postgres.h"

#include "fmgr.h"

#include "gram.h"

#include "utils/builtins.h"

extern Datum sqlf(PG_FUNCTION_ARGS);

PG_MODULE_MAGIC;

PG_FUNCTION_INFO_V1(sqlf);

Datum

sqlf(PG_FUNCTION_ARGS){

char *query = TextDatumGetCString(PG_GETARG_DATUM(0));

void *result;

yy_scan_string(query);

sqlf_yyparse(&result);

PG_RETURN_HEAPTUPLEHEADER(result);

}

regards.

Attachments:

gram2.yapplication/octet-stream; name=gram2.yDownload
%{
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    #include "postgres.h"
    #include "executor/spi.h"
    #include "access/heapam.h"
    #include "fmgr.h"
    #include "parsing.h"

    #define YYDEBUG 1
    #define QUERY_LENGTH 4
    #define YYPARSE_PARAM result  /* need this to pass a pointer (void *) to yyparse */

    int sqlf_yyparse(void *result);

    int real_length;
    char *field;
    char *fuzzy_query[QUERY_LENGTH];

    HeapTuple return_query(char *str);

%}

%name-prefix="sqlf_yy"

%union {
    int	integer;
    char *text;
}

%token CREATE FUZZY PREDICATE ON AS COMMA DOTDOT LEFTP RIGHTP INFINIT
        DROP EQUAL SELECT WHERE FROM AND OR ORDER BY ASC DESC WITH CALIBRATION
%token <text> PARAMETER 
%type <text> Param Param_select Param_from List_where List_order SelectStmt

%%


query:  /* empty string */
      |  query command
;

command: '\n'
            | CreateFuzzyPredStmt
            | DropFuzzyPredStmt
            | SelectStmt					
                       {
                          int i;
                          *((void **)result) = return_query(fuzzy_query[real_length-1]);

                          for (i=0;i<real_length;i++)
                            pfree(fuzzy_query[i]);
                        }
            | error '\n'  { yyerrok;}
;

CreateFuzzyPredStmt:
            CREATE FUZZY PREDICATE Param ON Param DOTDOT Param AS LEFTP Param COMMA Param COMMA Param COMMA Param RIGHTP
            {
                    create_fuzzy_pred($4,$6,$8,$11,$13,$15,$17);
            }
            |
            CREATE FUZZY PREDICATE Param ON Param DOTDOT Param AS LEFTP INFINIT COMMA INFINIT COMMA Param COMMA Param RIGHTP
            {
                    create_fuzzy_pred($4,$6,$8,"INFINIT","INFINIT",$15,$17);
            }
            |
            CREATE FUZZY PREDICATE Param ON Param DOTDOT Param AS LEFTP Param COMMA Param COMMA INFINIT COMMA INFINIT RIGHTP
            {
                    create_fuzzy_pred($4,$6,$8,$11,$13,"INFINIT","INFINIT");
            }
;

DropFuzzyPredStmt:
            DROP FUZZY PREDICATE Param
            {
                    drop_fuzzy_pred($4);
            }
;

/**************SELECT STATEMENT**********************************/
/*

[ WITH [ RECURSIVE ] with_query [, ...] ]
SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    * | expression [ [ AS ] output_name ] [, ...]
    [ FROM from_item [, ...] ]
    [ WHERE condition ]
    [ GROUP BY expression [, ...] ]
    [ HAVING condition [, ...] ]
    [ WINDOW window_name AS ( window_definition ) [, ...] ]
    [ { UNION | INTERSECT | EXCEPT } [ ALL ] select ]
    [ ORDER BY expression [ ASC | DESC | USING operator ] [ NULLS { FIRST | LAST } ] [, ...] ]
    [ LIMIT { count | ALL } ]
    [ OFFSET start [ ROW | ROWS ] ]
    [ FETCH { FIRST | NEXT } [ count ] { ROW | ROWS } ONLY ]
    [ FOR { UPDATE | SHARE } [ OF table_name [, ...] ] [ NOWAIT ] [...] ]

where from_item can be one of:

    [ ONLY ] table_name [ * ] [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    ( select ) [ AS ] alias [ ( column_alias [, ...] ) ]
    with_query_name [ [ AS ] alias [ ( column_alias [, ...] ) ] ]
    function_name ( [ argument [, ...] ] ) [ AS ] alias [ ( column_alias [, ...] | column_definition [, ...] ) ]
    function_name ( [ argument [, ...] ] ) AS ( column_definition [, ...] )
    from_item [ NATURAL ] join_type from_item [ ON join_condition | USING ( join_column [, ...] ) ]

and with_query is:

    with_query_name [ ( column_name [, ...] ) ] AS ( select )

    WITH CALIBRATION
*/

/* Missing pretty much everything, it parses the basic select */

SelectStmt:
            SELECT Param_select FROM Param_from
            {
                fuzzy_query[0]=(char *)palloc(sizeof(char)*(strlen($2)+strlen($4)+20));
                snprintf(fuzzy_query[0],(strlen($2)+strlen($4)+20),"SELECT %s FROM %s",$2,$4);
                $$=fuzzy_query[0];
                real_length=1;
            }
						|
            SelectStmt WHERE List_where
            {
                fuzzy_query[1]=(char *)palloc(sizeof(char)*(strlen($1)+strlen($3)+20));
                snprintf(fuzzy_query[1],(strlen($1)+strlen($3)+20),"%s WHERE %s",$1,$3);
                $$=fuzzy_query[1];
                real_length=2;
            }
						|
            SelectStmt ORDER BY List_order
            {
                fuzzy_query[2]=(char *)palloc(sizeof(char)*(strlen($1)+strlen($4)+20));
                snprintf(fuzzy_query[2],(strlen($1)+strlen($4)+20),"%s ORDER BY %s",$1,$4);
                $$=fuzzy_query[2];
                real_length=3;
            }
						|
            SelectStmt WITH CALIBRATION Param
            {
                fuzzy_query[3]=(char *)palloc(sizeof(char)*(strlen($1)+strlen($4)+20));
                snprintf(fuzzy_query[3],(strlen($1)+strlen($4)+20),"%s WITH CALIBRATION %s",$1,$4);
                $$=fuzzy_query[3];
                real_length=4;
            }
;

Param:	PARAMETER { $$ = $1; };

Param_select:
            Param { $$ = $1; }
            | Param_select COMMA Param {
                strcat($$,", ");
                strcat($$,$3);
            }
            | Param_select AS Param {
                strcat($$," AS ");
                strcat($$,$3);
            }
            | Param_select Param {
                strcat($$," ");
                strcat($$,$2);
            }
;

Param_from:
            Param { $$ = $1;}
            | Param_from COMMA Param {
                strcat($$,", ");
                strcat($$,$3);
            }
            | Param_from AS Param {
                strcat($$," AS ");
                strcat($$,$3);
            }
            | Param_from Param {
                strcat($$," ");
                strcat($$,$2);
            }
;


List_where:
            Param {
                $$=$1;
                field=$1;
            }
            | LEFTP Param {
                strcat($$," (");
                strcat($$,$2);
                field=$2;
            }
            | List_where EQUAL Param {
            	int len;
            	char *result;
              len=strlen(field)+strlen($3)+15;//15 is the length of "%s > %f AND %s < %f"
              result=(char *)palloc(sizeof(char)*(len*2));
              $$=translate_fuzzy_preds(result,field,$3);
              pfree(result);
            }
            | List_where AND Param {
                strcat($$," AND ");
                strcat($$,$3);
                field=$3;
            }
            | List_where RIGHTP AND Param {
                strcat($$,") AND ");
                strcat($$,$4);
                field=$4;
            }
            | List_where OR Param {
                strcat($$," OR ");
                strcat($$,$3);
                field=$3;
            }
            | List_where RIGHTP OR Param {
                strcat($$,") OR ");
                strcat($$,$4);
                field=$4;
            }
;

List_order:
            Param { $$=$1; }
            | List_order COMMA Param {
                strcat($$,", ");
                strcat($$,$3);
            }
            | List_order ASC { 
                strcat($$," ASC");
                strcat($$,$1);
            }
            | List_order DESC { 
                strcat($$," DESC");
                strcat($$,$1);
            }
;

%%
void yyerror (char *s) {elog (ERROR, "%s\n", s);}

HeapTuple 
return_query(char *str){
  HeapTuple	rettuple;
  int		ret, proc;

  SPI_connect();
  ret=SPI_execute(str,true,1);
  proc=SPI_processed;
	
  if (ret > 0 && SPI_tuptable != NULL){
    SPITupleTable *tuptable = SPI_tuptable;
    rettuple = tuptable->vals;
  }

  SPI_finish();

  return rettuple;

}

#include "scan.c"