Skip to content

Commit

Permalink
select with no filter
Browse files Browse the repository at this point in the history
  • Loading branch information
takanoriyanagitani committed Dec 29, 2020
1 parent c984c3c commit b9e206c
Show file tree
Hide file tree
Showing 15 changed files with 341 additions and 11 deletions.
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@ cmake_minimum_required(VERSION 3.0)

project(dir_fdw)

if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release")
endif()

set(CMAKE_C_FLAGS_RELEASE "-O3")
set(CMAKE_C_FLAGS_DEBUG "-O0 -g -coverage")

add_compile_options(
-mavx2
-ftree-vectorize
Expand Down
28 changes: 28 additions & 0 deletions d_begin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#pragma once

static void dir_fdw_begin(ForeignScanState* f, int eflags){
switch(eflags & EXEC_FLAG_EXPLAIN_ONLY){
case 0: break;
default: return;
}

DirFdwExecState* e = palloc(sizeof(DirFdwExecState));
f->fdw_state = e;

DirFdwOption o = {0};
dir_fdw_options(RelationGetRelid(f->ss.ss_currentRelation), &o);
switch(NULL==o.dirname){
case false: break;
default:
elog(ERROR, "Invalid dirname.");
return;
}

e->dirname = pstrdup(o.dirname);
e->d = AllocateDir(e->dirname);
switch(NULL == e->d){
case false: return;
default: break;
}
elog(ERROR, "Unable to get fd.");
}
10 changes: 10 additions & 0 deletions d_end.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

static void dir_fdw_end(ForeignScanState* f){
DirFdwExecState* e = f->fdw_state;
switch(FreeDir(e->d)){
case 0: return;
default: break;
}
elog(WARNING, "Unable to free dir.");
}
27 changes: 27 additions & 0 deletions d_explain.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once

#include <commands/explain.h>
#include <utils/rel.h>

#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>

static void dir_fdw_explain(ForeignScanState* f, ExplainState* e){
DirFdwOption o = {0};
dir_fdw_options(RelationGetRelid(f->ss.ss_currentRelation), &o);
ExplainPropertyText("Foreign dirname", o.dirname, e);

switch(!! e->costs){
case false: return;
default: break;
}

struct stat s = {0};
switch(stat(o.dirname, &s)){
case -1: return;
default: break;
}
ExplainPropertyInteger("Foreign dir size", "b", s.st_size, e);
}
18 changes: 18 additions & 0 deletions d_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,26 @@

#include <foreign/fdwapi.h>

#include "d_relsize.h"
#include "d_path.h"
#include "d_plan.h"
#include "d_explain.h"
#include "d_begin.h"
#include "d_iterate.h"
#include "d_rescan.h"
#include "d_end.h"

Datum dir_fdw_handler(PG_FUNCTION_ARGS){
FdwRoutine* r = makeNode(FdwRoutine);

r->GetForeignRelSize = dir_fdw_relsize;
r->GetForeignPaths = dir_fdw_path;
r->GetForeignPlan = dir_fdw_plan;
r->ExplainForeignScan = dir_fdw_explain;
r->BeginForeignScan = dir_fdw_begin;
r->IterateForeignScan = dir_fdw_iterate;
r->ReScanForeignScan = dir_fdw_rescan;
r->EndForeignScan = dir_fdw_end;

PG_RETURN_POINTER(r);
}
52 changes: 52 additions & 0 deletions d_iterate.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

static Datum b2pgb8(const void* bytes){
static const uint16_t bufsz = 256;
int sz = bufsz + VARHDRSZ;
bytea* ba = palloc(sz);
memcpy(VARDATA(ba), bytes, bufsz);
SET_VARSIZE(ba, sz);
return PointerGetDatum(ba);
}

static TupleTableSlot* dir_fdw_iterate(ForeignScanState* f){
DirFdwExecState* e = f->fdw_state;
TupleTableSlot* s = f->ss.ss_ScanTupleSlot;

TupleDesc t = s->tts_tupleDescriptor;
int n = t->natts;

ExecClearTuple(s);

switch(n){
case 3: break;
default:
return s;
}

switch(NULL == e->dirname){
case false: break;
default:
elog(ERROR, "invalid dirname.");
return s;
}

struct dirent* d = ReadDir(e->d, e->dirname);
switch(NULL == d){
case true: return s;
default: break;
}

Datum* values = s->tts_values;
bool* nulls = s->tts_isnull;

values[0] = d->d_ino;
values[1] = UInt8GetDatum(d->d_type);
values[2] = b2pgb8(d->d_name);
nulls[0] = false;
nulls[1] = false;
nulls[2] = false;
ExecStoreVirtualTuple(s);

return s;
}
31 changes: 31 additions & 0 deletions d_options.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <foreign/foreign.h>
#include <commands/defrem.h>

typedef struct DirFdwOption {
const char* dirname;
char filter;
} DirFdwOption;

static void dir_fdw_options(Oid tableid, DirFdwOption* o){
ForeignTable* t = GetForeignTable(tableid);
ListCell* i = NULL;
//char* filter = NULL;

foreach(i, t->options){
DefElem* d = lfirst(i);
switch(d->defname[0]){
case 'd':
o->dirname = defGetString(d);
break;
/*
case 'f':
filter = defGetString(d);
o->filter = NULL == filter ? '\0' : filter[0];
break;
*/
default: continue;
}
}
}
33 changes: 33 additions & 0 deletions d_path.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <optimizer/paths.h>
#include <optimizer/pathnode.h>

static void dir_fdw_estimate_cost(
PlannerInfo* p, RelOptInfo* r, DirFdwPlanState* s, Cost* c, Cost* t
){
Cost cpu = cpu_tuple_cost * 10 + r->baserestrictcost.per_tuple;
Cost run = seq_page_cost * s->pages;
run += cpu * s->ntup;
*c = r->baserestrictcost.startup;
*t = *c + run;
}

static void dir_fdw_path(PlannerInfo* p, RelOptInfo* r, Oid o){
DirFdwPlanState* s = r->fdw_private;
Cost start;
Cost total;
dir_fdw_estimate_cost(p, r, s, &start, &total);
add_path(r, (Path*)create_foreignscan_path(
p,
r,
NULL, // default pathtarget
r->rows,
start,
total,
NIL, // no pathkeys
r->lateral_relids,
NULL, // no extra plan
NIL //
));
}
24 changes: 24 additions & 0 deletions d_plan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#pragma once

#include <optimizer/planmain.h>

static ForeignScan* dir_fdw_plan(
PlannerInfo* p,
RelOptInfo* r,
Oid o,
ForeignPath* f,
List* l,
List* s,
Plan* outer
){
return make_foreignscan(
l,
s,
r->relid,
NIL, // no expressions to evaluate
f->fdw_private,
NIL, // no custom tlist
NIL, // no remote quals
outer
);
}
42 changes: 42 additions & 0 deletions d_relsize.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#pragma once

#include <optimizer/optimizer.h>

static double dir_fdw_estimate(
PlannerInfo* p, RelOptInfo* r, DirFdwPlanState* s
){
BlockNumber pages = 8;
s->pages = pages;
for(; r && 0 <= r->tuples && 0 < r->pages;){
double density = (double)r->tuples / (double)r->pages;
s->ntup = clamp_row_est(density * (double)pages);
break;
}
for(; NULL == r || r->tuples < 0 || r->pages <= 0;){
int w =
MAXALIGN(r->reltarget->width) + MAXALIGN(SizeofHeapTupleHeader);
s->ntup = clamp_row_est((double) BLCKSZ * 10.0 / (double)w);
break;
}
double nrow = s->ntup * clauselist_selectivity(
p,
r->baserestrictinfo,
0,
JOIN_INNER,
NULL
);
return clamp_row_est(nrow);
}

static void dir_fdw_relsize(PlannerInfo* p, RelOptInfo* r, Oid o){
DirFdwPlanState* s = palloc(sizeof(DirFdwPlanState));
r->fdw_private = s;
dir_fdw_options(o, &s->options);
r->rows = dir_fdw_estimate(p, r, s);
switch(NULL == s->options.dirname){
case false: return;
default:
elog(ERROR, "invalid dirname.");
return;
}
}
10 changes: 10 additions & 0 deletions d_rescan.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

static void dir_fdw_rescan(ForeignScanState* f){
DirFdwExecState* e = f->fdw_state;
switch(NULL == e->d){
case true: return;
default: break;
}
rewinddir(e->d);
}
14 changes: 14 additions & 0 deletions d_state.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma once

typedef struct DirFdwPlanState {
DirFdwOption options;

BlockNumber pages;
double ntup;
} DirFdwPlanState;

typedef struct DirFdwExecState {
const char* dirname;
int fd;
DIR* d;
} DirFdwExecState;
36 changes: 36 additions & 0 deletions d_validator.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,43 @@
#include <postgres.h>

#include <foreign/fdwapi.h>
#include <access/reloptions.h>
#include <commands/defrem.h>
#include <catalog/pg_foreign_table.h>

Datum dir_fdw_validator(PG_FUNCTION_ARGS){
Datum arr = PG_GETARG_DATUM(0);
Oid oid = PG_GETARG_OID(1);
List* lst = untransformRelOptions(arr);
ListCell* i = NULL;

const char* dirname = NULL;

foreach(i, lst){
DefElem* d = (DefElem*) lfirst(i);
const char* optname = d->defname;
switch(optname[0]){
case 'd':
dirname = defGetString(d);
break;
default:
ereport(ERROR, (
errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
errmsg("invalid option: %s", optname)
));
break;
}
}

switch(ForeignTableRelationId == oid && NULL == dirname){
case true:
ereport(ERROR, (
errcode(ERRCODE_FDW_DYNAMIC_PARAMETER_VALUE_NEEDED),
errmsg("dirname required.")
));
break;
default: break;
}

PG_RETURN_VOID();
}
3 changes: 3 additions & 0 deletions dir_fdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@ PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(dir_fdw_handler);
PG_FUNCTION_INFO_V1(dir_fdw_validator);

#include "d_options.h"
#include "d_state.h"

#include "d_validator.h"
#include "d_handler.h"
17 changes: 6 additions & 11 deletions dir_fdw.test.sql
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,13 @@ CREATE SERVER IF NOT EXISTS dsv FOREIGN DATA WRAPPER dir_fdw;

CREATE FOREIGN TABLE IF NOT EXISTS dt(
d_ino BIGINT,
d_type CHAR,
d_name bytea,
d_mode BIGINT,
d_nlink INTEGER,
d_user BIGINT,
d_group BIGINT,
d_size BIGINT,
d_bsize BIGINT,
d_bcnt BIGINT
) SERVER dsv;
d_type SMALLINT,
d_name TEXT
) SERVER dsv OPTIONS(
dirname '/home'
);

--SELECT * FROM dt WHERE k='hw';
SELECT * FROM dt;

DROP FOREIGN TABLE dt;
DROP SERVER dsv;
Expand Down

0 comments on commit b9e206c

Please sign in to comment.