Skip to content

Commit bb7f53a

Browse files
committed
Add a foreign-table-level option for selecting the target branch
1 parent e8d7046 commit bb7f53a

File tree

6 files changed

+47
-20
lines changed

6 files changed

+47
-20
lines changed

Changelog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
## Updates
88

99
* Add support for new columns and rework others
10+
* Add a foreign-table-level option for selecting the target branch
1011

1112
# Release 1.0.0
1213

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ Now you can start setting up your environment to access git repositories:
4343
commit_date timestamp with time zone
4444
)
4545
SERVER git_fdw_server
46-
OPTIONS (path '/home/franck/rails/.git');
46+
OPTIONS (
47+
path '/home/franck/rails/.git'
48+
branch 'master'
49+
);
4750
CREATE FOREIGN TABLE
4851

4952
franck=# SELECT message, name FROM rails_repository LIMIT 10;
@@ -81,6 +84,7 @@ There are no options that can be passed to a git\_fdw server.
8184
The possible options are:
8285

8386
* `path`: The path of the git repository;
87+
* `branch`: The branch to be used.
8488

8589
## TODO
8690

execution_state.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
typedef struct GitFdwExecutionState
22
{
33
char *path;
4+
char *branch;
45
List *options;
56
git_repository *repo;
67
int passes;

git_fdw.c

Lines changed: 36 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ PG_FUNCTION_INFO_V1(git_fdw_validator);
3838

3939
#define POSTGRES_TO_UNIX_EPOCH_DAYS (POSTGRES_EPOCH_JDATE - UNIX_EPOCH_JDATE)
4040
#define POSTGRES_TO_UNIX_EPOCH_USECS (POSTGRES_TO_UNIX_EPOCH_DAYS * USECS_PER_DAY)
41+
#define DEFAULT_BRANCH "master"
4142

4243
static void gitGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid);
4344
static void gitGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid);
@@ -50,7 +51,7 @@ static void fileReScanForeignScan(ForeignScanState *node);
5051
static void gitEndForeignScan(ForeignScanState *node);
5152

