return HeapTuple
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"