check in lex/yacc based relational algebra primitives
This commit is contained in:
parent
ff0887624c
commit
e96b4d1c05
20 changed files with 2132 additions and 561 deletions
|
@ -3,12 +3,19 @@ Project(Stasis)
|
|||
SET(PACKAGE_VERSION 1)
|
||||
|
||||
SUBDIRS(src test utilities benchmarks examples)
|
||||
SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
SET(FLEX_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
SET(BISON_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
# Main decisions
|
||||
SET(BUILD_SHARED_LIBS ON)
|
||||
#ENABLE_TESTING()
|
||||
INCLUDE(CTest)
|
||||
|
||||
FIND_PACKAGE(FLEX)
|
||||
FIND_PACKAGE(BISON)
|
||||
|
||||
|
||||
# Look for include files
|
||||
INCLUDE (CheckIncludeFiles)
|
||||
FIND_LIBRARY(CHECK_LIBRARY NAMES check)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
ADD_LIBRARY(referential algebra.c dml.c)
|
||||
SET(COMMON_LIBRARIES referential ${COMMON_LIBRARIES})
|
||||
SUBDIRS(lang)
|
||||
ADD_LIBRARY(referential algebra.c dml.c ddl.c tuple.c lang/ast.c)
|
||||
SET(COMMON_LIBRARIES referential refparse ${COMMON_LIBRARIES})
|
||||
IF(CHECK_LIBRARY)
|
||||
CREATE_CHECK_OPT(toplevel ${CMAKE_CURRENT_SOURCE_DIR}/test-script.ref)
|
||||
ENDIF(CHECK_LIBRARY)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,19 +1,29 @@
|
|||
#ifndef __ALGEBRA_H
|
||||
#define __ALGEBRA_H
|
||||
|
||||
#include "lang/ast.h"
|
||||
|
||||
typedef struct {
|
||||
recordid hash;
|
||||
} ReferentialAlgebra_context_t;
|
||||
|
||||
lladdIterator_t* ReferentialAlgebra_ExecuteQuery(int xid,
|
||||
ReferentialAlgebra_context_t* c, union_qry *q);
|
||||
|
||||
lladdIterator_t* ReferentialAlgebra_OpenTableScanner(int xid, recordid catalog,
|
||||
char * tablename);
|
||||
lladdIterator_t* ReferentialAlgebra_Select(int xid, lladdIterator_t* it,
|
||||
char ** predicate);
|
||||
union_cmp * predicate);
|
||||
lladdIterator_t* ReferentialAlgebra_Project(int xid, lladdIterator_t * it,
|
||||
char ** project);
|
||||
col_tuple * project);
|
||||
lladdIterator_t* ReferentialAlgebra_Join(int xid,
|
||||
lladdIterator_t * outer_it,
|
||||
lladdIterator_t * inner_it,
|
||||
cmp_tuple * cmp);
|
||||
lladdIterator_t* ReferentialAlgebra_KeyValCat(int xid, lladdIterator_t * it);
|
||||
char * tplRid(recordid rid);
|
||||
recordid ridTpl(char * tpl);
|
||||
|
||||
void ReferentialAlgebra_init();
|
||||
|
||||
char ** executeQuery(int xid, recordid hash, char * line);
|
||||
lladdIterator_t * parseExpression(int xid, recordid catalog, char **head);
|
||||
char** parseTuple(char ** head);
|
||||
ReferentialAlgebra_context_t * ReferentialAlgebra_openContext(int xid, recordid rid);
|
||||
recordid ReferentialAlgebra_allocContext(int xid);
|
||||
|
||||
#endif
|
||||
|
|
20
src/apps/referential/ddl.c
Normal file
20
src/apps/referential/ddl.c
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include "ddl.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
int ReferentialDDL_CreateTable(int xid, ReferentialAlgebra_context_t*context, create *q) {
|
||||
recordid newTable = ThashCreate(xid, VARIABLE_LENGTH, VARIABLE_LENGTH); // XXX assumes first col is a string!
|
||||
tuple_t ridtpl = tupleRid(newTable);
|
||||
tuple_t union_typ_tup = tupleUnion_typ(q->schema);
|
||||
assert(union_typ_tup.count);
|
||||
assert(union_typ_tup.col[0].int64 == string_typ); // XXX
|
||||
|
||||
ridtpl = tupleCatTuple(ridtpl,union_typ_tup);
|
||||
tupleFree(union_typ_tup);
|
||||
|
||||
size_t tplLen;
|
||||
byte * tplBytes = byteTuple(ridtpl,&tplLen);
|
||||
|
||||
ThashInsert(xid,context->hash,(byte*)q->tbl,strlen(q->tbl)+1,tplBytes,tplLen);
|
||||
free(tplBytes);
|
||||
return 1;
|
||||
}
|
6
src/apps/referential/ddl.h
Normal file
6
src/apps/referential/ddl.h
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef DDL_H
|
||||
#define DDL_H
|
||||
#include "algebra.h"
|
||||
#include "lang/ast.h"
|
||||
int ReferentialDDL_CreateTable(int xid, ReferentialAlgebra_context_t*context, create *q);
|
||||
#endif //DDL_H
|
|
@ -1,9 +1,13 @@
|
|||
#define _GNU_SOURCE
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <stasis/transactional.h>
|
||||
#include "dml.h"
|
||||
#include "algebra.h"
|
||||
/*
|
||||
int executeInsert(int xid, recordid tables, char * insert) {
|
||||
char * linecopy = strdup(insert+strlen("insert"));
|
||||
char * strtoks;
|
||||
|
@ -61,3 +65,89 @@ int executeDelete(int xid, recordid tables, char * delete) {
|
|||
free(linecopy);
|
||||
return 1;
|
||||
}
|
||||
*/
|
||||
static recordid ReferentialDML_lookupTableRid(int xid, ReferentialAlgebra_context_t*context, char * tablename) {
|
||||
expr_list * results = 0;
|
||||
char * line;
|
||||
asprintf(&line, "query {p ($1,$2,$3) {s ($0=\"%s\") TABLES} }", tablename);
|
||||
|
||||
//XXX memory leak!
|
||||
parse(line,&results);
|
||||
|
||||
assert(results); //XXX
|
||||
assert(results->count == 1); //XXX
|
||||
|
||||
lladdIterator_t * it = ReferentialAlgebra_ExecuteQuery(xid, context, results->ents[0]->u.q);
|
||||
recordid tableRid;
|
||||
|
||||
if(it) {
|
||||
int first = 1;
|
||||
while(Titerator_next(xid,it)) {
|
||||
assert(first);
|
||||
first = 0;
|
||||
byte * tup;
|
||||
Titerator_value(xid, it, &tup);
|
||||
tableRid = ridTuple(*(tuple_t*)tup);
|
||||
}
|
||||
Titerator_close(xid, it);
|
||||
} else {
|
||||
abort(); //XXX
|
||||
}
|
||||
return tableRid;
|
||||
}
|
||||
|
||||
int ReferentialDML_InsertTuple(int xid, ReferentialAlgebra_context_t*context, char * tablename, tuple_t t) {
|
||||
//XXX assumes table format is key value, starting with a string.
|
||||
tuple_t val = tupleTail(t, 1);
|
||||
size_t val_len;
|
||||
byte * val_byte = byteTuple(val,&val_len);
|
||||
|
||||
recordid tableRid = ReferentialDML_lookupTableRid(xid,context,tablename);
|
||||
|
||||
if(t.type[0] == string_typ) {
|
||||
ThashInsert(xid, tableRid, (byte*)t.col[0].string, 1+strlen(t.col[0].string), val_byte, val_len);
|
||||
} else if(t.type[0] == int64_typ) {
|
||||
abort(); // int keys not supported yet
|
||||
ThashInsert(xid, tableRid, (byte*)&t.col[0].int64, sizeof(int64_t), val_byte, val_len);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
||||
free(val_byte);
|
||||
tupleFree(val);
|
||||
return 0;
|
||||
}
|
||||
int ReferentialDML_DeleteTuple(int xid, ReferentialAlgebra_context_t*context, char * tablename, tuple_t t) {
|
||||
//XXX assumes table format is key value, starting with a string.
|
||||
// tuple_t val = tupleTail(t, 1);
|
||||
// size_t val_len;
|
||||
// byte * val_byte = byteTuple(val,&val_len);
|
||||
|
||||
recordid tableRid = ReferentialDML_lookupTableRid(xid,context,tablename);
|
||||
|
||||
if(t.type[0] == string_typ) {
|
||||
ThashRemove(xid, tableRid, (byte*)t.col[0].string, 1+strlen(t.col[0].string)); //, val_byte, val_len);
|
||||
} else if(t.type[0] == int64_typ) {
|
||||
abort(); // int keys not supported yet
|
||||
ThashRemove(xid, tableRid, (byte*)&t.col[0].int64, sizeof(int64_t)); //, val_byte, val_len);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
||||
//free(val_byte);
|
||||
//tupleFree(val);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ReferentialDML_ExecuteInsert(int xid, ReferentialAlgebra_context_t*context, insert *i) {
|
||||
tuple_t t = tupleVal_tuple(i->t);
|
||||
int ret = ReferentialDML_InsertTuple(xid, context, i->tbl, t);
|
||||
tupleFree(t);
|
||||
return ret;
|
||||
}
|
||||
int ReferentialDML_ExecuteDelete(int xid, ReferentialAlgebra_context_t*context, delete *d) {
|
||||
tuple_t t = tupleVal_tuple(d->t);
|
||||
int ret = ReferentialDML_DeleteTuple(xid, context, d->tbl, t);
|
||||
tupleFree(t);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include <stasis/transactional.h>
|
||||
#include "algebra.h"
|
||||
#include "lang/ast.h"
|
||||
|
||||
int executeDelete(int xid, recordid tables, char * delete);
|
||||
int executeInsert(int xid, recordid tables, char *insert);
|
||||
int ReferentialDML_ExecuteInsert(int xid, ReferentialAlgebra_context_t*context, insert *i);
|
||||
int ReferentialDML_ExecuteDelete(int xid, ReferentialAlgebra_context_t*context, delete *i);
|
||||
|
|
10
src/apps/referential/lang/CMakeLists.txt
Normal file
10
src/apps/referential/lang/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
BISON_TARGET(RefParser ${CMAKE_CURRENT_SOURCE_DIR}/parse.y ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c)
|
||||
FLEX_TARGET(RefParser ${CMAKE_CURRENT_SOURCE_DIR}/lexer.lex ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c)
|
||||
#SET(INCLUDE_DIR ${INCLUDE_DIR} ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
#COPY_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ast.h ${CMAKE_CURRENT_BINARY_DIR}/ast.h)
|
||||
ADD_LIBRARY(refparse ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c ${CMAKE_CURRENT_SOURCE_DIR}/ast.c)
|
||||
ADD_EXECUTABLE(parser ${CMAKE_CURRENT_BINARY_DIR}/lex.yy.c ${CMAKE_CURRENT_BINARY_DIR}/y.tab.c ${CMAKE_CURRENT_SOURCE_DIR}/ast.c ${CMAKE_CURRENT_SOURCE_DIR}/parse.c)
|
||||
SET_TARGET_PROPERTIES(refparse PROPERTIES COMPILE_FLAGS "-Wno-implicit -Wno-unused -I ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
SET_TARGET_PROPERTIES(parser PROPERTIES COMPILE_FLAGS "-Wno-implicit -Wno-unused -I ${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
ADD_TEST(test_parser ${CMAKE_CURRENT_SOURCE_DIR}/test_parser.pl)
|
||||
|
368
src/apps/referential/lang/ast.c
Normal file
368
src/apps/referential/lang/ast.c
Normal file
|
@ -0,0 +1,368 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "ast.h"
|
||||
|
||||
/*
|
||||
int walk(const expr_list * el) {
|
||||
return walk_expr_list(el);
|
||||
}
|
||||
|
||||
#define WALK_LIST(type, child_type) \
|
||||
int walk_##type(const type * x) { \
|
||||
int ret = 0; \
|
||||
for(int i = 0; i < x->count; i++) { \
|
||||
ret |= walk_##child_type(x->ents[i]); \
|
||||
} \
|
||||
return ret; \
|
||||
}
|
||||
|
||||
#define WALK_LIST_DECL(type) \
|
||||
int walk_##type(const type * x);
|
||||
|
||||
#define WALK_LEAF(type) \
|
||||
int walk_##type(const type * x) { \
|
||||
return 0; \
|
||||
}
|
||||
|
||||
#define WALK_LEAF_DECL(type) \
|
||||
int walk_##type(const type * x);
|
||||
|
||||
WALK_LIST_DECL(expr_list)
|
||||
WALK_LEAF_DECL(expr)
|
||||
|
||||
WALK_LIST(expr_list, expr)
|
||||
WALK_LEAF(expr)
|
||||
*/
|
||||
char * astrncat(char * dest, const char * src) {
|
||||
size_t destlen = dest ? strlen(dest) : 0;
|
||||
size_t srclen = strlen(src);
|
||||
dest = realloc(dest, destlen+srclen+1);
|
||||
if(srclen && !destlen) { dest[0] = 0; }
|
||||
/* printf("src =>%s<=",src); */
|
||||
strcat(dest, src);
|
||||
return dest;
|
||||
}
|
||||
char * afstrncat(char *dest, char * src) {
|
||||
dest = astrncat(dest, src);
|
||||
free(src);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
char * pp_expr_list(const expr_list* el) {
|
||||
char * ret = 0;
|
||||
int i;
|
||||
for(i = 0; i < el->count; i++) {
|
||||
ret = afstrncat(ret, pp_expr(el->ents[i]));
|
||||
ret = astrncat(ret, "\n");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_expr(const expr* e) {
|
||||
char * ret = 0;
|
||||
switch(e->typ) {
|
||||
case query_typ: {
|
||||
ret = astrncat(ret, "query ");
|
||||
ret = afstrncat(ret, pp_union_qry(e->u.q));
|
||||
} break;
|
||||
case insert_typ: {
|
||||
ret = astrncat(ret, "insert ");
|
||||
ret = afstrncat(ret, pp_insert(e->u.i));
|
||||
} break;
|
||||
case delete_typ: {
|
||||
ret = astrncat(ret, "delete ");
|
||||
ret = afstrncat(ret, pp_delete(e->u.d));
|
||||
} break;
|
||||
case create_typ: {
|
||||
ret = astrncat(ret, "create ");
|
||||
ret = afstrncat(ret, pp_create(e->u.c));
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_query(const query* q) {
|
||||
char * ret = 0;
|
||||
switch(q->typ) {
|
||||
case scan_typ: {
|
||||
ret = afstrncat(ret, pp_q_scan(q->u.scn));
|
||||
} break;
|
||||
case table_star_typ: {
|
||||
ret = astrncat(ret, "*");
|
||||
} break;
|
||||
case select_typ: {
|
||||
ret = astrncat(ret, "{s ");
|
||||
ret = afstrncat(ret, pp_union_cmp(q->u.sel->t));
|
||||
ret = astrncat(ret, " ");
|
||||
ret = afstrncat(ret, pp_union_qry(q->u.sel->q));
|
||||
ret = astrncat(ret, "}");
|
||||
} break;
|
||||
case project_typ: {
|
||||
ret = astrncat(ret, "{p ");
|
||||
ret = afstrncat(ret, pp_col_tuple(q->u.prj->t));
|
||||
ret = astrncat(ret, " ");
|
||||
ret = afstrncat(ret, pp_union_qry(q->u.prj->q));
|
||||
ret = astrncat(ret, "}");
|
||||
} break;
|
||||
case join_typ: {
|
||||
ret = astrncat(ret, "{j ");
|
||||
ret = afstrncat(ret, pp_cmp_tuple(q->u.jn->t));
|
||||
ret = astrncat(ret, " ");
|
||||
ret = afstrncat(ret, pp_union_qry(q->u.jn->lhs));
|
||||
ret = astrncat(ret, " ");
|
||||
ret = afstrncat(ret, pp_union_qry(q->u.jn->rhs));
|
||||
ret = astrncat(ret, "}");
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_create(const create * c){
|
||||
char * ret = 0;
|
||||
ret = astrncat(ret, c->tbl);
|
||||
ret = astrncat(ret, " ");
|
||||
ret = astrncat(ret, pp_union_typ(c->schema));
|
||||
return ret;
|
||||
}
|
||||
char * pp_q_scan(const q_scan* s) {
|
||||
char * ret = 0;
|
||||
asprintf(&ret, "%s", s->table);
|
||||
return ret;
|
||||
}
|
||||
char * pp_insert(const insert * i) {
|
||||
char * ret = 0;
|
||||
asprintf(&ret, "%s ", i->tbl);
|
||||
ret = afstrncat(ret, pp_val_tuple(i->t));
|
||||
return ret;
|
||||
}
|
||||
char * pp_delete(const delete * d) {
|
||||
char * ret = 0;
|
||||
asprintf(&ret, "%s ", d->tbl);
|
||||
ret = afstrncat(ret, pp_val_tuple(d->t));
|
||||
return ret;
|
||||
}
|
||||
/*char * pp_pat_tuple(const pat_tuple * p) {
|
||||
int i;
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
ret = astrncat(ret,"(");
|
||||
for(i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,", ");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = afstrncat(ret, pp_pat_entry(p->ents[i]));
|
||||
}
|
||||
ret = astrncat(ret,")");
|
||||
return ret;
|
||||
} */
|
||||
|
||||
char * pp_val_tuple(const val_tuple * p) {
|
||||
int i;
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
ret = astrncat(ret,"(");
|
||||
for(i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,", ");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = afstrncat(ret, pp_val_entry(p->ents[i]));
|
||||
}
|
||||
ret = astrncat(ret,")");
|
||||
return ret;
|
||||
}
|
||||
char * pp_col_tuple(const col_tuple * p) {
|
||||
int i;
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
ret = astrncat(ret,"(");
|
||||
for(i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,", ");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = afstrncat(ret, pp_col_entry(p->ents[i]));
|
||||
}
|
||||
ret = astrncat(ret,")");
|
||||
return ret;
|
||||
}
|
||||
char * pp_cmp_tuple(const cmp_tuple * p) {
|
||||
int i;
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
ret = astrncat(ret,"(");
|
||||
for(i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,", ");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = afstrncat(ret, pp_cmp_entry(p->ents[i]));
|
||||
}
|
||||
ret = astrncat(ret,")");
|
||||
return ret;
|
||||
}
|
||||
char * pp_typ_tuple(const typ_tuple * p) {
|
||||
int i;
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
ret = astrncat(ret,"(");
|
||||
for(i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,", ");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = afstrncat(ret, pp_typ_entry(p->ents[i]));
|
||||
}
|
||||
ret = astrncat(ret,")");
|
||||
return ret;
|
||||
}
|
||||
char * pp_union_qry(const union_qry * p) {
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
for(int i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,"|");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = astrncat(ret, pp_query(p->ents[i]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_union_typ(const union_typ * p) {
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
for(int i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,"|");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = astrncat(ret, pp_typ_tuple(p->ents[i]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_union_cmp(const union_cmp * p) {
|
||||
char * ret = 0;
|
||||
int first = 1;
|
||||
for(int i = 0; i < p->count; i++) {
|
||||
if(!first) {
|
||||
ret = astrncat(ret,"|");
|
||||
} else {
|
||||
first = 0;
|
||||
}
|
||||
ret = astrncat(ret, pp_cmp_tuple(p->ents[i]));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
/*char * pp_pat_entry(const pat_entry * p) {
|
||||
char * ret = 0;
|
||||
switch(p->typ) {
|
||||
case star_typ: {
|
||||
asprintf(&ret,"*");
|
||||
} break;
|
||||
case ident_typ: {
|
||||
asprintf(&ret,"%s",p->u.ident);
|
||||
} break;
|
||||
case int_typ: {
|
||||
asprintf(&ret,"%d",p->u.integ);
|
||||
} break;
|
||||
case string_typ: {
|
||||
asprintf(&ret,"\"%s\"",p->u.str);
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
return ret;
|
||||
} */
|
||||
char * pp_val_entry(const val_entry * p) {
|
||||
char * ret = 0;
|
||||
switch(p->typ) {
|
||||
case ident_typ: {
|
||||
asprintf(&ret,"%s",p->u.ident);
|
||||
} break;
|
||||
case int64_typ: {
|
||||
asprintf(&ret,"%lld",(long long int)p->u.integ);
|
||||
} break;
|
||||
case string_typ: {
|
||||
asprintf(&ret,"\"%s\"",p->u.str);
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_col_entry(const col_entry * p) {
|
||||
char * ret = 0;
|
||||
switch(p->typ) {
|
||||
case colint_typ: {
|
||||
asprintf(&ret,"$%d",p->u.colnum);
|
||||
} break;
|
||||
case colstr_typ: {
|
||||
asprintf(&ret,"$%s",p->u.colstr);
|
||||
} break;
|
||||
case string_typ: {
|
||||
asprintf(&ret,"%s",p->u.colstr);
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_cmp_entry(const cmp_entry * p) {
|
||||
char * ret = 0;
|
||||
switch(p->lhs_typ) {
|
||||
case col_typ: {
|
||||
ret = afstrncat(ret, pp_col_entry(p->lhs.colent));
|
||||
} break;
|
||||
case val_typ: {
|
||||
ret = afstrncat(ret, pp_val_entry(p->lhs.valent));
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
|
||||
switch(p->comparator) {
|
||||
case equal_typ: {
|
||||
ret = astrncat(ret, "=");
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
|
||||
switch(p->rhs_typ) {
|
||||
case col_typ: {
|
||||
ret = afstrncat(ret, pp_col_entry(p->rhs.colent));
|
||||
} break;
|
||||
case string_typ: {
|
||||
ret = afstrncat(ret, pp_col_entry(p->rhs.colent));
|
||||
} break;
|
||||
case val_typ: {
|
||||
ret = afstrncat(ret, pp_val_entry(p->rhs.valent));
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
char * pp_typ_entry(const typ_entry * p) {
|
||||
char * ret = 0;
|
||||
switch(p->typ) {
|
||||
case typ_typ: {
|
||||
switch(p->u.type) {
|
||||
case int64_typ: {
|
||||
ret = astrncat(ret, "int");
|
||||
} break;
|
||||
case string_typ: {
|
||||
ret = astrncat(ret, "string");
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
return ret;
|
||||
}
|
246
src/apps/referential/lang/ast.h
Normal file
246
src/apps/referential/lang/ast.h
Normal file
|
@ -0,0 +1,246 @@
|
|||
#ifndef _REFER_AST_H
|
||||
#define _REFER_AST_H
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct expr_list expr_list;
|
||||
typedef struct expr expr;
|
||||
typedef struct query query;
|
||||
typedef struct insert insert;
|
||||
typedef struct delete delete;
|
||||
typedef struct create create;
|
||||
|
||||
typedef struct q_scan q_scan;
|
||||
typedef struct q_select q_select;
|
||||
typedef struct q_project q_project;
|
||||
typedef struct q_join q_join;
|
||||
|
||||
//typedef struct pat_tuple pat_tuple;
|
||||
typedef struct cmp_tuple cmp_tuple;
|
||||
typedef struct col_tuple col_tuple;
|
||||
typedef struct val_tuple val_tuple;
|
||||
typedef struct typ_tuple typ_tuple;
|
||||
|
||||
typedef struct union_typ union_typ;
|
||||
typedef struct union_cmp union_cmp;
|
||||
typedef struct union_qry union_qry;
|
||||
|
||||
//typedef struct pat_entry pat_entry;
|
||||
typedef struct cmp_entry cmp_entry;
|
||||
typedef struct col_entry col_entry;
|
||||
typedef struct val_entry val_entry;
|
||||
typedef struct typ_entry typ_entry;
|
||||
|
||||
typedef char* table;
|
||||
typedef char* ident;
|
||||
|
||||
typedef int val_ent_wildcard;
|
||||
typedef char* val_ent_ident;
|
||||
typedef int64_t val_ent_int;
|
||||
typedef char* val_ent_string;
|
||||
|
||||
#include "../tuple.h" // for datatypes.
|
||||
/*typedef enum {
|
||||
integer_data_typ,
|
||||
string_data_typ
|
||||
} val_ent_typ;*/
|
||||
typedef int val_col_int;
|
||||
typedef char* val_col_string;
|
||||
|
||||
struct expr_list {
|
||||
int count;
|
||||
expr ** ents;
|
||||
};
|
||||
char * pp_expr_list(const expr_list*);
|
||||
struct expr {
|
||||
enum expr_typ {
|
||||
query_typ,
|
||||
insert_typ,
|
||||
delete_typ,
|
||||
create_typ
|
||||
} typ;
|
||||
union {
|
||||
union_qry * q;
|
||||
insert * i;
|
||||
delete * d;
|
||||
create * c;
|
||||
} u;
|
||||
};
|
||||
char * pp_expr(const expr*);
|
||||
|
||||
struct query {
|
||||
enum query_typ {
|
||||
scan_typ,
|
||||
table_star_typ,
|
||||
select_typ,
|
||||
project_typ,
|
||||
join_typ
|
||||
} typ;
|
||||
union {
|
||||
q_scan * scn;
|
||||
q_select * sel;
|
||||
q_project* prj;
|
||||
q_join * jn;
|
||||
} u;
|
||||
};
|
||||
char * pp_query(const query*);
|
||||
struct create {
|
||||
char * tbl;
|
||||
union_typ * schema;
|
||||
};
|
||||
char * pp_create(const create*);
|
||||
|
||||
struct q_scan {
|
||||
char * table;
|
||||
};
|
||||
char * pp_q_scan(const q_scan*);
|
||||
|
||||
struct q_select {
|
||||
union_cmp * t;
|
||||
union_qry * q;
|
||||
};
|
||||
//char * pp_q_select(const q_select*);
|
||||
|
||||
struct q_project {
|
||||
col_tuple * t;
|
||||
union_qry * q;
|
||||
};
|
||||
//char * pp_q_project(const q_project*);
|
||||
|
||||
struct q_join {
|
||||
cmp_tuple * t;
|
||||
union_qry * lhs;
|
||||
union_qry * rhs;
|
||||
};
|
||||
//char * pp_q_join(const q_join*);
|
||||
|
||||
struct insert {
|
||||
table tbl;
|
||||
val_tuple * t;
|
||||
};
|
||||
char * pp_insert(const insert*);
|
||||
|
||||
struct delete {
|
||||
table tbl;
|
||||
val_tuple * t;
|
||||
};
|
||||
char * pp_delete(const delete*);
|
||||
|
||||
enum cmp_typ {
|
||||
equal_typ
|
||||
};
|
||||
|
||||
/*struct pat_tuple {
|
||||
int count;
|
||||
pat_entry ** ents; // XXX tuple type?
|
||||
};
|
||||
char * pp_pat_tuple(const pat_tuple*); */
|
||||
|
||||
struct val_tuple {
|
||||
int count;
|
||||
val_entry ** ents;
|
||||
};
|
||||
char * pp_val_tuple(const val_tuple*);
|
||||
|
||||
struct col_tuple {
|
||||
int count;
|
||||
col_entry ** ents;
|
||||
};
|
||||
char * pp_col_tuple(const col_tuple*);
|
||||
struct cmp_tuple {
|
||||
int count;
|
||||
cmp_entry ** ents;
|
||||
};
|
||||
char * pp_cmp_tuple(const cmp_tuple*);
|
||||
struct typ_tuple {
|
||||
int count;
|
||||
typ_entry ** ents;
|
||||
};
|
||||
char * pp_typ_tuple(const typ_tuple*);
|
||||
/*struct pat_entry {
|
||||
enum tup_entry_typ typ;
|
||||
union {
|
||||
val_ent_wildcard wc;
|
||||
val_ent_ident ident;
|
||||
val_ent_int integ;
|
||||
val_ent_string str;
|
||||
} u;
|
||||
};
|
||||
char * pp_pat_entry(const pat_entry*); */
|
||||
struct val_entry {
|
||||
datatype_t typ;
|
||||
union {
|
||||
val_ent_ident ident;
|
||||
val_ent_int integ;
|
||||
val_ent_string str;
|
||||
} u;
|
||||
};
|
||||
char * pp_val_entry(const val_entry*);
|
||||
struct col_entry {
|
||||
datatype_t typ;
|
||||
union {
|
||||
val_col_string colstr;
|
||||
val_col_int colnum;
|
||||
} u;
|
||||
};
|
||||
char * pp_col_entry(const col_entry*);
|
||||
struct typ_entry {
|
||||
datatype_t typ;
|
||||
union {
|
||||
datatype_t type;
|
||||
} u;
|
||||
};
|
||||
char * pp_typ_entry(const typ_entry*);
|
||||
|
||||
struct union_typ {
|
||||
int count;
|
||||
typ_tuple ** ents;
|
||||
};
|
||||
char * pp_union_typ(const union_typ*);
|
||||
struct union_cmp {
|
||||
int count;
|
||||
cmp_tuple ** ents;
|
||||
};
|
||||
char * pp_union_cmp(const union_cmp*);
|
||||
struct union_qry {
|
||||
int count;
|
||||
query ** ents;
|
||||
};
|
||||
char * pp_union_qry(const union_qry*);
|
||||
|
||||
enum cmp_side_typ {
|
||||
col_typ,
|
||||
val_typ
|
||||
};
|
||||
struct cmp_entry {
|
||||
enum cmp_side_typ lhs_typ;
|
||||
enum cmp_side_typ rhs_typ;
|
||||
enum cmp_typ comparator;
|
||||
union {
|
||||
col_entry * colent;
|
||||
val_entry * valent;
|
||||
} lhs;
|
||||
union {
|
||||
col_entry * colent;
|
||||
val_entry * valent;
|
||||
} rhs;
|
||||
};
|
||||
char * pp_cmp_entry(const cmp_entry*);
|
||||
|
||||
|
||||
//int yyparse();
|
||||
extern expr_list * results;
|
||||
void parse(char *buf, expr_list **result);
|
||||
|
||||
char * astrncat(char *,const char *);
|
||||
char * afstrncat(char *,char *);
|
||||
|
||||
/*struct table {
|
||||
char * name;
|
||||
};
|
||||
char * pp_table(table*); */
|
||||
|
||||
/*struct ident {
|
||||
char * name;
|
||||
};
|
||||
char * pp_ident(ident*); */
|
||||
#endif// _REFER_AST_H
|
79
src/apps/referential/lang/lexer.lex
Normal file
79
src/apps/referential/lang/lexer.lex
Normal file
|
@ -0,0 +1,79 @@
|
|||
%{
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "ast.h"
|
||||
#include "y.tab.h"
|
||||
#include "parser_private.h"
|
||||
//#define DBG(x) printf("%s\t",x); ECHO
|
||||
#define DBG(x)
|
||||
|
||||
#define PARM yyget_extra(yyscanner)
|
||||
|
||||
#define YY_INPUT(buffer, res, max_size) \
|
||||
do { \
|
||||
if (PARM->pos >= PARM->length) \
|
||||
res = YY_NULL; \
|
||||
else \
|
||||
{ \
|
||||
res = PARM->length - PARM->pos; \
|
||||
res > (int)max_size ? res = max_size : 0; \
|
||||
memcpy(buffer, PARM->buf + PARM->pos, res); \
|
||||
PARM->pos += res; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
//%option reentrant bison-bridge
|
||||
//%option noyywrap
|
||||
//%option nounput
|
||||
|
||||
%}
|
||||
|
||||
%option reentrant bison-bridge
|
||||
%option noyywrap
|
||||
%option nounput
|
||||
|
||||
%START INTUPLE
|
||||
|
||||
%%
|
||||
"(" {DBG("LPAREN"); BEGIN INTUPLE; return LPAREN;}
|
||||
")" {DBG("RPAREN"); BEGIN 0; return RPAREN;}
|
||||
"{" {DBG("LBRACKET"); return LBRACKET;}
|
||||
"}" {DBG("RBRACKET"); return RBRACKET;}
|
||||
"," {DBG("COMMA"); return COMMA;}
|
||||
"|" {DBG("BAR"); return BAR;}
|
||||
"*" {DBG("STAR"); return STAR;}
|
||||
"=" {DBG("EQUAL"); return EQUAL;}
|
||||
"insert" {DBG("INSERT"); return INSERT;}
|
||||
"i" {DBG("INSERT"); return INSERT;}
|
||||
"delete" {DBG("DELETE"); return DELETE;}
|
||||
"d" {DBG("DELETE"); return DELETE;}
|
||||
"query" {DBG("QUERY"); return QUERY;}
|
||||
"q" {DBG("QUERY"); return QUERY;}
|
||||
"create" {DBG("CREATE"); return CREATE;}
|
||||
"c" {DBG("CREATE"); return CREATE;}
|
||||
"string" {DBG("STRING_TYPE"); return STRING_TYPE;}
|
||||
"int" {DBG("INT_TYPE"); return INT_TYPE;}
|
||||
"s" {DBG("SELECT"); return SELECT;}
|
||||
"select" {DBG("SELECT"); return SELECT;}
|
||||
"p" {DBG("PROJECT"); return PROJECT;}
|
||||
"project" {DBG("PROJECT"); return PROJECT;}
|
||||
"j" {DBG("JOIN"); return JOIN;}
|
||||
"join" {DBG("JOIN"); return JOIN;}
|
||||
<INTUPLE>[A-Za-z_][A-Za-z0-9_]* {DBG("IDENT"); yylval->string = strdup(yytext);return IDENT; }
|
||||
[A-Za-z_][A-Za-z0-9_]* {DBG("TABLE"); yylval->string = strdup(yytext); return TABLE; }
|
||||
[-+]?[0-9]+ {DBG("INT"); yylval->number = atoi(yytext); /*XXX error checking*/return INT; }
|
||||
$[A-Za-z_][A-Za-z0-9_]* {DBG("COLNAME"); yylval->string = strdup(yytext+1); return COLNAME; }
|
||||
$[1-9][0-9]* {DBG("COLNUM"); yylval->number = atoi(yytext+1); /*XXX*/return COLNUM; }
|
||||
$0 {DBG("COLNUM"); yylval->number = 0; return COLNUM; }
|
||||
|
||||
\"[^"]* {DBG("STRING");
|
||||
if (yytext[yyleng-1] == '\\') {
|
||||
yymore();
|
||||
} else {
|
||||
input(yyscanner);
|
||||
yylval->string = strdup(yytext+1);
|
||||
return STRING;
|
||||
}
|
||||
}
|
||||
[ \t\n] DBG("WS");
|
||||
%%
|
25
src/apps/referential/lang/parse.c
Normal file
25
src/apps/referential/lang/parse.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
#include "ast.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
int main (int argc, char * argv[]) {
|
||||
char * in = 0;
|
||||
size_t len = 0;
|
||||
char * buf = 0;
|
||||
int read;
|
||||
while(-1!=(read = getline(&in, &len, stdin))) {
|
||||
// printf("->%s<-",in);
|
||||
// fflush(NULL);
|
||||
buf = astrncat(buf,in);
|
||||
}
|
||||
// int ret = yyparse();
|
||||
expr_list * results = 0;
|
||||
|
||||
parse(buf, &results);
|
||||
if(results) {
|
||||
char * str = pp_expr_list(results);
|
||||
printf("%s", str);
|
||||
free(str);
|
||||
}
|
||||
return results == 0;
|
||||
}
|
295
src/apps/referential/lang/parse.y
Normal file
295
src/apps/referential/lang/parse.y
Normal file
|
@ -0,0 +1,295 @@
|
|||
%{
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "ast.h"
|
||||
|
||||
#include "/home/sears/stasis/src/apps/referential/lang/parser_private.h"
|
||||
|
||||
|
||||
void parse(char *buf, expr_list **result)
|
||||
{
|
||||
parse_parm pp;
|
||||
|
||||
pp.buf = buf;
|
||||
pp.length = strlen(buf);
|
||||
pp.pos = 0;
|
||||
*result = 0;
|
||||
yylex_init(&pp.yyscanner);
|
||||
yyset_extra(&pp, pp.yyscanner);
|
||||
yyparse(&pp, pp.yyscanner);
|
||||
*result = pp.result;
|
||||
yylex_destroy(pp.yyscanner);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%pure_parser
|
||||
%parse-param {parse_parm *parm}
|
||||
%parse-param {void *scanner}
|
||||
%lex-param {yyscan_t *scanner}
|
||||
|
||||
//%}
|
||||
|
||||
%token LPAREN RPAREN LBRACKET RBRACKET
|
||||
%token COMMA BAR STAR EQUAL
|
||||
%token SELECT PROJECT JOIN
|
||||
%token QUERY INSERT DELETE CREATE
|
||||
|
||||
/* The reserved words "string" and "int" */
|
||||
%token STRING_TYPE
|
||||
%token INT_TYPE
|
||||
|
||||
|
||||
|
||||
%union {
|
||||
val_entry * val_ent;
|
||||
col_entry * col_ent;
|
||||
cmp_entry * cmp_ent;
|
||||
typ_entry * typ_ent;
|
||||
val_tuple * val_tup;
|
||||
col_tuple * col_tup;
|
||||
cmp_tuple * cmp_tup;
|
||||
typ_tuple * typ_tup;
|
||||
union_typ * union_typ;
|
||||
union_cmp * union_cmp;
|
||||
union_qry * union_qry;
|
||||
insert * ins_expr;
|
||||
delete * del_expr;
|
||||
query * qry_expr;
|
||||
create * crt_expr;
|
||||
expr * expr;
|
||||
expr_list * exprs;
|
||||
char * string;
|
||||
int number;
|
||||
enum cmp_typ comparator;
|
||||
}
|
||||
|
||||
%token <string> TABLE
|
||||
%token <string> IDENT
|
||||
%token <string> COLNAME
|
||||
%token <number> COLNUM
|
||||
%token <string> STRING
|
||||
%token <number> INT
|
||||
|
||||
%type <val_ent> val
|
||||
%type <col_ent> col
|
||||
%type <cmp_ent> cmp
|
||||
%type <typ_ent> typ
|
||||
%type <comparator> test
|
||||
|
||||
%type <val_tup> val_list val_tuple
|
||||
%type <col_tup> col_list col_tuple
|
||||
%type <cmp_tup> cmp_list cmp_tuple
|
||||
%type <typ_tup> typ_list typ_tuple
|
||||
|
||||
%type <union_typ> union_typ
|
||||
%type <union_cmp> union_cmp
|
||||
%type <union_qry> union_qry
|
||||
|
||||
%type <ins_expr> insert
|
||||
%type <del_expr> delete
|
||||
%type <qry_expr> query
|
||||
%type <crt_expr> create
|
||||
%type <expr> expr
|
||||
%type <exprs> expr_list
|
||||
|
||||
%%
|
||||
|
||||
expr_list : expr { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; parm->result = $$; }
|
||||
| expr_list expr
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $2;
|
||||
}
|
||||
|
||||
expr : QUERY union_qry {
|
||||
$$ = malloc(sizeof(*$$));
|
||||
$$->typ = query_typ;
|
||||
$$->u.q = $2;
|
||||
}
|
||||
| INSERT insert {
|
||||
$$ = malloc(sizeof(*$$));
|
||||
$$->typ = insert_typ;
|
||||
$$->u.i = $2;
|
||||
}
|
||||
| DELETE delete {
|
||||
$$ = malloc(sizeof(*$$));
|
||||
$$->typ = delete_typ;
|
||||
$$->u.d = $2;
|
||||
}
|
||||
| CREATE create {
|
||||
$$ = malloc(sizeof(*$$));
|
||||
$$->typ = create_typ;
|
||||
$$->u.c = $2;
|
||||
}
|
||||
union_qry : query { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; }
|
||||
| union_qry BAR query
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $3;
|
||||
}
|
||||
|
||||
query : TABLE
|
||||
{
|
||||
$$ = malloc(sizeof(*$$)); $$->typ=scan_typ;
|
||||
$$->u.scn = malloc(sizeof(*$$->u.scn));
|
||||
$$->u.scn->table = $1;
|
||||
}
|
||||
| STAR
|
||||
{
|
||||
$$ = malloc(sizeof(*$$)); $$->typ=table_star_typ;
|
||||
$$->u.scn = 0;
|
||||
}
|
||||
| LBRACKET SELECT union_cmp union_qry RBRACKET
|
||||
{
|
||||
$$ = malloc(sizeof(*$$)); $$->typ=select_typ;
|
||||
$$->u.sel = malloc(sizeof(*$$->u.sel));
|
||||
$$->u.sel->t = $3;
|
||||
$$->u.sel->q = $4;
|
||||
}
|
||||
| LBRACKET PROJECT col_tuple union_qry RBRACKET
|
||||
{
|
||||
$$ = malloc(sizeof(*$$)); $$->typ=project_typ;
|
||||
$$->u.prj = malloc(sizeof(*$$->u.prj));
|
||||
$$->u.prj->t = $3;
|
||||
$$->u.prj->q = $4;
|
||||
}
|
||||
| LBRACKET JOIN cmp_tuple union_qry union_qry RBRACKET
|
||||
{
|
||||
$$ = malloc(sizeof(*$$)); $$->typ=join_typ;
|
||||
$$->u.jn = malloc(sizeof(*$$->u.jn));
|
||||
$$->u.jn->t = $3;
|
||||
$$->u.jn->lhs = $4;
|
||||
$$->u.jn->rhs = $5;
|
||||
};
|
||||
|
||||
insert : TABLE val_tuple { $$ = malloc(sizeof(*$$)); $$->tbl = $1; $$->t = $2; }
|
||||
delete : TABLE val_tuple { $$ = malloc(sizeof(*$$)); $$->tbl = $1; $$->t = $2; }
|
||||
|
||||
create : TABLE union_typ { $$ = malloc(sizeof(*$$)); $$->tbl = $1; $$->schema = $2; }
|
||||
|
||||
val_tuple : LPAREN val_list RPAREN { $$ = $2; }
|
||||
|
||||
val_list : val { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; }
|
||||
| val_list COMMA val
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $3;
|
||||
}
|
||||
|
||||
val : IDENT { $$ = malloc(sizeof(*$$)); $$->typ = ident_typ; $$->u.ident = $1; }
|
||||
| INT { $$ = malloc(sizeof(*$$)); $$->typ = int64_typ; $$->u.integ = $1; }
|
||||
| STRING { $$ = malloc(sizeof(*$$)); $$->typ = string_typ; $$->u.str = $1; }
|
||||
|
||||
col_tuple : LPAREN col_list RPAREN { $$ = $2; }
|
||||
| LPAREN RPAREN { $$ = malloc(sizeof(*$$)); $$->count = 0; $$->ents = malloc(1); }
|
||||
|
||||
col_list : col { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; }
|
||||
| col_list COMMA col
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $3;
|
||||
}
|
||||
|
||||
col : COLNUM { $$ = malloc(sizeof(*$$)); $$->typ = colint_typ; $$->u.colnum = $1; }
|
||||
| COLNAME { $$ = malloc(sizeof(*$$)); $$->typ = colstr_typ; $$->u.colstr = $1; }
|
||||
|
||||
cmp_tuple : LPAREN cmp_list RPAREN { $$ = $2; }
|
||||
| LPAREN RPAREN { $$ = malloc(sizeof(*$$)); $$->count = 0; $$->ents = malloc(sizeof(char)); }
|
||||
|
||||
cmp_list : cmp { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; }
|
||||
| cmp_list COMMA cmp
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $3;
|
||||
}
|
||||
|
||||
cmp : col test val { $$ = malloc(sizeof(*$$)); $$->lhs_typ = col_typ; $$->lhs.colent = $1;
|
||||
$$->comparator = $2;
|
||||
$$->rhs_typ = val_typ; $$->rhs.valent = $3; }
|
||||
| val test col { $$ = malloc(sizeof(*$$)); $$->lhs_typ = val_typ; $$->lhs.valent = $1;
|
||||
$$->comparator = $2;
|
||||
$$->rhs_typ = col_typ; $$->rhs.colent = $3; }
|
||||
| col test col { $$ = malloc(sizeof(*$$)); $$->lhs_typ = col_typ; $$->lhs.colent = $1;
|
||||
$$->comparator = $2;
|
||||
$$->rhs_typ = col_typ; $$->rhs.colent = $3; }
|
||||
| val test val { $$ = malloc(sizeof(*$$)); $$->lhs_typ = val_typ; $$->lhs.valent = $1;
|
||||
$$->comparator = $2;
|
||||
$$->rhs_typ = val_typ; $$->rhs.valent = $3; }
|
||||
| col { $$ = malloc(sizeof(*$$)); $$->lhs_typ = col_typ; $$->lhs.colent = $1;
|
||||
$$->comparator = equal_typ;
|
||||
$$->rhs_typ = col_typ; $$->rhs.colent = $1; }
|
||||
| IDENT
|
||||
{ $$ = malloc(sizeof(*$$)); $$->lhs_typ = col_typ; $$->lhs.colent = malloc(sizeof(*$$->lhs.colent));
|
||||
$$->lhs.colent->typ=string_typ; $$->lhs.colent->u.colstr=$1;
|
||||
$$->comparator = equal_typ;
|
||||
$$->rhs_typ = col_typ; $$->rhs.colent = malloc(sizeof(*$$->rhs.colent));
|
||||
$$->rhs.colent->typ=string_typ; $$->rhs.colent->u.colstr=$1; }
|
||||
typ_tuple : LPAREN typ_list RPAREN { $$ = $2; }
|
||||
typ_list : typ { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; }
|
||||
| typ_list COMMA typ
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $3;
|
||||
}
|
||||
|
||||
typ : STRING_TYPE
|
||||
{
|
||||
$$ = malloc(sizeof(*$$));
|
||||
$$->typ = typ_typ;
|
||||
$$->u.type = string_typ;
|
||||
}
|
||||
| INT_TYPE
|
||||
{
|
||||
$$ = malloc(sizeof(*$$));
|
||||
$$->typ = typ_typ;
|
||||
$$->u.type = int64_typ;
|
||||
}
|
||||
|
||||
union_typ : typ_tuple { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; }
|
||||
| union_typ BAR typ_tuple
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $3;
|
||||
}
|
||||
|
||||
union_cmp : cmp_tuple { $$ = malloc(sizeof(*$$)); $$->count = 1; $$->ents = malloc(sizeof(*($$->ents))); $$->ents[0] = $1; }
|
||||
| union_cmp BAR cmp_tuple
|
||||
{
|
||||
$$ = $1 ;
|
||||
($$->count)++;
|
||||
$$->ents = realloc($$->ents, sizeof(*($$->ents)) * ($$->count));
|
||||
$$->ents[($$->count)-1] = $3;
|
||||
}
|
||||
|
||||
test : EQUAL { $$ = equal_typ; }
|
||||
|
||||
%%
|
||||
|
||||
int yyerror(parse_parm * param, void * yyscanner, char * errMsg) {
|
||||
printf("Error: %s\n", errMsg);
|
||||
// XXX memory leak?
|
||||
param->result = 0;
|
||||
return 0;
|
||||
}
|
||||
int yywrap () { return 1; }
|
||||
|
||||
//#include "lex.yy.c"
|
||||
|
29
src/apps/referential/lang/parser_private.h
Normal file
29
src/apps/referential/lang/parser_private.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
From:
|
||||
|
||||
http://www.usualcoding.eu/index.php?tag/flex
|
||||
|
||||
*/
|
||||
|
||||
typedef struct parse_parm_s
|
||||
{
|
||||
void *yyscanner;
|
||||
char *buf;
|
||||
int pos;
|
||||
int length;
|
||||
void *result;
|
||||
} parse_parm;
|
||||
|
||||
//void parse(char *buf, expr_list **result);
|
||||
|
||||
|
||||
//#define YYSTYPE
|
||||
|
||||
#define YY_EXTRA_TYPE parse_parm *
|
||||
|
||||
//int yylex(void /*YYSTYPE*/ *, void *);
|
||||
int yylex_init(void **);
|
||||
int yylex_destroy(void *);
|
||||
void yyset_extra(YY_EXTRA_TYPE, void *);
|
||||
int yyparse(parse_parm *, void *);
|
||||
//void yyerror();
|
92
src/apps/referential/lang/test_parser.pl
Executable file
92
src/apps/referential/lang/test_parser.pl
Executable file
|
@ -0,0 +1,92 @@
|
|||
#!/usr/bin/perl -w
|
||||
use strict;
|
||||
|
||||
my @winners;
|
||||
my @losers;
|
||||
|
||||
#
|
||||
# query tests
|
||||
#
|
||||
my $fail = 0;
|
||||
|
||||
push @winners, 'query foo';
|
||||
push @winners, 'query foo1';
|
||||
push @winners, 'query {s ($1=2,$2="asd",$3=x) foo}';
|
||||
push @winners, 'query {p ($1,$2) foo}';
|
||||
push @winners, 'query {j ($1=$4,"foo"=$3,$5=x,3=$6) foo bar}';
|
||||
push @winners, 'query {select ($1=2,$2="asd",$3=x) foo}';
|
||||
push @winners, 'query {project ($1,$2) foo}';
|
||||
push @winners, 'query {join ($1=$4,"foo"=$3,$5=x,3=$6) foo bar}';
|
||||
push @winners, 'query {
|
||||
j
|
||||
($1=$4,"foo"=$3,$5=x,3=$6)
|
||||
{
|
||||
s ($0="a",$2=1) foo
|
||||
}
|
||||
bar
|
||||
}';
|
||||
|
||||
push @winners, 'query {select ($3 = "blue")|($3 = 10) questions_three}';
|
||||
push @winners, 'query {project ($3){select($1="Galahad")questions_three}}';
|
||||
|
||||
push @winners, 'query {join ($MigratorID=$MigratorID) Migrators *}';
|
||||
push @winners, 'query {join ($MigratorID) Migrators { join ($BirdId) Birds *} | Fruits }';
|
||||
push @winners, 'query {join ($Type) * *}';
|
||||
push @winners, 'query {project ($titl) {select ($author="sears") {join (docid) * *}}}';
|
||||
|
||||
push @losers, 'query 1';
|
||||
push @losers, 'query foo 1';
|
||||
push @losers, 'query {p (a,2) foo}';
|
||||
push @losers, 'query {p (1,2) foo}';
|
||||
push @losers, 'query {p ("a",$2) foo}';
|
||||
push @losers, 'query {p ($1,"a") foo}';
|
||||
push @losers, 'query {
|
||||
j
|
||||
($1=$4,"foo"=$3,$5=x,3=$6)
|
||||
{
|
||||
s ("a",*,1) foo
|
||||
|
||||
bar
|
||||
}';
|
||||
#
|
||||
# insert tests
|
||||
#
|
||||
|
||||
push @winners, 'insert foo (a,"1",1)';
|
||||
push @winners, 'insert foo (a,"`1234567890-=~!@#$%^&*()+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;\\\'ASDFGHJKL:'."\n".'zxcvbnm,./ZXCVBNM<>?",1)';
|
||||
|
||||
push @winners, 'delete foo (a,"1",1)';
|
||||
push @winners, 'delete foo (a,"`1234567890-=~!@#$%^&*()+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;\\\'ASDFGHJKL:'."\n".'zxcvbnm,./ZXCVBNM<>?",1)';
|
||||
|
||||
push @losers, 'delete foo (string,"1",1)';
|
||||
push @losers, 'delete foo (int,"`1234567890-=~!@#$%^&*()+qwertyuiop[]\QWERTYUIOP{}|asdfghjkl;\\\'ASDFGHJKL:'."\n".'zxcvbnm,./ZXCVBNM<>?",1)';
|
||||
|
||||
push @winners, 'create foo (int, string, int)';
|
||||
push @losers, 'create foo';
|
||||
push @losers, 'create foo (int, string, "char")';
|
||||
|
||||
push @winners, 'create foo (int, string)|(string, int)';
|
||||
|
||||
|
||||
|
||||
foreach my $q (@winners) {
|
||||
open TST, "| ./parser";
|
||||
print TST $q;
|
||||
if(!close TST) {
|
||||
# command failed:
|
||||
print "unexpected fail: $q\n";
|
||||
$fail ++;
|
||||
}
|
||||
}
|
||||
foreach my $q (@losers) {
|
||||
open TST, "| ./parser";
|
||||
print TST $q;
|
||||
if(close TST) {
|
||||
# command succeeded:
|
||||
print "unexpected pass: $q\n";
|
||||
$fail ++;
|
||||
}
|
||||
}
|
||||
if($fail) {
|
||||
exit(1);
|
||||
}
|
|
@ -1,26 +1,48 @@
|
|||
query
|
||||
query TABLES
|
||||
query {s (1) TABLES}
|
||||
query {s ($1) TABLES}
|
||||
query {s ($1=TABLES) TABLES}
|
||||
query {s ($0=TABLES) TABLES}
|
||||
query {s ($0="TABLES") TABLES}
|
||||
query {s ($1="TABLES") TABLES}
|
||||
query {s (TABLES,*,*,*) TABLES}
|
||||
query {s (TABLES,*,*,*,*) TABLES}
|
||||
query {p (1,2,3,4) TABLES}
|
||||
query {p ($1,$2,$3,$4) TABLES}
|
||||
query {p (0,1,2,3) TABLES}
|
||||
query {p ($0,$1,$2,$3) TABLES}
|
||||
query {p ($0,$1,$2,$100) TABLES}
|
||||
query {p (0,0,0,0) TABLES}
|
||||
query {p (0,1,2,3,0,1,2,3,0) TABLES}
|
||||
query {p ($0,$0,$0,$0) TABLES}
|
||||
query {p ($0,$1,$2,$3,$0,$1,$2,$3,$0) TABLES}
|
||||
query {p (0,1,2,3,0,1,2,3,0) xxx}
|
||||
query {p ($0,$1,$2,$3,$0,$1,$2,$3,$0) xxx}
|
||||
query {p (0) xxx}
|
||||
query {p ($0) xxx}
|
||||
query {s (*) xxx}
|
||||
query {s () xxx}
|
||||
query {s () TABLES}
|
||||
query {j (1=1) xxx yyy}
|
||||
query {j ($1=$1) xxx yyy}
|
||||
query {p (a,b,c) TABLES}
|
||||
query {p (0,1,2) TABLES}
|
||||
query {p ($0,$1,$2) TABLES}
|
||||
query {s () TABLES}
|
||||
query {p () TABLES}
|
||||
query {s () {p () TABLES} }
|
||||
query {j () TABLES TABLES}
|
||||
query {j ($0=$0) TABLES TABLES}
|
||||
query {j (0=0) TABLES TABLES}
|
||||
query {j (0=1) TABLES TABLES}
|
||||
query {j (0=0,1=1) TABLES TABLES}
|
||||
query {j ($0=$0,$1=$1) TABLES TABLES}
|
||||
query {j (0=0,1=2) TABLES TABLES}
|
||||
query {j ($0=$0,$1=$2) TABLES TABLES}
|
||||
query {j ($0=$0,$1=$100) TABLES TABLES}
|
||||
query {j (0<0) TABLES TABLES}
|
||||
query {j ($0<$0) TABLES TABLES}
|
||||
query {x y z}
|
||||
create foo
|
||||
insert foo bar
|
||||
|
||||
|
|
|
@ -12,8 +12,14 @@
|
|||
#include <stasis/transactional.h>
|
||||
|
||||
#include "algebra.h"
|
||||
#include "tuple.h"
|
||||
#include "ddl.h"
|
||||
#include "dml.h"
|
||||
|
||||
|
||||
#include "lang/ast.h"
|
||||
//XXX#include "lang/context.h"
|
||||
|
||||
#define MAX_CONN_QUEUE 10
|
||||
#define THREAD_POOL 20
|
||||
#define SHUTDOWN_SERVER 1
|
||||
|
@ -36,6 +42,8 @@ char interpreterStates[THREAD_POOL];
|
|||
pthread_t interpreters[THREAD_POOL];
|
||||
FILE * interpreterConnections[THREAD_POOL];
|
||||
|
||||
ReferentialAlgebra_context_t * context;
|
||||
|
||||
int openInterpreter(FILE * in, FILE * out, recordid hash);
|
||||
|
||||
void * interpreterThread(void * arg) {
|
||||
|
@ -112,7 +120,7 @@ int openInterpreter(FILE * in, FILE * out, recordid hash) {
|
|||
AUTOCOMMIT = 1;
|
||||
Tcommit(xid);
|
||||
}
|
||||
} else if(!strncmp(line+1,"parseTuple",strlen("parseToken"))) {
|
||||
/* } else if(!strncmp(line+1,"parseTuple",strlen("parseToken"))) {
|
||||
char * c = line + 1 + strlen("parseToken");
|
||||
char ** toks = parseTuple(&c);
|
||||
for(int i = 0; toks[i]; i++) {
|
||||
|
@ -123,7 +131,7 @@ int openInterpreter(FILE * in, FILE * out, recordid hash) {
|
|||
strlen("parseExpression"))) {
|
||||
char * c = line + 1 + strlen("parseExpression");
|
||||
lladdIterator_t * it = parseExpression(xid, hash, &c);
|
||||
it = 0;
|
||||
it = 0; */
|
||||
} else if(!strncmp(line+1,"exit",strlen("exit"))) {
|
||||
break;
|
||||
} else if(!strncmp(line+1,"shutdown",strlen("shutdown"))) {
|
||||
|
@ -131,63 +139,51 @@ int openInterpreter(FILE * in, FILE * out, recordid hash) {
|
|||
break;
|
||||
}
|
||||
} else {
|
||||
if(!strncmp(line,"create",strlen("create"))) {
|
||||
|
||||
char * linecopy = strdup(line+strlen("create"));
|
||||
char * strtoks;
|
||||
char * tablename = strtok_r(linecopy, " \r\n",&strtoks);
|
||||
size_t sz;
|
||||
byte* delme;
|
||||
|
||||
if(AUTOCOMMIT) xid = Tbegin();
|
||||
|
||||
if(-1 == (sz=ThashLookup(xid, hash, (byte*)tablename,strlen(tablename)+1,&delme))) {
|
||||
fprintf(out, "Creating table %s\n", tablename);
|
||||
recordid newHash = ThashCreate(xid, VARIABLE_LENGTH, VARIABLE_LENGTH);
|
||||
char * tpl = tplRid(newHash);
|
||||
char * insert;
|
||||
asprintf(&insert, "insert TABLES %s,%s\n", tablename, tpl);
|
||||
|
||||
executeInsert(xid, hash, insert);
|
||||
|
||||
free(insert);
|
||||
free(tpl);
|
||||
} else {
|
||||
fprintf(out, "Table already exists: %s\n", tablename);
|
||||
free(delme);
|
||||
// assert(sz == sizeof(recordid));
|
||||
}
|
||||
|
||||
if(AUTOCOMMIT) Tcommit(xid);
|
||||
|
||||
free(linecopy);
|
||||
} else if(!strncmp(line,"query",strlen("query"))) {
|
||||
char * linecopy = strdup(line+strlen("query"));
|
||||
|
||||
char ** result = executeQuery(xid, hash, linecopy);
|
||||
|
||||
int i = 0;
|
||||
if(result) {
|
||||
while(result[i]) {
|
||||
fprintf(out, "%s\n", result[i]);
|
||||
free(result[i]);
|
||||
i++;
|
||||
expr_list * results = 0;
|
||||
parse(line, &results);
|
||||
for(int i = 0; results && i < results->count; i++) {
|
||||
expr * e = results->ents[i];
|
||||
switch(e->typ) {
|
||||
case query_typ: {
|
||||
lladdIterator_t * it = ReferentialAlgebra_ExecuteQuery(xid, context, e->u.q);
|
||||
if(it) {
|
||||
while(Titerator_next(xid,it)) {
|
||||
byte * tup;
|
||||
Titerator_value(xid,it, &tup);
|
||||
char * tupleString = stringTuple(*(tuple_t*)tup);
|
||||
fprintf(out, "%s\n", tupleString);
|
||||
free(tupleString);
|
||||
}
|
||||
Titerator_close(xid,it);
|
||||
}
|
||||
free(result);
|
||||
} else {
|
||||
fprintf(out, "query failed\n");
|
||||
} break;
|
||||
case insert_typ: {
|
||||
if(AUTOCOMMIT) { xid = Tbegin(); }
|
||||
ReferentialDML_ExecuteInsert(xid, context, e->u.i);
|
||||
if(AUTOCOMMIT) { Tcommit(xid); xid = -1;}
|
||||
} break;
|
||||
case delete_typ: {
|
||||
if(AUTOCOMMIT) { xid = Tbegin(); }
|
||||
ReferentialDML_ExecuteDelete(xid, context, e->u.d);
|
||||
if(AUTOCOMMIT) { Tcommit(xid); xid = -1;}
|
||||
} break;
|
||||
case create_typ: {
|
||||
if(AUTOCOMMIT) { xid = Tbegin(); }
|
||||
ReferentialDDL_CreateTable(xid, context, e->u.c);
|
||||
if(AUTOCOMMIT) { xid = Tcommit(xid); xid = -1;}
|
||||
} break;
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
free(linecopy);
|
||||
} else if(!strncmp(line,"insert",strlen("insert"))) {
|
||||
if(AUTOCOMMIT) xid = Tbegin();
|
||||
executeInsert(xid, hash, line);
|
||||
if(AUTOCOMMIT) Tcommit(xid);
|
||||
} else if(!strncmp(line,"delete",strlen("delete"))) {
|
||||
if(AUTOCOMMIT) xid = Tbegin();
|
||||
executeDelete(xid, hash, line);
|
||||
if(AUTOCOMMIT) Tcommit(xid);
|
||||
}
|
||||
|
||||
//XXX typecheck(context, results);
|
||||
if(results) {
|
||||
char * str = pp_expr_list(results);
|
||||
printf("%s", str);
|
||||
free(str);
|
||||
} else {
|
||||
fprintf(out, "I don't understand...\n");
|
||||
printf("No results\n");
|
||||
}
|
||||
}
|
||||
fprintf(out, "> ");
|
||||
|
@ -318,14 +314,10 @@ int main(int argc, char * argv[]) {
|
|||
assert(rootEntry.page == ROOT_RECORD.page);
|
||||
assert(rootEntry.slot == ROOT_RECORD.slot);
|
||||
|
||||
hash = ThashCreate(xid, VARIABLE_LENGTH, VARIABLE_LENGTH);
|
||||
hash = ReferentialAlgebra_allocContext(xid);
|
||||
|
||||
Tset(xid, rootEntry, &hash);
|
||||
|
||||
char * tpl = tplRid(hash);
|
||||
|
||||
ThashInsert(xid,hash,(byte*)"TABLES", strlen("TABLES")+1, (byte*)tpl, strlen(tpl)+1);
|
||||
|
||||
} else {
|
||||
printf("Opened existing store\n");
|
||||
rootEntry.page = ROOT_RECORD.page;
|
||||
|
@ -333,8 +325,11 @@ int main(int argc, char * argv[]) {
|
|||
rootEntry.size = sizeof(recordid);
|
||||
|
||||
Tread(xid, rootEntry, &hash);
|
||||
|
||||
}
|
||||
|
||||
context = ReferentialAlgebra_openContext(xid,hash);
|
||||
|
||||
Tcommit(xid);
|
||||
|
||||
FILE * in;
|
||||
|
|
249
src/apps/referential/tuple.c
Normal file
249
src/apps/referential/tuple.c
Normal file
|
@ -0,0 +1,249 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
//#include "old_algebra.h"
|
||||
#include "tuple.h"
|
||||
#include "lang/ast.h"
|
||||
|
||||
/*char * tplRid(recordid rid) {
|
||||
char * ret;
|
||||
asprintf(&ret, "%d,%d,%lld", rid.page, rid.slot, (long long)rid.size);
|
||||
return ret;
|
||||
}
|
||||
recordid ridTpl(char * tpl) {
|
||||
int count;
|
||||
char * freeme;
|
||||
char ** tok = split(tpl, &freeme, &count, ", ");
|
||||
recordid ret;
|
||||
errno = 0;
|
||||
assert(count == 3);
|
||||
ret.page = strtol(tok[0],NULL,10);
|
||||
ret.slot = strtol(tok[1],NULL,10);
|
||||
ret.size = strtol(tok[2],NULL,10);
|
||||
if(errno) {
|
||||
perror("Couldn't parse rid");
|
||||
abort();
|
||||
}
|
||||
free(freeme);
|
||||
free(tok);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char ** tplDup(char ** tup) {
|
||||
int i = 0;
|
||||
for(; tup[i]; i++) { } // i = num non-null entries
|
||||
char ** ret = malloc(sizeof(char**) * (i+1));
|
||||
ret[i] = 0;
|
||||
while(i) {
|
||||
i--;
|
||||
ret[i] = strdup(tup[i]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void tplFree(char ** tup) {
|
||||
for(int i = 0; tup[i]; i++) {
|
||||
free(tup[i]);
|
||||
}
|
||||
free(tup);
|
||||
}*/
|
||||
|
||||
tuple_t tupleRid(recordid rid) {
|
||||
tuple_t ret;
|
||||
ret.count = 3;
|
||||
ret.type = malloc(sizeof(datatype_t)*3);
|
||||
ret.col = malloc(sizeof(tuplecol_t)*3);
|
||||
ret.type[0] = int64_typ;
|
||||
ret.type[1] = int64_typ;
|
||||
ret.type[2] = int64_typ;
|
||||
ret.col[0].int64 = rid.page;
|
||||
ret.col[1].int64 = rid.slot;
|
||||
ret.col[2].int64 = rid.size;
|
||||
return ret;
|
||||
}
|
||||
recordid ridTuple(tuple_t tup) {
|
||||
recordid ret = { tup.col[0].int64, tup.col[1].int64, tup.col[2].int64 };
|
||||
return ret;
|
||||
}
|
||||
tuple_t tupleDup(tuple_t tup) {
|
||||
tuple_t ret;
|
||||
ret.count = tup.count;
|
||||
ret.type = malloc(sizeof(*ret.type)*tup.count);
|
||||
ret.col = malloc(sizeof(*ret.col)*tup.count);
|
||||
memcpy(ret.type, tup.type, sizeof(*ret.type)*tup.count);
|
||||
for(col_t i = 0; i < tup.count; i++) {
|
||||
switch(ret.type[i]) {
|
||||
case int64_typ: {
|
||||
ret.col[i].int64 = tup.col[i].int64;
|
||||
} break;
|
||||
case string_typ: {
|
||||
ret.col[i].string = strdup(tup.col[i].string);
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void tupleFree(tuple_t tup) {
|
||||
for(col_t i = 0; i < tup.count; i++) {
|
||||
switch(tup.type[i]) {
|
||||
case int64_typ: {
|
||||
// nop
|
||||
} break;
|
||||
case string_typ: {
|
||||
free(tup.col[i].string);
|
||||
} break;
|
||||
default: abort();
|
||||
}
|
||||
}
|
||||
if(tup.col) { free(tup.col); }
|
||||
if(tup.type) { free(tup.type); }
|
||||
}
|
||||
|
||||
tuple_t tupleAlloc() {
|
||||
tuple_t ret;
|
||||
ret.count = 0;
|
||||
ret.type = 0;
|
||||
ret.col = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
tuple_t tupleCatInt64(tuple_t t, int64_t i) {
|
||||
t.count++;
|
||||
t.type = realloc(t.type,t.count * sizeof(t.type[0]));
|
||||
t.col = realloc(t.col,t.count * sizeof(t.col[0]));
|
||||
t.type[t.count-1] = int64_typ;
|
||||
t.col[t.count-1].int64 = i;
|
||||
return t;
|
||||
}
|
||||
tuple_t tupleCatString(tuple_t t, const char * str) {
|
||||
t.count++;
|
||||
t.type = realloc(t.type,t.count * sizeof(t.type[0]));
|
||||
t.col = realloc(t.col,t.count * sizeof(t.col[0]));
|
||||
t.type[t.count-1] = string_typ;
|
||||
t.col[t.count-1].string = strdup(str);
|
||||
return t;
|
||||
}
|
||||
tuple_t tupleCatCol(tuple_t t, tuple_t src, col_t i) {
|
||||
if(src.type[i] == string_typ) {
|
||||
t = tupleCatString(t, src.col[i].string);
|
||||
} else if (src.type[i] == int64_typ) {
|
||||
t = tupleCatInt64(t, src.col[i].int64);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
tuple_t tupleCatTuple(tuple_t t, tuple_t src) {
|
||||
for(int i = 0; i < src.count; i++) {
|
||||
t = tupleCatCol(t, src, i);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
tuple_t tupleTail(tuple_t src, col_t start_pos) {
|
||||
tuple_t t = tupleAlloc();
|
||||
for(int i = start_pos; i < src.count; i++) {
|
||||
t = tupleCatCol(t, src, i);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
byte * byteTuple(tuple_t t,size_t* s) {
|
||||
byte * b;
|
||||
*s = sizeof(col_t) + t.count * (sizeof(datatype_t));
|
||||
for(col_t i = 0; i<t.count; i++) {
|
||||
(*s)+= (t.type[i] == int64_typ ? sizeof(int64_t)
|
||||
: (strlen(t.col[i].string)+1));
|
||||
}
|
||||
b = malloc(*s);
|
||||
byte * next_b = b;
|
||||
(*(col_t*)next_b) = t.count;
|
||||
next_b += sizeof(col_t);
|
||||
size_t typlen = sizeof(datatype_t)*t.count;
|
||||
memcpy(next_b,t.type,typlen);
|
||||
next_b += typlen;
|
||||
for(col_t i = 0; i<t.count; i++) {
|
||||
if(t.type[i] == int64_typ) {
|
||||
*(int64_t*)next_b = t.col[i].int64;
|
||||
next_b += sizeof(int64_t);
|
||||
} else {
|
||||
assert(t.type[i] == string_typ);
|
||||
size_t len = strlen(t.col[i].string)+1;
|
||||
memcpy(next_b, t.col[i].string, len);
|
||||
next_b += len;
|
||||
}
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
char * stringTuple(tuple_t t) {
|
||||
char * ret = astrncat(0,"(");
|
||||
for(int i = 0; i < t.count; i++) {
|
||||
if(i) { ret = astrncat(ret, ","); }
|
||||
if(t.type[i] == int64_typ) {
|
||||
char * tok;
|
||||
asprintf(&tok,"%lld",(long long)t.col[i].int64);
|
||||
ret = afstrncat(ret,tok);
|
||||
} else if(t.type[i] == string_typ) {
|
||||
ret = astrncat(ret,t.col[i].string);
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
ret = astrncat(ret,")");
|
||||
return ret;
|
||||
}
|
||||
|
||||
tuple_t tupleByte(byte* b) {
|
||||
tuple_t t;
|
||||
t.count = *(col_t*)b;
|
||||
// printf("deserialized size: %d\n", t.count);
|
||||
byte * b_next = b;
|
||||
b_next += sizeof(col_t);
|
||||
size_t typelen = sizeof(datatype_t)*t.count;
|
||||
t.type = malloc(typelen);
|
||||
memcpy(t.type, b_next, typelen);
|
||||
b_next+=typelen;
|
||||
t.col = malloc(sizeof(tuplecol_t)*t.count);
|
||||
for(col_t i = 0; i < t.count; i++) {
|
||||
if(t.type[i] == int64_typ) {
|
||||
t.col[i].int64 = *(int64_t*)b_next;
|
||||
b_next += sizeof(int64_t);
|
||||
} else {
|
||||
size_t len = strlen((char*)b_next)+1;
|
||||
t.col[i].string = malloc(len);
|
||||
strcpy(t.col[i].string,(char*)b_next);
|
||||
b_next += len;
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
tuple_t tupleVal_tuple(val_tuple * v) {
|
||||
tuple_t t = tupleAlloc();
|
||||
|
||||
for(int i = 0; i < v->count; i++) {
|
||||
if(v->ents[i]->typ == string_typ) {
|
||||
t = tupleCatString(t, v->ents[i]->u.str);
|
||||
} else if(v->ents[i]->typ == int64_typ) {
|
||||
t = tupleCatInt64(t, v->ents[i]->u.integ);
|
||||
} else if(v->ents[i]->typ == ident_typ) {
|
||||
abort();
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
tuple_t tupleUnion_typ(union_typ * v) {
|
||||
assert(v->count == 1);
|
||||
tuple_t t = tupleAlloc();
|
||||
typ_tuple * tt = v->ents[0];
|
||||
for(int i = 0; i < tt->count; i++) {
|
||||
assert(tt->ents[i]->typ == typ_typ);
|
||||
t = tupleCatInt64(t, tt->ents[i]->u.type);
|
||||
}
|
||||
return t;
|
||||
}
|
51
src/apps/referential/tuple.h
Normal file
51
src/apps/referential/tuple.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#include "lang/ast.h"
|
||||
|
||||
#ifndef TUPLE_H
|
||||
#define TUPLE_H
|
||||
#include <stasis/transactional.h>
|
||||
#include <ctype.h>
|
||||
|
||||
typedef uint8_t col_t;
|
||||
|
||||
typedef enum {
|
||||
star_typ,
|
||||
ident_typ,
|
||||
int64_typ,
|
||||
string_typ,
|
||||
colint_typ,
|
||||
colstr_typ,
|
||||
typ_typ,
|
||||
} datatype_t;
|
||||
|
||||
|
||||
typedef union {
|
||||
int64_t int64;
|
||||
char * string;
|
||||
} tuplecol_t;
|
||||
typedef struct tuple_t {
|
||||
col_t count;
|
||||
datatype_t * type;
|
||||
tuplecol_t * col;
|
||||
} tuple_t;
|
||||
|
||||
tuple_t tupleRid(recordid rid);
|
||||
recordid ridTuple(tuple_t tpl);
|
||||
|
||||
char * stringTuple(tuple_t);
|
||||
byte * byteTuple(tuple_t,size_t*);
|
||||
tuple_t tupleByte(byte*);
|
||||
|
||||
tuple_t tupleVal_tuple(val_tuple * t);
|
||||
tuple_t tupleUnion_typ(union_typ * t);
|
||||
|
||||
tuple_t tupleDup(tuple_t tup);
|
||||
void tupleFree(tuple_t tup);
|
||||
|
||||
tuple_t tupleAlloc();
|
||||
|
||||
tuple_t tupleCatString(tuple_t t, const char * str);
|
||||
tuple_t tupleCatInt64(tuple_t t, int64_t str);
|
||||
tuple_t tupleCatCol(tuple_t t, tuple_t src, col_t col);
|
||||
tuple_t tupleCatTuple(tuple_t t, tuple_t src);
|
||||
tuple_t tupleTail(tuple_t t, col_t start_pos);
|
||||
#endif //TUPLE_H/
|
Loading…
Reference in a new issue