5253
static bool is_valid_option(const char *option, Oid context);
53-
static void gitGetOptions(Oid foreigntableid, char **path, List **other_options);
54+
static void gitGetOptions(Oid foreigntableid, GitFdwPlanState *state, List **other_options);
5455
static void estimate_costs(PlannerInfo *root, RelOptInfo *baserel,
5556
GitFdwPlanState *fdw_private,
5657
Cost *startup_cost, Cost *total_cost);
@@ -75,7 +76,8 @@ Datum git_fdw_handler(PG_FUNCTION_ARGS) {
7576
Datum git_fdw_validator(PG_FUNCTION_ARGS) {
7677
List *options_list = untransformRelOptions(PG_GETARG_DATUM(0));
7778
Oid catalog = PG_GETARG_OID(1);
78-
char *path = NULL;
79+
char *path = NULL;
80+
char *branch = NULL;
7981
List *other_options = NIL;
8082
ListCell *cell;
8183

@@ -116,6 +118,14 @@ Datum git_fdw_validator(PG_FUNCTION_ARGS) {
116118
errmsg("conflicting or redundant options")));
117119
path = defGetString(def);
118120
}
121+
else if (strcmp(def->defname, "branch") == 0)
122+
{
123+
if (branch)
124+
ereport(ERROR,
125+
(errcode(ERRCODE_SYNTAX_ERROR),
126+
errmsg("conflicting or redundant options")));
127+
branch = defGetString(def);
128+
}
119129
else
120130
other_options = lappend(other_options, def);
121131
}
@@ -130,6 +140,7 @@ Datum git_fdw_validator(PG_FUNCTION_ARGS) {
130140
// FIXME: Avoid global variable
131141
// TODO: Find where this variable should go (Plan or Path?)
132142
char * repository_path;
143+
char * repository_branch;
133144

134145
static bool is_valid_option(const char *option, Oid context) {
135146
const struct GitFdwOption *opt;
@@ -142,7 +153,7 @@ static bool is_valid_option(const char *option, Oid context) {
142153
}
143154

144155
// Fetch path and options from the server (only)
145-
static void gitGetOptions(Oid foreigntableid, char **path, List **other_options) {
156+
static void gitGetOptions(Oid foreigntableid, GitFdwPlanState *state, List **other_options) {
146157
ForeignTable *table;
147158
List *options;
148159
ListCell *lc,
@@ -153,24 +164,31 @@ static void gitGetOptions(Oid foreigntableid, char **path, List **other_options)
153164
options = NIL;
154165
options = list_concat(options, table->options);
155166

156-
*path = NULL;
157-
158167
prev = NULL;
159168
foreach(lc, options) {
160169
DefElem *def = (DefElem *) lfirst(lc);
161170

162171
if (strcmp(def->defname, "path") == 0) {
163-
*path = defGetString(def);
172+
state->path = defGetString(def);
164173
options = list_delete_cell(options, lc, prev);
165-
break;
166174
}
175+
176+
if (strcmp(def->defname, "branch") == 0) {
177+
state->branch = defGetString(def);
178+
options = list_delete_cell(options, lc, prev);
179+
}
180+
167181
prev = lc;
168182
}
169183

170-
if (*path == NULL) {
184+
if (state->path == NULL) {
171185
elog(ERROR, "path is required for git_fdw foreign tables (path of the .git repo)");
172186
}
173187

188+
if (state->branch == NULL) {
189+
state->branch = DEFAULT_BRANCH;
190+
}
191+
174192
*other_options = options;
175193
}
176194

@@ -180,7 +198,7 @@ static void gitGetForeignRelSize(PlannerInfo *root, RelOptInfo *baserel, Oid for
180198
// Pass path and options from the options (only the table for now, but
181199
// could be from the server too) into the baserel
182200
fdw_private = (GitFdwPlanState *) palloc(sizeof(GitFdwPlanState));
183-
gitGetOptions(foreigntableid, &fdw_private->path, &fdw_private->options);
201+
gitGetOptions(foreigntableid, fdw_private, &fdw_private->options);
184202
baserel->fdw_private = (void *) fdw_private;
185203
// TODO: We should estimate baserel->rows
186204
}
@@ -219,7 +237,8 @@ static ForeignScan * gitGetForeignPlan(PlannerInfo *root, RelOptInfo *baserel, O
219237
ForeignScan * scan = make_foreignscan(tlist, scan_clauses, scan_relid, NIL, best_path->fdw_private);
220238

221239
//ForeignScan * scan = make_foreignscan(tlist, scan_clauses, scan_relid, NIL, baserel->fdw_private);
222-
repository_path = ((GitFdwPlanState*)scan->fdw_private)->path;
240+
repository_path = ((GitFdwPlanState*)scan->fdw_private)->path;
241+
repository_branch = ((GitFdwPlanState*)scan->fdw_private)->branch;
223242
return scan;
224243
}
225244

@@ -233,8 +252,9 @@ static void gitBeginForeignScan(ForeignScanState *node, int eflags) {
233252
git_oid oid;
234253

235254
festate = (GitFdwExecutionState *) palloc(sizeof(GitFdwExecutionState));
236-
festate->path = repository_path;
237-
festate->repo = NULL;
255+
festate->path = repository_path;
256+
festate->branch = repository_branch;
257+
festate->repo = NULL;
238258
festate->walker = NULL;
239259

240260
node->fdw_state = (void *) festate;
@@ -246,18 +266,17 @@ static void gitBeginForeignScan(ForeignScanState *node, int eflags) {
246266
return;
247267
}
248268

249-
// Read HEAD on master
269+
// Read HEAD on specified branch (DEFAULT_BRANCH by default)
250270
char head_filepath[512];
251271
FILE *head_fileptr;
252272
char head_rev[41];
253273

254274
strcpy(head_filepath, festate->path);
255-
256275
if(strrchr(festate->path, '/') != (festate->path+strlen(festate->path)))
257-
strcat(head_filepath, "/refs/heads/master");
276+
strcat(head_filepath, "/refs/heads/");
258277
else
259-
strcat(head_filepath, "refs/heads/master");
260-
278+
strcat(head_filepath, "refs/heads/");
279+
strcat(head_filepath, festate->branch);
261280

262281
if((head_fileptr = fopen(head_filepath, "r")) == NULL){
263282
elog(ERROR, "Error opening '%s'\n", head_filepath);

options.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ struct GitFdwOption {
55

66
// Only allow setting the repository's path
77
static const struct GitFdwOption valid_options[] = {
8-
{"path", ForeignTableRelationId},
9-
{NULL, InvalidOid}
8+
{"path", ForeignTableRelationId, false},
9+
{"branch", ForeignTableRelationId, false},
10+
{NULL, InvalidOid, false}
1011
};

plan_state.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
typedef struct GitFdwPlanState
22
{
33
char *path;
4+
char *branch;
45
List *options;
56
BlockNumber pages;
67
double ntuples;

0 commit comments

Comments
 (0)